Changeset 679

Show
Ignore:
Timestamp:
08/10/06 23:08:32 (16 years ago)
Author:
jerome
Message:

Used pylint to remove some uglyness from the code.
Removed all the handling of SIGTERMS since CUPS backends ignore
SIGTERM anyway.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • tea4cups/trunk/tea4cups

    r677 r679  
    2323# 
    2424# 
     25 
     26"""Tea4CUPS is the Swiss Army's knife of the CUPS Administrator. 
     27 
     28 
     29Licensing terms : 
     30 
     31  (c) 2005, 2006 Jerome Alet <alet@librelogiciel.com> 
     32  (c) 2005 Peter Stuge <stuge-tea4cups@cdy.org> 
     33  This program is free software; you can redistribute it and/or modify 
     34  it under the terms of the GNU General Public License as published by 
     35  the Free Software Foundation; either version 2 of the License, or 
     36  (at your option) any later version. 
     37   
     38  This program is distributed in the hope that it will be useful, 
     39  but WITHOUT ANY WARRANTY; without even the implied warranty of 
     40  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     41  GNU General Public License for more details. 
     42   
     43  You should have received a copy of the GNU General Public License 
     44  along with this program; if not, write to the Free Software 
     45  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 
     46 
     47 
     48Setup : 
     49 
     50  Copy the different files where they belong : 
     51   
     52    $ cp tea4cups /usr/lib/cups/backend/ 
     53    $ chown root.root /usr/lib/cups/backend/tea4cups 
     54    $ chmod 700 /usr/lib/cups/backend/tea4cups 
     55    $ cp tea4cups.conf /etc/cupsd/ 
     56   
     57  Now edit the configuration file to suit your needs : 
     58   
     59    $ vi /etc/cupsd/tea4cups.conf 
     60     
     61    NB : you can use emacs as well :-) 
     62     
     63  Finally restart CUPS : 
     64   
     65    $ /etc/init.d/cupsys restart 
     66   
     67  You can now create "Tea4CUPS Managed" print queues from 
     68  CUPS' web interface, or using lpadmin. 
     69   
     70Send bug reports to : alet@librelogiciel.com   
     71"""         
    2572 
    2673import sys 
     
    798845        raise ConfigError, "Invalid configuration file : no option %s in section [%s]" % (option, section) 
    799846 
     847def isTrue(option) : 
     848    """Returns 1 if option is set to true, else 0.""" 
     849    if (option is not None) and (option.upper().strip() in ['Y', 'YES', '1', 'ON', 'T', 'TRUE']) : 
     850        return 1 
     851    else : 
     852        return 0 
     853 
     854def getCupsConfigDirectives(directives=[]) : 
     855    """Retrieves some CUPS directives from its configuration file. 
     856 
     857       Returns a mapping with lowercased directives as keys and 
     858       their setting as values. 
     859    """ 
     860    dirvalues = {} 
     861    cupsroot = os.environ.get("CUPS_SERVERROOT", "/etc/cups") 
     862    cupsdconf = os.path.join(cupsroot, "cupsd.conf") 
     863    try : 
     864        conffile = open(cupsdconf, "r") 
     865    except IOError : 
     866        raise TeeError, "Unable to open %s" % cupsdconf 
     867    else : 
     868        for line in conffile.readlines() : 
     869            linecopy = line.strip().lower() 
     870            for di in [d.lower() for d in directives] : 
     871                if linecopy.startswith("%s " % di) : 
     872                    try : 
     873                        val = line.split()[1] 
     874                    except : 
     875                        pass # ignore errors, we take the last value in any case. 
     876                    else : 
     877                        dirvalues[di] = val 
     878        conffile.close() 
     879    return dirvalues 
     880     
    800881class CupsBackend : 
    801882    """Base class for tools with no database access.""" 
     
    807888        self.myname = "tea4cups" 
    808889        self.pid = os.getpid() 
     890        self.debug = True 
     891        self.isCancelled = False 
     892        self.Title = None 
     893        self.InputFile = None 
     894        self.RealBackend = None 
     895        self.ControlFile = None 
     896        self.ClientHost = None 
     897        self.PrinterName = None 
     898        self.JobBilling = None 
     899        self.UserName = None 
     900        self.Copies = None 
     901        self.Options = None 
     902        self.DataFile = None 
     903        self.JobMD5Sum = None 
     904        self.JobSize = None 
     905        self.DeviceURI = None 
     906        self.JobId = None 
     907        self.Directory = None 
     908        self.pipes = {} 
     909        self.config = None 
     910        self.conffile = None 
    809911 
    810912    def readConfig(self) : 
     
    815917            self.config = ConfigParser.ConfigParser() 
    816918            self.config.read([self.conffile]) 
    817             self.debug = self.isTrue(self.getGlobalOption("debug", ignore=1)) 
     919            self.debug = isTrue(self.getGlobalOption("debug", ignore=1)) 
    818920        else : 
    819921            self.config = FakeConfig() 
     
    832934        if self.debug : 
    833935            self.logInfo(message, level="debug") 
    834  
    835     def isTrue(self, option) : 
    836         """Returns 1 if option is set to true, else 0.""" 
    837         if (option is not None) and (option.upper().strip() in ['Y', 'YES', '1', 'ON', 'T', 'TRUE']) : 
    838             return 1 
    839         else : 
    840             return 0 
    841936 
    842937    def getGlobalOption(self, option, ignore=0) : 
     
    9061001                # see if the pid contained in the lock file is still running 
    9071002                os.kill(pid, 0) 
    908             except OSError, e : 
    909                 if e.errno != errno.EPERM : 
     1003            except OSError, error : 
     1004                if error.errno != errno.EPERM : 
    9101005                    # process doesn't exist anymore 
    9111006                    os.remove(lockfilename) 
     
    9221017                answer = os.popen(backend, "r") 
    9231018                try : 
    924                     devices = [line.strip() for line in answer.readlines()] 
     1019                    devices = [deviceline.strip() for deviceline in answer.readlines()] 
    9251020                except : 
    9261021                    devices = [] 
     
    9831078            fulldevice_uri = device_uri[:] 
    9841079            device_uri = fulldevice_uri[len(muststartwith):] 
    985             for i in range(2) : 
     1080            for dummy in range(2) : 
    9861081                if device_uri.startswith("/") : 
    9871082                    device_uri = device_uri[1:] 
    9881083        try : 
    989             (backend, destination) = device_uri.split(":", 1) 
     1084            (backend, dummy) = device_uri.split(":", 1) 
    9901085        except ValueError : 
    9911086            if not device_uri : 
     
    10151110        if type(john) == type([]) :                           
    10161111            john = john[-1] 
    1017         (chtype, self.ClientHost) = john                           
     1112        (dummy, self.ClientHost) = john                           
    10181113        try :         
    10191114            jbing = answer.job["job-billing"] 
     
    10221117        if type(jbing) == type([]) :  
    10231118            jbing = jbing[-1] 
    1024         (jbtype, self.JobBilling) = jbing 
    1025  
    1026     def getCupsConfigDirectives(self, directives=[]) : 
    1027         """Retrieves some CUPS directives from its configuration file. 
    1028  
    1029            Returns a mapping with lowercased directives as keys and 
    1030            their setting as values. 
    1031         """ 
    1032         dirvalues = {} 
    1033         cupsroot = os.environ.get("CUPS_SERVERROOT", "/etc/cups") 
    1034         cupsdconf = os.path.join(cupsroot, "cupsd.conf") 
    1035         try : 
    1036             conffile = open(cupsdconf, "r") 
    1037         except IOError : 
    1038             raise TeeError, "Unable to open %s" % cupsdconf 
    1039         else : 
    1040             for line in conffile.readlines() : 
    1041                 linecopy = line.strip().lower() 
    1042                 for di in [d.lower() for d in directives] : 
    1043                     if linecopy.startswith("%s " % di) : 
    1044                         try : 
    1045                             val = line.split()[1] 
    1046                         except : 
    1047                             pass # ignore errors, we take the last value in any case. 
    1048                         else : 
    1049                             dirvalues[di] = val 
    1050             conffile.close() 
    1051         return dirvalues 
     1119        (dummy, self.JobBilling) = jbing 
     1120 
    10521121 
    10531122    def parseIPPRequestFile(self) : 
     
    10551124        requestroot = os.environ.get("CUPS_REQUESTROOT") 
    10561125        if requestroot is None : 
    1057             cupsdconf = self.getCupsConfigDirectives(["RequestRoot"]) 
     1126            cupsdconf = getCupsConfigDirectives(["RequestRoot"]) 
    10581127            requestroot = cupsdconf.get("requestroot", "/var/spool/cups") 
    10591128        if (len(self.JobId) < 5) and self.JobId.isdigit() : 
     
    11581227    def cleanUp(self) : 
    11591228        """Cleans up the place.""" 
    1160         if (not self.isTrue(self.getPrintQueueOption(self.PrinterName, "keepfiles", ignore=1))) \ 
     1229        if (not isTrue(self.getPrintQueueOption(self.PrinterName, "keepfiles", ignore=1))) \ 
    11611230            and os.path.exists(self.DataFile) : 
    11621231            try : 
     
    11651234                self.logInfo("Problem when removing %s : %s" % (self.DataFile, msg), "error") 
    11661235 
    1167     def sigtermHandler(self, signum, frame) : 
    1168         """Sets an attribute whenever SIGTERM is received.""" 
    1169         self.gotSigTerm = 1 
    1170         self.logInfo("SIGTERM received for Job %s." % self.JobId) 
    1171  
    11721236    def runBranches(self) : 
    11731237        """Launches each hook defined for the current print queue.""" 
    11741238        self.isCancelled = 0    # did a prehook cancel the print job ? 
    1175         self.gotSigTerm = 0 
    1176         signal.signal(signal.SIGTERM, self.sigtermHandler) 
    1177         serialize = self.isTrue(self.getPrintQueueOption(self.PrinterName, "serialize", ignore=1)) 
     1239        serialize = isTrue(self.getPrintQueueOption(self.PrinterName, "serialize", ignore=1)) 
    11781240        self.pipes = { 0: (0, 1) } 
    11791241        branches = self.enumBranches(self.PrinterName, "prehook") 
     
    11831245        for p in [ (k, v) for (k, v) in self.pipes.items() if k != 0 ] : 
    11841246            os.close(p[1][1]) 
    1185         if not self.isCancelled and not self.gotSigTerm : 
     1247        if not self.isCancelled : 
    11861248            if self.RealBackend : 
    11871249                retcode = self.launchOriginalBackend() 
     
    11921254                        self.logDebug("Launching onfail script %s" % onfail) 
    11931255                        os.system(onfail) 
    1194             if not self.gotSigTerm : 
    1195                 os.environ["TEASTATUS"] = str(retcode) 
    1196                 branches = self.enumBranches(self.PrinterName, "posthook") 
    1197                 if self.runCommands("posthook", branches, serialize) : 
    1198                     self.logInfo("An error occured during the execution of posthooks.", "warn") 
     1256                         
     1257            os.environ["TEASTATUS"] = str(retcode) 
     1258            branches = self.enumBranches(self.PrinterName, "posthook") 
     1259            if self.runCommands("posthook", branches, serialize) : 
     1260                self.logInfo("An error occured during the execution of posthooks.", "warn") 
     1261                 
    11991262        for p in [ (k, v) for (k, v) in self.pipes.items() if k != 0 ] : 
    12001263            os.close(p[1][0]) 
    1201         signal.signal(signal.SIGTERM, signal.SIG_IGN) 
    12021264        if not retcode : 
    12031265            self.logInfo("OK") 
     
    12491311            self.logDebug("Begin serialized %ss" % btypetitle) 
    12501312            for branch in branchlist : 
    1251                 if self.gotSigTerm : 
    1252                     break 
    12531313                retcode = self.runCommand(branch, branches[branch]) 
    12541314                self.logDebug("Exit code for %s %s on printer %s is %s" % (btype, branch, self.PrinterName, retcode)) 
     
    12651325            pids = {} 
    12661326            for branch in branchlist : 
    1267                 if self.gotSigTerm : 
    1268                     break 
    12691327                pid = os.fork() 
    12701328                if pid : 
     
    13411399                status = os.waitpid(pid, 0)[1] 
    13421400            except OSError, (err, msg) : 
    1343                 if (err == 4) and self.gotSigTerm : 
    1344                     os.kill(pid, signal.SIGTERM) 
     1401                if err == 4 : 
    13451402                    killed = 1 
    13461403        if os.WIFEXITED(status) : 
    13471404            status = os.WEXITSTATUS(status) 
    13481405            if status : 
    1349                 self.logInfo("CUPS backend %s returned %d." % (originalbackend,\ 
     1406                self.logInfo("CUPS backend %s returned %d." % (originalbackend, \ 
    13501407                                                             status), "error") 
    13511408            return status 
    13521409        elif not killed : 
    1353             self.logInfo("CUPS backend %s died abnormally." % originalbackend,\ 
     1410            self.logInfo("CUPS backend %s died abnormally." % originalbackend, \ 
    13541411                                                              "error") 
    13551412            return -1 
     
    13681425        sys.exit(1) 
    13691426    else : 
    1370         retcode = 1 
     1427        returncode = 1 
    13711428        try : 
    13721429            try : 
     
    13751432                wrapper.saveDatasAndCheckSum() 
    13761433                wrapper.exportAttributes() 
    1377                 retcode = wrapper.runBranches() 
     1434                returncode = wrapper.runBranches() 
    13781435            except SystemExit, e : 
    1379                 retcode = e.code 
     1436                returncode = e.code 
    13801437            except : 
    13811438                import traceback 
    13821439                lines = [] 
    1383                 for line in traceback.format_exception(*sys.exc_info()) : 
    1384                     lines.extend([l for l in line.split("\n") if l]) 
    1385                 msg = "ERROR: ".join(["%s (PID %s) : %s\n" % (wrapper.MyName, \ 
     1440                for errline in traceback.format_exception(*sys.exc_info()) : 
     1441                    lines.extend([l for l in errline.split("\n") if l]) 
     1442                errormessage = "ERROR: ".join(["%s (PID %s) : %s\n" % (wrapper.MyName, \ 
    13861443                                                              wrapper.pid, l) \ 
    13871444                            for l in (["ERROR: Tea4CUPS v%s" % __version__] + lines)]) 
    1388                 sys.stderr.write(msg) 
     1445                sys.stderr.write(errormessage) 
    13891446                sys.stderr.flush() 
    1390                 retcode = 1 
     1447                returncode = 1 
    13911448        finally :         
    13921449            wrapper.cleanUp() 
    1393         sys.exit(retcode) 
     1450        sys.exit(returncode)