Advertisement
scriptz-team

[PYTHON] QMAiL REPAiR QUEUE

Apr 29th, 2012
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.63 KB | None | 0 0
  1. #!/usr/bin/python
  2. '''queue_repair.py - qmail tools.
  3.  
  4. '''
  5.  
  6. __version__ = '0.9.0'
  7. __author__ = 'xXx'
  8.  
  9. import sys
  10. import os
  11. from stat import *
  12. import string
  13. import pwd
  14. import grp
  15. import getopt
  16.  
  17.  
  18. #######################################
  19. # globals
  20. #######################################
  21.  
  22. confqmail = '/var/qmail'
  23. wd = None
  24. testmode = 1
  25. checked_dir = {}
  26. checked_owner = {}
  27. checked_mode = {}
  28.  
  29.  
  30. #######################################
  31. # data
  32. #######################################
  33.  
  34. users = {
  35. 'alias' : None,
  36. 'qmaild' : None,
  37. 'qmaill' : None,
  38. 'qmailp' : None,
  39. 'qmailq' : None,
  40. 'qmailr' : None,
  41. 'qmails' : None,
  42. }
  43.  
  44. groups = {
  45. 'qmail' : None,
  46. 'nofiles' : None,
  47. }
  48.  
  49. dirs = {
  50. # Directories to check; format is:
  51. # key: pathname - all paths are relative to conf-qmail
  52. # data: (user, group, mode, split)
  53. # split is: 0 : no, 1 : yes, -1 : only with big-todo
  54. 'queue' : ('qmailq', 'qmail', 0750, 0),
  55. 'queue/bounce' : ('qmails', 'qmail', 0700, 0),
  56. 'queue/info' : ('qmails', 'qmail', 0700, 1),
  57. 'queue/intd' : ('qmailq', 'qmail', 0700, -1),
  58. 'queue/local' : ('qmails', 'qmail', 0700, 1),
  59. 'queue/lock' : ('qmailq', 'qmail', 0750, 0),
  60. 'queue/mess' : ('qmailq', 'qmail', 0750, 1),
  61. 'queue/pid' : ('qmailq', 'qmail', 0700, 0),
  62. 'queue/remote' : ('qmails', 'qmail', 0700, 1),
  63. 'queue/todo' : ('qmailq', 'qmail', 0750, -1),
  64. }
  65.  
  66. nondirs = {
  67. # Files to check; format is:
  68. # key: pathname - all paths are relative to conf-qmail
  69. # data: (user, group, mode)
  70. 'queue/lock/sendmutex' : ('qmails', 'qmail', 0600),
  71. 'queue/lock/tcpto' : ('qmailr', 'qmail', 0644),
  72. }
  73.  
  74.  
  75. #######################################
  76. # functions
  77. #######################################
  78.  
  79. #######################################
  80. def primes(min, max):
  81. '''primes(min, max)
  82.  
  83. Return a list of primes between min and max inclusive.
  84. '''
  85. result = []
  86. primelist = [2]
  87. if min <= 2:
  88. result.append(2)
  89. i = 3
  90. while i <= max:
  91. for p in primelist:
  92. if (i % p == 0) or (p * p > i): break
  93. if (i % p <> 0):
  94. primelist.append(i)
  95. if i >= min:
  96. result.append(i)
  97. i = i + 2
  98. return result
  99.  
  100. #######################################
  101. def err(s, showhelp=0):
  102. '''err(s, showhelp=0)
  103.  
  104. Write s + '\n' to stderr, optionally call show_help(), and exit.
  105. '''
  106. sys.stderr.write('%s\n' % s)
  107. if showhelp:
  108. show_help()
  109. if wd:
  110. os.chdir(wd)
  111. sys.exit(1)
  112.  
  113. #######################################
  114. def msg(s):
  115. '''msg(s)
  116.  
  117. Write s + '\n' to stdout.
  118. '''
  119. sys.stdout.write('%s\n' % s)
  120.  
  121. #######################################
  122. def is_splitdir(is_split, bigtodo):
  123. '''is_splitdir(is_split, bigtodo)
  124.  
  125. Return 0 if directory should not contain split subdirectories, 1 if it
  126. should.
  127. '''
  128. return (is_split == 1) or (is_split == -1 and bigtodo)
  129.  
  130. #######################################
  131. def determine_users():
  132. '''determine_users()
  133.  
  134. Look up UIDs and GIDs for all keys in globals users and groups which are
  135. not already set.
  136. '''
  137. global users, groups
  138. msg('finding qmail UIDs/GIDs...')
  139. us = users.keys()
  140. gs = groups.keys()
  141. for u in us:
  142. if users[u]:
  143. # Handle case of someone else determining UIDs for us
  144. msg(' %-7s preset as UID %i' % (u, users[u]))
  145. continue
  146. try:
  147. users[u] = pwd.getpwnam(u)[2]
  148. except KeyError:
  149. err('no uid for %s' % u)
  150. msg(' %-7s : UID %i' % (u, users[u]))
  151. for g in gs:
  152. if groups[g]:
  153. # Handle case of someone else determining GIDs for us
  154. msg(' %-7s preset as GID %i' % (g, groups[g]))
  155. continue
  156. try:
  157. groups[g] = grp.getgrnam(g)[2]
  158. except KeyError:
  159. err('no gid for %s' % g)
  160. msg(' %-7s : GID %i' % (g, groups[g]))
  161.  
  162. #######################################
  163. def check_dir(path, user, group, mode):
  164. '''check_dir(path, user, group, mode)
  165.  
  166. Verify path is an existing directory, that it owned by user:group, and
  167. that it has octal mode mode. If testmode is set, create path if it
  168. doesn't exist.
  169. '''
  170. if checked_dir.has_key(path):
  171. return
  172. msg(' checking directory %s...' % path)
  173. if not os.path.exists(path):
  174. msg(' directory %s does not exist' % path)
  175. if not testmode:
  176. os.makedirs(path, mode)
  177. else:
  178. if os.path.islink(path):
  179. msg(' %s is a symlink instead of directory' % path)
  180. if not testmode:
  181. os.unlink(path)
  182. if not os.path.isdir(path):
  183. msg(' %s is not a directory' % path)
  184. if not testmode:
  185. os.unlink(path)
  186. chown(path, user, group)
  187. chmod(path, mode)
  188. checked_dir[path] = None
  189.  
  190. #######################################
  191. def chown(path, user, group):
  192. '''chown(path, user, group)
  193.  
  194. Verify path is owned by user:group, and make it so if testmode is not set.
  195. '''
  196. if checked_owner.has_key(path):
  197. return
  198. uid = users[user]
  199. gid = groups[group]
  200. try:
  201. s = os.stat(path)
  202. if s[ST_UID] != uid or s[ST_GID] != gid:
  203. msg(' %s ownership %i:%i, should be %s:%s' % (path,
  204. s[ST_UID], s[ST_GID], user, group))
  205. if not testmode:
  206. os.chown(path, uid, gid)
  207. s = os.stat(path)
  208. msg(' fixed, %s ownership %i:%i' % (path, s[ST_UID], s[ST_GID]))
  209. else:
  210. msg(' testmode, not fixing')
  211. except OSError, o:
  212. err(o or '[no error message]')
  213. checked_owner[path] = None
  214.  
  215. #######################################
  216. def chmod(path, mode):
  217. '''chmod(path, mode)
  218.  
  219. Verify path has mode mode, and make it so if testmode is not set.
  220. '''
  221. if checked_mode.has_key(path):
  222. return
  223. try:
  224. s = os.stat(path)
  225. curmode = S_IMODE(s[ST_MODE])
  226. if curmode != mode:
  227. msg(' %s is mode %o, should be %o' % (path, curmode, mode))
  228. if not testmode:
  229. os.chmod(path, mode)
  230. s = os.stat(path)
  231. newmode = S_IMODE(s[ST_MODE])
  232. msg(' changed %s mode to %o' % (path, newmode))
  233. else:
  234. msg(' testmode, not fixing')
  235. except OSError, o:
  236. err(o or '[no error message]')
  237. checked_mode[path] = None
  238.  
  239. #######################################
  240. def determine_split():
  241. '''determine_split()
  242.  
  243. Return probable conf-split value of queue based on contents.
  244. '''
  245. splits = []
  246. msg('determining conf-split...')
  247. for (path, (user, group, mode, is_split)) in dirs.items():
  248. if is_split != 1:
  249. continue
  250. highest = 0
  251. contents = os.listdir(path)
  252. for item in contents:
  253. p = os.path.join(path, item)
  254. if os.path.islink(p):
  255. msg(' found unexpected symlink %s' % p)
  256. continue
  257. if not os.path.isdir(p):
  258. msg(' found unexpected non-directory %s' % p)
  259. continue
  260. try:
  261. i = int(item)
  262. except ValueError:
  263. msg(' found unexpected directory %s' % p)
  264. continue
  265. if i > highest:
  266. highest = i
  267. splits.append(highest)
  268. split = splits[0]
  269. for i in splits[1:]:
  270. if i != split:
  271. err(' not all subdirectories split the same; use --split N to force')
  272. # First split directory is '0'
  273. split = split + 1
  274. msg(' conf-split appears to be %i' % split)
  275. return split
  276.  
  277. #######################################
  278. def determine_bigtodo(split):
  279. '''determine_bigtodo(split)
  280.  
  281. Return 1 if big-todo appears to be in use based on contents of queue,
  282. 0 otherwise.
  283. '''
  284. splits = []
  285. bigtodo = 0
  286. msg('determining big-todo...')
  287. for i in range(split):
  288. p = os.path.join('queue/todo', str(i))
  289. if os.path.islink(p):
  290. msg(' found unexpected symlink %s' % p)
  291. elif os.path.isdir(p):
  292. splits.append(i)
  293. elif not os.path.exists(p):
  294. # big-todo probably not in use
  295. pass
  296. else:
  297. msg(' found unexpected direntry %s' % p)
  298.  
  299. if splits == range(split):
  300. # big-todo apparently in use
  301. bigtodo = 1
  302. msg(' big-todo found')
  303. elif splits:
  304. # big-todo in use, but doesn't match split
  305. err(' todo split != split; if using --split N, use --bigtodo to force')
  306. else:
  307. msg(' big-todo not found')
  308.  
  309. return bigtodo
  310.  
  311. #######################################
  312. def check_dirs(paths, split, bigtodo):
  313. '''check_dirs(paths, split, bigtodo)
  314.  
  315. Verify ownership, mode, and contents of each queue directory in paths.
  316. '''
  317. msg('checking main queue directories...')
  318. _dirs = paths.keys()
  319. _dirs.sort()
  320. for path in _dirs:
  321. (user, group, mode, is_split) = paths[path]
  322. check_dir(path, user, group, mode)
  323.  
  324. msg('checking split sub-directories...')
  325. for (path, (user, group, mode, is_split)) in paths.items():
  326. if path in ('queue', 'queue/lock'):
  327. # Nothing in these directories to check at this point
  328. continue
  329. this_split = is_splitdir(is_split, bigtodo)
  330. if not this_split:
  331. splits = []
  332. else:
  333. splits = range(split)
  334. for i in splits:
  335. splitpath = os.path.join(path, str(i))
  336. check_dir(splitpath, user, group, mode)
  337.  
  338. try:
  339. contents = os.listdir(path)
  340. except OSError:
  341. # Directory missing
  342. if testmode:
  343. continue
  344. err('bug -- directory %s missing, should exist by now' % path)
  345.  
  346. for item in contents:
  347. p = os.path.join(path, item)
  348. if this_split:
  349. if (is_split == -1) and os.path.isfile(p):
  350. # Found possible file in path while converting queue to
  351. # big-todo
  352. try:
  353. i = int(item)
  354. if not testmode:
  355. # Move to '0' split subdirectory; will be
  356. # fixed later by check_hash_and_ownership
  357. new_p = os.path.join(path, '0', item)
  358. msg(' moving %s to %s' % (p, new_p))
  359. os.rename(p, new_p)
  360. except ValueError:
  361. # Not a message file
  362. msg(' found unexpected file %s' % p)
  363. continue
  364. # This directory should contain only split subdirectories
  365. if not os.path.isdir(p):
  366. msg(' found unexpected direntry %s' % p)
  367. continue
  368. try:
  369. i = int(item)
  370. if i not in splits:
  371. msg(' found unexpected split subdirectory %s' % p)
  372. if not testmode:
  373. files = os.listdir(p)
  374. for f in files:
  375. # Move any files in this to-be-remove split subdir
  376. # into the 0 splitdir. Will be moved into the
  377. # proper split subdir later by
  378. # check_hash_and_ownership().
  379. filep = os.path.join(p, f)
  380. msg(' preserving file %s' % filep)
  381. os.rename(filep, os.path.join(path, '0', f))
  382. os.removedirs(p)
  383. except ValueError:
  384. msg(' found unexpected direntry %s' % p)
  385. else:
  386. # This directory should contain only files
  387. if os.path.isdir(p):
  388. msg(' found unexpected directory %s' % p)
  389. try:
  390. i = int(item)
  391. except ValueError:
  392. msg(' %s not a split subdirectory; ignoring' % p)
  393. continue
  394. msg(' %s is a split subdirectory; %s should not be split' % (p, path))
  395. if not testmode:
  396. savefiles = os.listdir(p)
  397. if savefiles:
  398. msg(' moving files from %s to %s' % (p, path))
  399. for f in savefiles:
  400. os.rename(os.path.join(p, f), os.path.join(path, f))
  401. os.rmdir(p)
  402. elif not os.path.isfile(p):
  403. msg(' found unexpected direntry %s; ignoring' % p)
  404. continue
  405. else:
  406. # Found file
  407. pass
  408.  
  409. #######################################
  410. def check_files(paths):
  411. '''check_files(paths)
  412.  
  413. Verify ownership and mode of each queue file in paths.
  414. '''
  415. msg('checking files...')
  416. for (path, (user, group, mode)) in paths.items():
  417. if os.path.exists(path):
  418. if not os.path.isfile(path):
  419. msg(' %s is not a file' % path)
  420. if not testmode:
  421. os.unlink(path)
  422. else:
  423. msg(' file %s does not exist' % path)
  424. if not os.path.exists(path) and not testmode:
  425. open(path, 'w')
  426. chown(path, user, group)
  427. chmod(path, mode)
  428.  
  429. #######################################
  430. def check_trigger():
  431. '''check_trigger()
  432.  
  433. Verify ownership, mode, and inode type of trigger fifo.
  434. '''
  435. path = 'queue/lock/trigger'
  436. user = 'qmails'
  437. group = 'qmail'
  438.  
  439. if not os.path.exists(path):
  440. msg(' %s missing' % path)
  441. else:
  442. if os.path.islink(path):
  443. msg(' %s is a symlink instead of fifo' % path)
  444. if not testmode:
  445. os.unlink(path)
  446. else:
  447. mode = os.stat(path)[ST_MODE]
  448. if not S_ISFIFO(mode):
  449. msg(' %s not a fifo' % path)
  450. if not testmode:
  451. os.unlink(path)
  452. if not os.path.exists(path) and not testmode:
  453. os.mkfifo(path)
  454. chown(path, user, group)
  455. chmod(path, 0622)
  456.  
  457. #######################################
  458. def check_messages(path, split):
  459. '''check_messages(path, split)
  460.  
  461. Return list of files found under path which are not named after their
  462. inode number.
  463. '''
  464. misnamed = []
  465. msg('checking queue/mess files...')
  466. for i in range(split):
  467. messdir = os.path.join(path, str(i))
  468. try:
  469. contents = os.listdir(messdir)
  470. except OSError:
  471. continue
  472. for f in contents:
  473. p = os.path.join(messdir, f)
  474. if os.path.islink(p):
  475. msg(' found unexpected symlink %s' % p)
  476. continue
  477. elif not os.path.isfile(p):
  478. msg(' found unexpected non-file %s' % p)
  479. continue
  480. try:
  481. filenum = int(f)
  482. except ValueError:
  483. msg(' found unexpected file %s' % p)
  484. continue
  485.  
  486. s = os.stat(p)
  487. inode = s[ST_INO]
  488. if filenum == inode:
  489. continue
  490. # Found mess file not named after inode
  491. msg(' %s is inode %i' % (p, inode))
  492. # Will be fixed by fix_inode_names()
  493. misnamed.append((i, filenum, inode))
  494. return misnamed
  495.  
  496. #######################################
  497. def fix_inode_names(paths, split, bigtodo, misnamed):
  498. '''fix_inode_names(paths, split, bigtodo, misnamed)
  499.  
  500. For each path in paths, correct file names based on results of
  501. check_messages(). Correct split sub-directory location as well.
  502. '''
  503. msg('fixing misnamed messages...')
  504. for (path, (user, junk, junk, is_split)) in paths.items():
  505. for (oldhash, oldno, newno) in misnamed:
  506. if not is_splitdir(is_split, bigtodo):
  507. old_p = os.path.join(path, str(oldno))
  508. new_p = os.path.join(path, str(newno))
  509. else:
  510. old_p = os.path.join(path, str(oldhash), str(oldno))
  511. new_p = os.path.join(path, str(newno % split), str(newno))
  512. if os.path.exists(old_p):
  513. if os.path.islink(old_p):
  514. msg(' found unexpected symlink %s' % old_p)
  515. continue
  516. if not os.path.isfile(old_p):
  517. msg(' found unexpected direntry %s' % old_p)
  518. continue
  519. msg(' %s should be %s' % (old_p, new_p))
  520. if not testmode:
  521. os.rename(old_p, new_p)
  522. msg(' fixed')
  523.  
  524. #######################################
  525. def check_hash_and_ownership(paths, split, bigtodo):
  526. '''check_hash_and_ownership(paths, split, bigtodo)
  527.  
  528. For each path in paths, correct file ownership, mode, and split subdirectory
  529. of all files found.
  530. '''
  531. msg('checking split locations...')
  532. for (path, (user, group, junk, is_split)) in paths.items():
  533. if path in ('queue', 'queue/lock'):
  534. # Nothing in these directories to check at this point
  535. continue
  536. elif path in ('queue/mess', 'queue/todo'):
  537. mode = 0644
  538. else:
  539. mode = 0600
  540. this_split = is_splitdir(is_split, bigtodo)
  541. if this_split:
  542. splits = range(split)
  543. else:
  544. splits = ['']
  545. for splitval in splits:
  546. _dir = os.path.join(path, str(splitval))
  547. try:
  548. contents = os.listdir(_dir)
  549. except OSError:
  550. if not testmode:
  551. err('bug -- directory %s missing, should exist by now' % _dir)
  552. continue
  553. for f in contents:
  554. old_p = os.path.join(_dir, f)
  555. try:
  556. if not os.path.isfile(old_p):
  557. raise ValueError
  558. j = int(f)
  559. except ValueError:
  560. msg(' found unexpected direntry %s; ignoring' % old_p)
  561. continue
  562. # Check ownership and mode
  563. chown(old_p, user, group)
  564. chmod(old_p, mode)
  565. if not this_split:
  566. continue
  567. # Check whether file is in correct split sub-directory
  568. hashv = j % split
  569. if hashv != splitval:
  570. # message in wrong split dir
  571. new_p = os.path.join(path, str(hashv), f)
  572. msg(' %s should be %s' % (old_p, new_p))
  573. if not testmode:
  574. os.rename(old_p, new_p)
  575. # Ensure ownership and mode
  576. chown(new_p, user, group)
  577. chmod(new_p, mode)
  578. msg(' fixed')
  579.  
  580. #######################################
  581. def get_current_messages(split):
  582. '''get_current_messages(split)
  583.  
  584. Return list of all message files under queue/mess.
  585. '''
  586. messages = []
  587. msg('finding current messages...')
  588. for i in range(split):
  589. path = os.path.join('queue/mess', str(i))
  590. try:
  591. contents = os.listdir(path)
  592. except OSError:
  593. continue
  594. for item in contents:
  595. try:
  596. messages.append(int(item))
  597. except ValueError:
  598. if testmode:
  599. pass
  600. else:
  601. msg(' found unexpected direntry %s' % os.path.join(path, item))
  602. messages.sort()
  603. msg(' found %i messages' % len(messages))
  604. return messages
  605.  
  606. #######################################
  607. def check_queue(qmaildir=confqmail, test=1, force_split=None, force_bigtodo=None, force_create=0, mathishard=0):
  608. '''check_queue(qmaildir=confqmail, test=1, force_split=None, force_bigtodo=None, force_create=0, mathishard=0)
  609.  
  610. Verify (and correct if test is not set) queue structure rooted at
  611. qmaildir/queue.
  612. Determine conf-split automatically if force_split is not set.
  613. Determine if big-todo is in use automatically if force_bigtodo is not set.
  614. '''
  615. global wd
  616. global testmode
  617. testmode = test
  618. split = None
  619.  
  620. wd = os.getcwd()
  621. try:
  622. os.chdir(qmaildir)
  623. except StandardError:
  624. err('failed to chdir to %s' % qmaildir)
  625.  
  626. if testmode:
  627. msg('running in test-only mode')
  628. else:
  629. msg('running in repair mode')
  630.  
  631. determine_users()
  632.  
  633. if not force_split:
  634. try:
  635. split = determine_split()
  636. except OSError:
  637. msg('basic queue directories not found at %s' % qmaildir)
  638.  
  639. if not split:
  640. if not force_create:
  641. err(' use --create to force creation of queue at %s' % qmaildir)
  642. # --create implies --repair
  643. testmode = 0
  644. if not force_split:
  645. err('if creating a new queue, you must supply a conf-split value with --split')
  646. split = int(force_split)
  647. if split < 1:
  648. err('split must be >= 1')
  649. if not force_bigtodo:
  650. err('if creating a new queue, you must supply either --bigtodo or --no-bigtodo')
  651. msg('using forced conf-split of %i' % split)
  652. msg('creating new queue at %s' % qmaildir)
  653.  
  654. l = int(split * 0.8)
  655. h = int(split * 1.2)
  656. suggested_splits = primes(l, h)
  657. if not split in suggested_splits:
  658. msg('split should be prime, not %i: suggestions %s' % (split, suggested_splits))
  659. if not mathishard and not testmode:
  660. err(' use --i-want-a-broken-conf-split to force non-prime split')
  661.  
  662. if force_bigtodo == 1:
  663. bigtodo = 1
  664. msg('using forced big-todo')
  665. elif force_bigtodo == -1:
  666. bigtodo = 0
  667. msg('using forced non-big-todo')
  668. else:
  669. bigtodo = determine_bigtodo(split)
  670.  
  671. check_dirs(dirs, split, bigtodo)
  672. check_files(nondirs)
  673. check_trigger()
  674.  
  675. misnamed = check_messages('queue/mess', split)
  676.  
  677. # Handle misnamed files in directories
  678. if misnamed:
  679. fix_inode_names(dirs, split, bigtodo, misnamed)
  680.  
  681. # Handle mis-hashed files and bad owner/group/mode
  682. check_hash_and_ownership(dirs, split, bigtodo)
  683.  
  684. #######################################
  685. def show_help():
  686. '''show_help()
  687.  
  688. Display usage information.
  689. '''
  690. msg('\n'
  691. 'Usage: queue_repair.py [options] [conf-qmail]\n')
  692. msg('Options:\n'
  693. ' conf-qmail (default: %s)' % confqmail)
  694. msg(
  695. ' -t or --test Test only; do not modify the filesystem\n'
  696. ' -r or --repair Repair errors found (default: test)\n'
  697. ' -b or --bigtodo Force use of big-todo (default: auto)\n'
  698. ' -n or --no-bigtodo Force non-use of big-todo (default: auto)\n'
  699. ' -s N or --split N Force conf-split of N (default: auto)\n'
  700. ' -c or --create Force creation of queue (default: no)\n'
  701. ' --i-want-a-broken-conf-split Force non-prime conf-split (default: no)\n'
  702. ' -h or --help This text\n'
  703. )
  704.  
  705. #######################################
  706. def main():
  707. '''main()
  708.  
  709. Parse options and call check_queue().
  710. '''
  711. msg('queue_repair.py v. %s\n'
  712. 'Copyright (C) 2001 %s' % (__version__, __author__))
  713. msg('Licensed under the GNU General Public License version 2\n')
  714.  
  715. optionlist = 's:bnrthc'
  716. longoptionlist = ('split=', 'bigtodo', 'no-bigtodo', 'repair', 'test',
  717. 'i-want-a-broken-conf-split', 'help', 'create')
  718. force_split = None
  719. force_bigtodo = None
  720. test = 1
  721. qmaildir = confqmail
  722. mathishard = 0
  723. create = 0
  724.  
  725. try:
  726. options, args = getopt.getopt(sys.argv[1:], optionlist, longoptionlist)
  727.  
  728. for (option, value) in options:
  729. if option in ('-s', '--split'):
  730. try:
  731. force_split = int(value)
  732. if force_split < 1:
  733. raise ValueError
  734. except ValueError:
  735. raise getopt.error, 'split value must be a positive integer (%s)' % value
  736. elif option in ('-n', '--no-bigtodo'):
  737. force_bigtodo = -1
  738. elif option in ('-b', '--bigtodo'):
  739. force_bigtodo = 1
  740. elif option in ('-r', '--repair'):
  741. test = 0
  742. elif option in ('-t', '--test'):
  743. test = 1
  744. elif option == '--i-want-a-broken-conf-split':
  745. mathishard = 1
  746. elif option in ('-h', '--help'):
  747. show_help()
  748. sys.exit(0)
  749. elif option in ('-c', '--create'):
  750. create = 1
  751. if args:
  752. if len(args) > 1:
  753. raise getopt.error, 'conf-qmail must be a single argument (%s)' % string.join(args)
  754. qmaildir = args[0]
  755.  
  756. except getopt.error, o:
  757. err('Error: %s' % o, showhelp=1)
  758.  
  759. check_queue(qmaildir, test, force_split, force_bigtodo, create, mathishard)
  760.  
  761. #######################################
  762. if __name__ == '__main__':
  763. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement