root / pykota / trunk / bin / edpykota @ 1258

Revision 1258, 27.5 kB (checked in by jalet, 20 years ago)

edpykota now supports adding printers to printer groups.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# PyKota Print Quota Editor
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.65  2004/01/08 16:24:49  jalet
27# edpykota now supports adding printers to printer groups.
28#
29# Revision 1.64  2004/01/08 14:10:32  jalet
30# Copyright year changed.
31#
32# Revision 1.63  2003/11/24 16:50:58  jalet
33# Old help message deletedd
34#
35# Revision 1.62  2003/11/12 23:28:38  jalet
36# More work on new backend. This commit may be unstable.
37#
38# Revision 1.61  2003/11/12 13:06:35  jalet
39# Bug fix wrt no user/group name command line argument to edpykota
40#
41# Revision 1.60  2003/10/09 21:25:24  jalet
42# Multiple printer names or wildcards can be passed on the command line
43# separated with commas.
44# Beta phase.
45#
46# Revision 1.59  2003/10/07 09:07:27  jalet
47# Character encoding added to please latest version of Python
48#
49# Revision 1.58  2003/10/03 12:27:01  jalet
50# Several optimizations, especially with LDAP backend
51#
52# Revision 1.57  2003/08/20 16:01:19  jalet
53# Comment added.
54#
55# Revision 1.56  2003/07/29 20:55:17  jalet
56# 1.14 is out !
57#
58# Revision 1.55  2003/07/28 09:11:12  jalet
59# PyKota now tries to add its attributes intelligently in existing LDAP
60# directories.
61#
62# Revision 1.54  2003/07/21 06:32:42  jalet
63# Prevents email messages to be sent at modification/creation time for
64# a user/group quota
65#
66# Revision 1.53  2003/07/09 06:03:41  jalet
67# Fixed typo when using edpykota --prototype
68#
69# Revision 1.52  2003/07/07 12:11:13  jalet
70# Small fix
71#
72# Revision 1.51  2003/07/07 11:55:50  jalet
73# Small fix
74#
75# Revision 1.50  2003/07/05 12:33:53  jalet
76# More on previous fix.
77#
78# Revision 1.49  2003/07/05 12:32:07  jalet
79# Ensure that the user don't pass more than two prices for a printer.
80#
81# Revision 1.48  2003/06/25 19:52:30  jalet
82# Should be ready for testing :-)
83#
84# Revision 1.47  2003/06/25 14:10:01  jalet
85# Hey, it may work (edpykota --reset excepted) !
86#
87# Revision 1.46  2003/06/16 11:59:09  jalet
88# More work on LDAP
89#
90# Revision 1.45  2003/06/11 19:32:00  jalet
91# Severe bug wrt account balance setting should be corrected.
92#
93# Revision 1.44  2003/04/29 22:03:38  jalet
94# Better error handling.
95#
96# Revision 1.43  2003/04/23 22:13:56  jalet
97# Preliminary support for LPRng added BUT STILL UNTESTED.
98#
99# Revision 1.42  2003/04/17 13:38:47  jalet
100# Docstring corrected for better manual page
101#
102# Revision 1.41  2003/04/16 12:35:49  jalet
103# Groups quota work now !
104#
105# Revision 1.40  2003/04/16 08:22:09  jalet
106# More strict error detection.
107# Minor code rewrite to avoid some repetitive tests.
108#
109# Revision 1.39  2003/04/16 08:01:53  jalet
110# edpykota --charge command line option works now.
111#
112# Revision 1.38  2003/04/15 22:02:43  jalet
113# More complete docstring
114#
115# Revision 1.37  2003/04/15 21:58:33  jalet
116# edpykota now accepts a --delete option.
117# Preparation to allow edpykota to accept much more command line options
118# (WARNING : docstring is OK, but code isn't !)
119#
120# Revision 1.36  2003/04/15 13:55:28  jalet
121# Options --limitby and --balance added to edpykota
122#
123# Revision 1.35  2003/04/15 13:06:39  jalet
124# Allow to add a printer without any user
125#
126# Revision 1.34  2003/04/11 16:51:11  jalet
127# Bug fix for edpykota --add with users who already had a quota on the printer.
128#
129# Revision 1.33  2003/04/10 21:47:20  jalet
130# Job history added. Upgrade script neutralized for now !
131#
132# Revision 1.32  2003/04/08 21:31:39  jalet
133# (anything or 0) = anything !!! Go back to school Jerome !
134#
135# Revision 1.31  2003/04/08 21:13:44  jalet
136# Prepare --groups option to work.
137#
138# Revision 1.30  2003/04/08 21:10:18  jalet
139# Checks --groups option presence instead of --users because --users is the default.
140#
141# Revision 1.29  2003/04/05 09:28:56  jalet
142# Unnecessary message was logged
143#
144# Revision 1.28  2003/03/29 13:45:26  jalet
145# GPL paragraphs were incorrectly (from memory) copied into the sources.
146# Two README files were added.
147# Upgrade script for PostgreSQL pre 1.01 schema was added.
148#
149# Revision 1.27  2003/03/10 00:23:04  jalet
150# Bad english
151#
152# Revision 1.26  2003/03/10 00:11:27  jalet
153# Cleaner example.
154#
155# Revision 1.25  2003/03/09 23:56:21  jalet
156# Option noquota added to do accounting only.
157#
158# Revision 1.24  2003/02/27 23:48:41  jalet
159# Correctly maps PyKota's log levels to syslog log levels
160#
161# Revision 1.23  2003/02/27 22:55:20  jalet
162# WARN log priority doesn't exist.
163#
164# Revision 1.22  2003/02/27 09:37:02  jalet
165# Wildcards seem to work now
166#
167# Revision 1.21  2003/02/27 09:04:46  jalet
168# user and group names can be passed as wildcards if the --add option
169# is not set. The default is to act on all users or groups.
170#
171# Revision 1.20  2003/02/10 12:07:30  jalet
172# Now repykota should output the recorded total page number for each printer too.
173#
174# Revision 1.19  2003/02/09 13:40:29  jalet
175# typo
176#
177# Revision 1.18  2003/02/09 12:56:53  jalet
178# Internationalization begins...
179#
180# Revision 1.17  2003/02/08 22:47:23  jalet
181# Option --reset can now be used without having to use soft and hard limits
182# on the command line.
183#
184# Revision 1.16  2003/02/08 22:39:46  jalet
185# --reset command line option added
186#
187# Revision 1.15  2003/02/08 22:20:01  jalet
188# Clarification on why we don't check with /etc/passwd to see if the user
189# name is valid or not.
190#
191# Revision 1.14  2003/02/08 22:18:15  jalet
192# Now checks user and group names for validity before adding them
193#
194# Revision 1.13  2003/02/08 22:09:02  jalet
195# Only printer was added the first time.
196#
197# Revision 1.12  2003/02/08 21:44:49  jalet
198# Python 2.1 string module doesn't define ascii_letters
199#
200# Revision 1.11  2003/02/08 09:42:44  jalet
201# Better handle wrong or bad command line arguments
202#
203# Revision 1.10  2003/02/08 09:39:20  jalet
204# typos
205#
206# Revision 1.9  2003/02/08 09:38:06  jalet
207# Badly placed test
208#
209# Revision 1.8  2003/02/07 22:53:57  jalet
210# Checks if printer name is valid before adding it
211#
212# Revision 1.7  2003/02/07 22:17:58  jalet
213# Incomplete test
214#
215# Revision 1.6  2003/02/07 22:13:13  jalet
216# Perhaps edpykota is now able to add printers !!! Oh, stupid me !
217#
218# Revision 1.5  2003/02/06 14:49:04  jalet
219# edpykota should be ok now
220#
221# Revision 1.4  2003/02/06 14:28:59  jalet
222# edpykota should be ok, minus some typos
223#
224# Revision 1.3  2003/02/06 10:47:21  jalet
225# Documentation string and command line options didn't match.
226#
227# Revision 1.2  2003/02/06 10:39:23  jalet
228# Preliminary edpykota work.
229#
230# Revision 1.1  2003/02/05 21:41:09  jalet
231# Skeletons added for all command line tools
232#
233#
234#
235
236import sys
237
238from pykota import version
239from pykota.tool import PyKotaTool, PyKotaToolError
240from pykota.config import PyKotaConfigError
241from pykota.storage import PyKotaStorageError
242
243__doc__ = """edpykota v%s (c) 2003-2004 C@LL - Conseil Internet & Logiciels Libres
244A Print Quota editor for PyKota.
245
246command line usage :
247
248  edpykota [options] user1 user2 ... userN
249 
250  edpykota [options] group1 group2 ... groupN
251
252options :
253
254  -v | --version       Prints edpykota's version number then exits.
255  -h | --help          Prints this message then exits.
256 
257  -a | --add           Adds users and/or printers if they don't
258                       exist on the Quota Storage Server.
259                       
260  -d | --delete        Deletes users/groups from the quota storage.
261                       Printers are never deleted.
262                       
263  -c | --charge p[,j]  Sets the price per page and per job to charge
264                       for a particular printer. Job price is optional.
265                       If both are to be set, separate them with a comma.
266                       Floating point values are allowed.
267 
268  -i | --ingroups g1[,g2...]  Puts the users into each of the groups
269                              listed, separated by commas. The groups
270                              must already exist in the Quota Storage.
271 
272  -u | --users         Edit users print quotas, this is the default.
273 
274  -P | --printer p     Edit quotas on printer p only. Actually p can
275                       use wildcards characters to select only
276                       some printers. The default value is *, meaning
277                       all printers.
278                       You can specify several names or wildcards,
279                       by separating them with commas.
280 
281  -G | --pgroups pg1[,pg2...] Adds the printer(s) to the printer groups
282                       pg1, pg2, etc... which must already exist.
283                       A printer group is just like a normal printer,
284                       only that it is usually unknown from the printing
285                       system. Create printer groups exactly the same
286                       way that you create printers, then add other
287                       printers to them with this option.
288                       Accounting is done on a printer and on all
289                       the printer groups it belongs to, quota checking
290                       is done on a printer and on all the printer groups
291                       it belongs to.
292 
293  -g | --groups        Edit users groups print quotas instead of users.
294                         
295  -p | --prototype u|g Uses user u or group g as a prototype to set
296                       print quotas
297                       
298  -n | --noquota       Doesn't set a quota but only does accounting.
299 
300  -r | --reset         Resets the printed page counter for the user
301                       or group to zero. The life time page counter
302                       is kept unchanged.
303                       
304  -l | --limitby l     Choose if the user/group is limited in printing                     
305                       by its account balance or by its page quota.
306                       The default value is 'quota'. Allowed values
307                       are 'quota' and 'balance'.
308                       
309  -b | --balance b     Sets the user's account balance to b.                     
310                       Account balance may be increase or decreased
311                       if b is prefixed with + or -.
312                       WARNING : when decreasing account balance,
313                       the total paid so far by the user is decreased
314                       too.
315                       Groups don't have a real balance, but the
316                       sum of their users' account balance.
317                       
318  -S | --softlimit sl  Sets the quota soft limit to sl pages.                       
319 
320  -H | --hardlimit hl  Sets the quota hard limit to hl pages.
321 
322  user1 through userN and group1 through groupN can use wildcards
323  if the --add option is not set.
324 
325examples :                             
326
327  $ edpykota -p jerome john paul george ringo
328 
329  This will set print quotas for the users john, paul, george and ringo
330  to the same values than user jerome. User jerome must exist.
331 
332  $ edpykota --printer lp -S 50 -H 60 jerome
333 
334  This will set jerome's print quota on the lp printer to a soft limit
335  of 50 pages, and a hard limit of 60 pages. If either user jerome or
336  printer lp doesn't exist on the Quota Storage Server then nothing is done.
337
338  $ edpykota --add --printer lp --ingroups coders,it -S 50 -H 60 jerome
339 
340  Same as above, but if either user jerome or printer lp doesn't exist
341  on the Quota Storage Server they are automatically added. Also
342  user jerome is put into the groups "coders" and "it" which must
343  already exist in the Quota Storage.
344           
345  $ edpykota -g -S 500 -H 550 financial support           
346 
347  This will set print quota soft limit to 500 pages and hard limit
348  to 550 pages for groups financial and support on all printers.
349 
350  $ edpykota --reset jerome "jo*"
351 
352  This will reset jerome's page counter to zero on all printers, as
353  well as every user whose name begins with 'jo'.
354  Their life time page counter on each printer will be kept unchanged.
355 
356  $ edpykota --printer hpcolor --noquota jerome
357 
358  This will tell PyKota to not limit jerome when printing on the
359  hpcolor printer. All his jobs will be allowed on this printer, but
360  accounting of the pages he prints will still be kept.
361  Print Quotas for jerome on other printers are unchanged.
362 
363  $ edpykota --limitby balance jerome
364 
365  This will tell PyKota to limit jerome by his account's balance
366  when printing.
367 
368  $ edpykota --balance +10.0 jerome
369 
370  This will increase jerome's account balance by 10.0 (in your
371  own currency). You can decrease the account balance with a
372  dash prefix, and set it to a fixed amount with no prefix.
373 
374  $ edpykota --delete jerome rachel
375 
376  This will completely delete jerome and rachel from the Quota Storage
377  database. All their quotas and jobs will be deleted too.
378 
379  $ edpykota --printer lp --charge 0.1
380 
381  This will set the page price for printer lp to 0.1. Job price
382  will not be changed.
383 
384  $ edpykota --printer hplj1,hplj2 --pgroups Laser,HP
385 
386  This will put printers hplj1 and hplj2 in printers groups Laser and HP.
387  When printing either on hplj1 or hplj2, print quota will also be
388  checked and accounted for on virtual printers Laser and HP.
389
390This program is free software; you can redistribute it and/or modify
391it under the terms of the GNU General Public License as published by
392the Free Software Foundation; either version 2 of the License, or
393(at your option) any later version.
394
395This program is distributed in the hope that it will be useful,
396but WITHOUT ANY WARRANTY; without even the implied warranty of
397MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
398GNU General Public License for more details.
399
400You should have received a copy of the GNU General Public License
401along with this program; if not, write to the Free Software
402Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
403
404Please e-mail bugs to: %s""" % (version.__version__, version.__author__)
405       
406class EdPyKota(PyKotaTool) :       
407    """A class for edpykota."""
408    def main(self, names, options) :
409        """Edit user or group quotas."""
410       
411        suffix = (options["groups"] and "Group") or "User"       
412       
413        softlimit = hardlimit = None   
414        if not options["noquota"] :
415            if options["softlimit"] :
416                try :
417                    softlimit = int(options["softlimit"].strip())
418                except ValueError :   
419                    raise PyKotaToolError, _("Invalid softlimit value %s.") % options["softlimit"]
420            if options["hardlimit"] :
421                try :
422                    hardlimit = int(options["hardlimit"].strip())
423                except ValueError :   
424                    raise PyKotaToolError, _("Invalid hardlimit value %s.") % options["hardlimit"]
425            if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) :       
426                # error, exchange them
427                self.logger.log_message(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit))
428                (softlimit, hardlimit) = (hardlimit, softlimit)
429           
430        balance = options["balance"]
431        if balance :
432            balance = balance.strip()
433            try :
434                balancevalue = float(balance)
435            except ValueError :   
436                raise PyKotaToolError, _("Invalid balance value %s" % options["balance"])
437           
438        if options["charge"] :
439            try :
440                charges = [float(part) for part in options["charge"].split(',', 1)]
441            except ValueError :   
442                raise PyKotaToolError, _("Invalid charge amount value %s" % options["charge"])
443            else :   
444                if len(charges) > 2 :
445                    charges = charges[:2]
446                if len(charges) != 2 :
447                    charges = [charges[0], None]
448                   
449        limitby = options["limitby"]
450        if limitby :
451            limitby = limitby.strip().lower()
452        if limitby and (limitby not in ('quota', 'balance')) :   
453            raise PyKotaToolError, _("Invalid limitby value %s" % options["limitby"])
454           
455        if options["ingroups"] :   
456            groupnames = [gname.strip() for gname in options["ingroups"].split(',')]
457        else :   
458            groupnames = []
459           
460        if options["prototype"] :   
461            protoentry = getattr(self.storage, "get%s" % suffix)(options["prototype"])
462           
463        printeradded = 0
464        printers = self.storage.getMatchingPrinters(options["printer"])
465        if not printers :
466            pname = options["printer"]
467            if options["add"] and pname :
468                if self.isValidName(pname) :
469                    printers = [ self.storage.addPrinter(pname) ]
470                    if printers[0].Exists :
471                        printeradded = 1
472                    else :   
473                        raise PyKotaToolError, _("Impossible to add printer %s") % pname
474                else :   
475                    raise PyKotaToolError, _("Invalid printer name %s") % pname
476            else :
477                raise PyKotaToolError, _("There's no printer matching %s") % pname
478        if not names :   
479            if options["add"] :
480                if not printeradded :
481                    raise PyKotaToolError, _("You have to pass user or group names on the command line")
482                else :   
483                    names = getattr(self.storage, "getAll%ssNames" % suffix)()
484            else :   
485                names = [ "*" ] # all users
486               
487        printersgroups = []       
488        if options["pgroups"] :       
489            printersgroups = self.storage.getMatchingPrinters(options["pgroups"])
490           
491        changed = {} # tracks changes made at the user/group level
492        for printer in printers :
493            for pgroup in printersgroups :
494                pgroup.addPrinterToGroup(printer)   
495               
496            if options["charge"] :
497                (perpage, perjob) = charges
498                printer.setPrices(perpage, perjob)   
499               
500            if options["prototype"] :
501                if protoentry.Exists :
502                    protoquota = getattr(self.storage, "get%sPQuota" % suffix)(protoentry, printer)
503                    if not protoquota.Exists :
504                        self.logger.log_message(_("Prototype %s not found in Quota Storage for printer %s.") % (protoentry.Name, printer.Name))
505                        continue    # skip this printer
506                    else :   
507                        (softlimit, hardlimit) = (protoquota.SoftLimit, protoquota.HardLimit)
508                else :       
509                    self.logger.log_message(_("Prototype object %s not found in Quota Storage.") % protoentry.Name)
510                   
511            if not options["noquota"] :   
512                if hardlimit is None :   
513                    hardlimit = softlimit
514                    if hardlimit is not None :
515                        self.logger.log_message(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer.Name))
516                if softlimit is None :   
517                    softlimit = hardlimit
518                    if softlimit is not None :
519                        self.logger.log_message(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer.Name))
520                       
521            if options["add"] :   
522                allentries = []   
523                for name in names :
524                    entry = getattr(self.storage, "get%s" % suffix)(name)
525                    entrypquota = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
526                    allentries.append((entry, entrypquota))
527            else :   
528                allentries = getattr(self.storage, "getPrinter%ssAndQuotas" % suffix)(printer, names)
529               
530            for (entry, entrypquota) in allentries :
531                if not changed.has_key(entry.Name) :
532                    changed[entry.Name] = {}
533                    if not options["groups"] :
534                        changed[entry.Name]["ingroups"] = []
535                       
536                if not entry.Exists :       
537                    # not found
538                    if options["add"] :
539                        # In case we want to add something, it is crucial
540                        # that we DON'T check with the system accounts files
541                        # like /etc/passwd because users may be defined
542                        # only remotely
543                        if self.isValidName(entry.Name) :
544                            entry = getattr(self.storage, "add%s" % suffix)(entry)
545                        else :   
546                            if options["groups"] :
547                                self.logger.log_message(_("Invalid group name %s") % entry.Name)
548                            else :   
549                                self.logger.log_message(_("Invalid user name %s") % entry.Name)
550                               
551                if entry.Exists and (not entrypquota.Exists) :
552                    # not found
553                    if options["add"] :
554                        entrypquota = getattr(self.storage, "add%sPQuota" % suffix)(entry, printer)
555                       
556                if not entrypquota.Exists :     
557                    self.logger.log_message(_("Quota not found for object %s on printer %s.") % (entry.Name, printer.Name))
558                else :   
559                    if options["delete"] :
560                        entry.delete()
561                    else :
562                        if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) :
563                            entrypquota.setLimits(softlimit, hardlimit)
564                        if limitby :
565                            if changed[entry.Name].get("limitby") is None :
566                                entry.setLimitBy(limitby)
567                                changed[entry.Name]["limitby"] = limitby
568                       
569                        if not options["groups"] :
570                            if options["reset"] :
571                                entrypquota.reset()
572                               
573                            if balance :
574                                if changed[entry.Name].get("balance") is None :
575                                    if balance.startswith("+") or balance.startswith("-") :
576                                        newbalance = float(entry.AccountBalance or 0.0) + balancevalue
577                                        newlifetimepaid = float(entry.LifeTimePaid or 0.0) + balancevalue
578                                        entry.setAccountBalance(newbalance, newlifetimepaid)
579                                    else :
580                                        diff = balancevalue - float(entry.AccountBalance or 0.0)
581                                        newlifetimepaid = float(entry.LifeTimePaid or 0.0) + diff
582                                        entry.setAccountBalance(balancevalue, newlifetimepaid)
583                                    changed[entry.Name]["balance"] = balance
584                                   
585                            for groupname in groupnames :       
586                                # not executed if option --ingroups is not used
587                                if groupname not in changed[entry.Name]["ingroups"] :
588                                    group = self.storage.getGroup(groupname)
589                                    if group.Exists :
590                                        self.storage.addUserToGroup(entry, group)
591                                        changed[entry.Name]["ingroups"].append(groupname)
592                                    else :
593                                        self.logger.log_message(_("Group %s not found in the PyKota Storage.") % groupname)
594                                       
595                        # This line disabled to prevent sending of unwanted email                 
596                        # messages if quota is reached at creation/modification time.
597                        # The check will be done at print time anyway.
598                        # getattr(self, "warn%sPQuota" % suffix)(entrypquota)   
599                     
600if __name__ == "__main__" : 
601    retcode = 0
602    try :
603        defaults = { \
604                     "printer" : "*", \
605                   }
606        short_options = "vhdc:l:b:i:naugrp:P:S:H:G:"
607        long_options = ["help", "version", "charge=", "delete", "limitby=", "balance=", "ingroups=", "noquota", "add", "users", "groups", "reset", "prototype=", "printer=", "softlimit=", "hardlimit=", "pgroups="]
608       
609        # Initializes the command line tool
610        editor = EdPyKota(doc=__doc__)
611       
612        # parse and checks the command line
613        (options, args) = editor.parseCommandline(sys.argv[1:], short_options, long_options)
614       
615        # sets long options
616        options["help"] = options["h"] or options["help"]
617        options["version"] = options["v"] or options["version"]
618        options["add"] = options["a"] or options["add"]
619        options["users"] = options["u"] or options["users"]
620        options["groups"] = options["g"] or options["groups"]
621        options["prototype"] = options["p"] or options["prototype"]
622        options["printer"] = options["P"] or options["printer"] or defaults["printer"]
623        options["softlimit"] = options["S"] or options["softlimit"]
624        options["hardlimit"] = options["H"] or options["hardlimit"] 
625        options["reset"] = options["r"] or options["reset"] 
626        options["noquota"] = options["n"] or options["noquota"]
627        options["limitby"] = options["l"] or options["limitby"]
628        options["balance"] = options["b"] or options["balance"] 
629        options["delete"] = options["d"] or options["delete"] 
630        options["ingroups"] = options["i"] or options["ingroups"]
631        options["charge"] = options["c"] or options["charge"]
632        options["pgroups"] = options["G"] or options["pgroups"]
633       
634        if options["help"] :
635            editor.display_usage_and_quit()
636        elif options["version"] :
637            editor.display_version_and_quit()
638        elif options["users"] and options["groups"] :   
639            raise PyKotaToolError, _("incompatible options, see help.")
640        elif (options["add"] or options["prototype"]) and options["delete"] :   
641            raise PyKotaToolError, _("incompatible options, see help.")
642        elif (options["softlimit"] or options["hardlimit"]) and options["prototype"] :   
643            raise PyKotaToolError, _("incompatible options, see help.")
644        elif options["noquota"] and (options["prototype"] or options["hardlimit"] or options["softlimit"]) :
645            raise PyKotaToolError, _("incompatible options, see help.")
646        elif options["groups"] and (options["balance"] or options["ingroups"]) :
647            raise PyKotaToolError, _("incompatible options, see help.")
648        else :
649            retcode = editor.main(args, options)
650    except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg :           
651        sys.stderr.write("%s\n" % msg)
652        sys.stderr.flush()
653        retcode = -1
654
655    try :
656        editor.storage.close()
657    except (TypeError, NameError, AttributeError) :   
658        pass
659       
660    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.