]> code.delx.au - offlineimap/blob - offlineimap/init.py
Instead of blowing up when the account name is missing, display a useful error messag...
[offlineimap] / offlineimap / init.py
1 # OfflineIMAP initialization code
2 # Copyright (C) 2002, 2003 John Goerzen
3 # <jgoerzen@complete.org>
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 from offlineimap import imaplib, imapserver, repository, folder, mbnames, threadutil, version, syncmaster, accounts
20 from offlineimap.localeval import LocalEval
21 from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
22 from offlineimap.ui import UIBase
23 import re, os, os.path, offlineimap, sys
24 from offlineimap.CustomConfig import CustomConfigParser
25 from threading import *
26 import threading
27 from getopt import getopt
28
29 try:
30 import fcntl
31 hasfcntl = 1
32 except:
33 hasfcntl = 0
34
35 lockfd = None
36
37 def lock(config, ui):
38 global lockfd, hasfcntl
39 if not hasfcntl:
40 return
41 lockfd = open(config.getmetadatadir() + "/lock", "w")
42 try:
43 fcntl.flock(lockfd, fcntl.LOCK_EX | fcntl.LOCK_NB)
44 except IOError:
45 ui.locked()
46 ui.terminate(1)
47
48 def startup(versionno):
49 assert versionno == version.versionstr, "Revision of main program (%s) does not match that of library (%s). Please double-check your PYTHONPATH and installation locations." % (versionno, version.versionstr)
50 options = {}
51 if '--help' in sys.argv[1:]:
52 sys.stdout.write(version.cmdhelp + "\n")
53 sys.exit(0)
54
55 for optlist in getopt(sys.argv[1:], 'P:1oa:c:d:l:u:h')[0]:
56 options[optlist[0]] = optlist[1]
57
58 if options.has_key('-h'):
59 sys.stdout.write(version.cmdhelp)
60 sys.stdout.write("\n")
61 sys.exit(0)
62 configfilename = os.path.expanduser("~/.offlineimaprc")
63 if options.has_key('-c'):
64 configfilename = options['-c']
65 if options.has_key('-P'):
66 if not options.has_key('-1'):
67 sys.stderr.write("FATAL: profile mode REQUIRES -1\n")
68 sys.exit(100)
69 profiledir = options['-P']
70 os.mkdir(profiledir)
71 threadutil.setprofiledir(profiledir)
72 sys.stderr.write("WARNING: profile mode engaged;\nPotentially large data will be created in " + profiledir + "\n")
73
74 config = CustomConfigParser()
75 if not os.path.exists(configfilename):
76 sys.stderr.write(" *** Config file %s does not exist; aborting!\n" % configfilename)
77 sys.exit(1)
78
79 config.read(configfilename)
80
81 ui = offlineimap.ui.detector.findUI(config, options.get('-u'))
82 UIBase.setglobalui(ui)
83
84 if options.has_key('-l'):
85 ui.setlogfd(open(options['-l'], 'wt'))
86
87 ui.init_banner()
88
89 if options.has_key('-d'):
90 for debugtype in options['-d'].split(','):
91 ui.add_debug(debugtype.strip())
92 if debugtype == 'imap':
93 imaplib.Debug = 5
94 if debugtype == 'thread':
95 threading._VERBOSE = 1
96
97 if options.has_key('-o'):
98 # FIXME: maybe need a better
99 for section in accounts.getaccountlist(config):
100 config.remove_option('Account ' + section, "autorefresh")
101
102 lock(config, ui)
103
104 if options.has_key('-l'):
105 sys.stderr = ui.logfile
106
107 activeaccounts = config.get("general", "accounts")
108 if options.has_key('-a'):
109 activeaccounts = options['-a']
110 activeaccounts = activeaccounts.replace(" ", "")
111 activeaccounts = activeaccounts.split(",")
112 allaccounts = accounts.AccountHashGenerator(config)
113
114 syncaccounts = {}
115 for account in activeaccounts:
116 if account not in allaccounts:
117 if len(allaccounts) == 0:
118 errormsg = 'The account "%s" does not exist because no accounts are defined!'%account
119 else:
120 errormsg = 'The account "%s" does not exist. Valid accounts are:'%account
121 for name in allaccounts.keys():
122 errormsg += '\n%s'%name
123 ui.terminate(1, errortitle = 'Unknown Account "%s"'%account, errormsg = errormsg)
124 syncaccounts[account] = allaccounts[account]
125
126 server = None
127 remoterepos = None
128 localrepos = None
129
130 if options.has_key('-1'):
131 threadutil.initInstanceLimit("ACCOUNTLIMIT", 1)
132 else:
133 threadutil.initInstanceLimit("ACCOUNTLIMIT",
134 config.getdefaultint("general", "maxsyncaccounts", 1))
135
136 for reposname in config.getsectionlist('Repository'):
137 for instancename in ["FOLDER_" + reposname,
138 "MSGCOPY_" + reposname]:
139 if options.has_key('-1'):
140 threadutil.initInstanceLimit(instancename, 1)
141 else:
142 threadutil.initInstanceLimit(instancename,
143 config.getdefaultint('Repository ' + reposname, "maxconnections", 1))
144
145 threadutil.initexitnotify()
146 t = ExitNotifyThread(target=syncmaster.syncitall,
147 name='Sync Runner',
148 kwargs = {'accounts': syncaccounts,
149 'config': config})
150 t.setDaemon(1)
151 t.start()
152 try:
153 threadutil.exitnotifymonitorloop(threadutil.threadexited)
154 except SystemExit:
155 raise
156 except:
157 ui.mainException() # Also expected to terminate.
158
159