Show
Ignore:
Timestamp:
01/08/08 00:03:01 (17 years ago)
Author:
jerome
Message:

Doesn't drop and regain priviledges anymore : no added security since we could regain them (we needed to regain them for PAM and some end user scripts). This is also more consistent.
Removed SGTERM handling stuff in cupspykota : now only SIGINT can be used.
Now outputs an error message when printing (but doesn't fail) if CUPS is
not v1.3.4 or higher : we need 1.3.4 or higher because it fixes some
problematic charset handling bugs (by only accepting ascii and utf-8,
but this is a different story...)
Now ensures only the supported exit codes are returned by cupspykota :
we used to exit -1 in some cases (see man backend for details).

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/cupspykota

    r3275 r3276  
    7272        signal.signal(signal.SIGTERM, signal.SIG_IGN) 
    7373        signal.signal(signal.SIGPIPE, signal.SIG_IGN) 
     74        self.oldSigIntHandler = signal.signal(signal.SIGINT, signal.SIG_IGN) 
    7475        self.MyName = "PyKota" 
    7576        self.myname = "cupspykota" 
     
    8485        if not self.config.isAdmin : 
    8586            from pykota import config 
    86             username = self.originalUserName 
     87            username = self.effectiveUserName 
    8788            raise config.PyKotaConfigError, _("User %(username)s is not allowed to read ~pykota/pykotadmin.conf, you must check the permissions.") % locals() 
    88         self.gotSigTerm = 0 
    89         self.disableSigInt() 
    90         self.installSigTermHandler() 
    91          
    92     def sigtermHandler(self, signum, frame) : 
    93         """Sets an attribute whenever SIGTERM is received.""" 
    94         self.gotSigTerm = 1 
    95         self.printInfo(_("SIGTERM received, job %s cancelled.") % self.Ticket.JobId) 
    96         os.environ["PYKOTASTATUS"] = "CANCELLED" 
    97          
    98     def deinstallSigTermHandler(self) :            
    99         """Deinstalls the SIGTERM handler.""" 
    100         self.logdebug("Deinstalling SIGTERM handler...") 
    101         signal.signal(signal.SIGTERM, signal.SIG_IGN) 
    102         self.logdebug("SIGTERM handler deinstalled.") 
    103          
    104     def installSigTermHandler(self) :            
    105         """Installs the SIGTERM handler.""" 
    106         self.logdebug("Installing SIGTERM handler...") 
    107         signal.signal(signal.SIGTERM, self.sigtermHandler) 
    108         self.logdebug("SIGTERM handler installed.") 
    109          
    110     def disableSigInt(self) :     
    111         """Disables the SIGINT signal (which raises KeyboardInterrupt).""" 
    112         self.logdebug("Disabling SIGINT...") 
    113         self.oldSigIntHandler = signal.signal(signal.SIGINT, signal.SIG_IGN) 
    114         self.logdebug("SIGINT disabled.") 
    11589         
    11690    def enableSigInt(self) :     
    11791        """Enables the SIGINT signal (which raises KeyboardInterrupt).""" 
    118         self.logdebug("Enabling SIGINT...") 
    11992        signal.signal(signal.SIGINT, self.oldSigIntHandler) 
    120         self.logdebug("SIGINT enabled.") 
    12193         
    12294    def waitForLock(self) :     
     
    153125           Executes each existing backend in turn in device enumeration mode. 
    154126           Returns the list of available backends. 
     127            
     128           Unfortunately this method can't output any debug information 
     129           to stdout or stderr, else CUPS considers that the device is 
     130           not available. 
    155131        """ 
    156         # Unfortunately this method can't output any debug information 
    157         # to stdout or stderr, else CUPS considers that the device is 
    158         # not available. 
    159132        available = [] 
    160133        (directory, myname) = os.path.split(sys.argv[0]) 
     
    226199        return available 
    227200                         
     201    def checkCUPSVersion(self) :                     
     202        """Checks if CUPS is not v1.3.4 or higher.""" 
     203        fullversion = os.environ.get("SOFTWARE", "") 
     204        if fullversion.startswith("CUPS/") : 
     205            vnum = fullversion.split("/")[1] 
     206            try : 
     207               (major, minor, release) = [int(p) for p in vnum.split(".")] 
     208            except ValueError :    
     209                pass 
     210            else :     
     211                return (major > 1) \ 
     212                        or ((major == 1) and (minor > 3)) \ 
     213                        or ((major == 1) and (minor == 3) and (release >= 4)) 
     214        return False 
     215         
    228216    def initBackendParameters(self) :     
    229217        """Initializes the backend's attributes.""" 
     
    233221        # the environment before launching the real backend  
    234222        self.logdebug("Initializing backend...") 
     223         
     224        if not self.checkCUPSVersion() : 
     225            self.printInfo("BEWARE : CUPS is too old. You must use CUPS v1.3.4 or higher.", "error") 
    235226         
    236227        self.PrinterName = os.environ.get("PRINTER", "") 
     
    410401            self.logdebug("Launching subprocess [%s] to overwrite the job ticket." \ 
    411402                                     % jobticketcommand) 
    412             self.regainPriv()                          
    413403            inputfile = os.popen(jobticketcommand, "r") 
    414404            try : 
     
    433423                self.logdebug("IOError while reading subprocess' output : %s" % msg) 
    434424            inputfile.close()     
    435             self.dropPriv() 
    436425             
    437426            # now overwrite the job's ticket if new data was supplied 
     
    458447        outfile = open(self.DataFile, "wb")     
    459448        if self.Ticket.FileName is not None : 
    460             self.regainPriv() 
    461449            infile = open(self.Ticket.FileName, "rb") 
    462450            self.logdebug("Reading input datas from %s" % self.Ticket.FileName) 
     
    481469        if mustclose :     
    482470            infile.close() 
    483             self.dropPriv() 
    484471             
    485472        outfile.close() 
     
    494481        """Cleans up the place.""" 
    495482        self.logdebug("Cleaning up...") 
    496         self.regainPriv() 
    497         self.deinstallSigTermHandler() 
    498483        if (self.DataFile is not None) and os.path.exists(self.DataFile) : 
    499484            try : 
     
    933918            if mailto == "EXTERNAL" : 
    934919                # TODO : clean this again 
    935                 self.regainPriv() 
    936920                self.externalMailTo(arguments, self.Action, self.User, self.Printer, self.Reason) 
    937                 self.dropPriv() 
    938921            else :     
    939922                # TODO : clean this again 
     
    11141097        else : 
    11151098            self.printInfo(_("Job accounting begins.")) 
    1116             self.deinstallSigTermHandler() 
    11171099            self.accounter.beginJob(self.Printer) 
    1118             self.installSigTermHandler() 
    11191100         
    11201101        # handle starting banner pages with accounting 
    11211102        if (self.Action != "CANCEL") and accountbanner in ["STARTING", "BOTH"] : 
    1122             if not self.gotSigTerm : 
    1123                 self.handleBanner("starting", 1) 
    1124          
    1125         # pass the job's data to the real backend     
    1126         if (not self.gotSigTerm) and (self.Action in ["ALLOW", "WARN"]) : 
     1103            self.handleBanner("starting", 1) 
     1104         
     1105        # pass the job's data to the real backend if needed    
     1106        if self.Action in ("ALLOW", "WARN") : 
    11271107            retcode = self.printJobDatas() 
    11281108        else :         
     
    11341114        # handle ending banner pages with accounting 
    11351115        if (self.Action != "CANCEL") and accountbanner in ["ENDING", "BOTH"] : 
    1136             if not self.gotSigTerm : 
    1137                 self.handleBanner("ending", 1) 
     1116            self.handleBanner("ending", 1) 
    11381117         
    11391118        # stops accounting 
     
    11431122            self.printInfo(_("Job cancelled, no accounting has been done.")) 
    11441123        else : 
    1145             self.deinstallSigTermHandler() 
    11461124            self.accounter.endJob(self.Printer) 
    1147             self.installSigTermHandler() 
    11481125            self.printInfo(_("Job accounting ends.")) 
    11491126         
     
    12841261         
    12851262        self.logdebug("Starting original backend %s with args %s" % (originalbackend, " ".join(['"%s"' % a for a in arguments]))) 
    1286         self.regainPriv()     
    12871263        pid = os.fork() 
    12881264        self.logdebug("Forked !") 
     
    12981274            self.logdebug("We shouldn't be there !!!")     
    12991275            os._exit(-1) 
    1300         self.dropPriv()     
    13011276         
    13021277        self.logdebug("Waiting for original backend to exit...")     
    1303         killed = 0 
     1278        killed = False 
    13041279        status = -1 
    13051280        while status == -1 : 
     
    13071282                status = os.waitpid(pid, 0)[1] 
    13081283            except OSError, (err, msg) : 
    1309                 if (err == 4) and self.gotSigTerm : 
    1310                     os.kill(pid, signal.SIGTERM) 
    1311                     killed = 1 
     1284                if err == 4 : 
     1285                    killed = True 
    13121286                     
    13131287        if os.WIFEXITED(status) : 
     
    13251299            self.Reason = "CUPS backend %s died abnormally." % originalbackend 
    13261300            self.printInfo(self.Reason, "error") 
    1327             return -1 
     1301            return 1 
    13281302        else : 
    13291303            self.Reason = "CUPS backend %s was killed." % originalbackend