Show
Ignore:
Timestamp:
11/14/03 23:05:12 (20 years ago)
Author:
jalet
Message:

New CUPS backend fully functionnal.
Old CUPS configuration method is now officially deprecated.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/cupspykota

    r1184 r1185  
    2424# 
    2525# $Log$ 
     26# Revision 1.7  2003/11/14 22:05:12  jalet 
     27# New CUPS backend fully functionnal. 
     28# Old CUPS configuration method is now officially deprecated. 
     29# 
    2630# Revision 1.6  2003/11/14 20:13:11  jalet 
    2731# We exit the loop too soon. 
     
    147151    return "%s >/dev/null" % (cmdline % locals()) 
    148152 
    149 def sigterm_handler(signum, frame) : 
    150     """Handler for SIGTERM.""" 
    151     sys.stderr.write("INFO: PyKota backend aborted.") 
    152     sys.exit(1) 
    153      
    154153def main(thebackend) :     
    155154    """Do it, and do it right !""" 
     
    157156    # CUPS backends ignore SIGPIPE and exit(1) on SIGTERM 
    158157    # Fortunately SIGPIPE is already ignored by Python 
    159     # It's there just in case this changes in the future 
     158    # It's there just in case this changes in the future. 
     159    # But here we will IGNORE SIGTERM for now, and see 
     160    # if we shouldn't pass it to the original backend 
     161    # instead. 
    160162    signal.signal(signal.SIGPIPE, signal.SIG_IGN) 
    161     signal.signal(signal.SIGTERM, sigterm_handler) 
     163    signal.signal(signal.SIGTERM, signal.SIG_IGN) 
    162164     
    163165    # 
     
    226228        thebackend.accounter.beginJob(printer, user) 
    227229         
    228         # executes original backend 
     230        # Now it becomes tricky... 
     231         
     232        # First ensure that we have a file object as input 
    229233        mustclose = 0     
    230234        if thebackend.inputfile is not None :     
     
    236240        else :     
    237241            infile = sys.stdin 
     242             
     243        # Find the real backend pathname     
    238244        realbackend = os.path.join(os.path.split(sys.argv[0])[0], thebackend.originalbackend) 
    239         subprocess = PyKotaPopen3([realbackend] + sys.argv[1:], capturestderr=1, arg0=os.environ["DEVICE_URI"]) 
    240         pollster = select.poll() 
     245         
     246        # And launch it 
     247        subprocess = PyKotaPopen3([realbackend] + sys.argv[1:], capturestderr=1, bufsize=0, arg0=os.environ["DEVICE_URI"]) 
     248         
     249        # Save file descriptors, we will need them later. 
    241250        infno = infile.fileno() 
    242251        stdoutfno = sys.stdout.fileno() 
     
    245254        tocfno = subprocess.tochild.fileno() 
    246255        cerrfno = subprocess.childerr.fileno() 
     256         
     257        # We will have to be careful when dealing with I/O  
     258        # So we use a poll object to know when to read or write 
     259        pollster = select.poll() 
    247260        pollster.register(infno, select.POLLIN | select.POLLPRI) 
    248261        pollster.register(fromcfno, select.POLLIN | select.POLLPRI) 
     
    251264        pollster.register(stderrfno, select.POLLOUT) 
    252265        pollster.register(tocfno, select.POLLOUT) 
     266         
     267        # Initialize our buffers 
    253268        indata = "" 
    254269        outdata = "" 
    255270        errdata = "" 
    256         end = 0 
    257         while not end : 
    258             availablefds = pollster.poll(500) 
    259             if not availablefds : 
    260                 end = 1 
    261             else :     
    262                 for (fd, mask) in availablefds : 
    263                     thebackend.logdebug("Stream: %02i  Mask: %02x" % (fd, mask)) 
    264                     if mask & select.POLLHUP : 
    265                         if fd == infno : 
    266                             end = 1 # this happens with real stdin 
    267                     if mask & select.POLLOUT : 
    268                         if fd == tocfno : 
    269                             if indata : 
    270                                 os.write(fd, indata)     
    271                                 indata = "" 
    272                         elif fd == stdoutfno : 
    273                             if outdata : 
    274                                 os.write(fd, outdata) 
     271        endinput = 0 
     272        status = -1 
     273        while status == -1 : 
     274            # First check if original backend is still alive 
     275            status = subprocess.poll() 
     276             
     277            # In any case, deal with any remaining I/O 
     278            availablefds = pollster.poll() 
     279            for (fd, mask) in availablefds : 
     280                if mask & select.POLLOUT : 
     281                    # We can write 
     282                    if fd == tocfno : 
     283                        if indata : 
     284                            os.write(fd, indata)     
     285                            indata = "" 
     286                    elif fd == stdoutfno : 
     287                        if outdata : 
     288                            os.write(fd, outdata) 
     289                            outdata = "" 
     290                    elif fd == stderrfno : 
     291                        if errdata : 
     292                            os.write(fd, errdata) 
     293                            errdata = "" 
     294                if (mask & select.POLLIN) or (mask & select.POLLPRI) :      
     295                    # We have something to read 
     296                    data = os.read(fd, 256 * 1024) 
     297                    if fd == infno : 
     298                        indata += data 
     299                        if not data :    # If yes, then no more input data 
     300                            endinput = 1 # this happens with real files. 
     301                    elif fd == fromcfno : 
     302                        outdata += data 
     303                    elif fd == cerrfno :     
     304                        errdata += data 
     305                if mask & select.POLLHUP : 
     306                    # Some standard I/O stream has no more datas 
     307                    if fd == infno : 
     308                        # Here we are in the case where the input file is stdin. 
     309                        # which has no more data to be read. 
     310                        endinput = 1 
     311                    elif fd == fromcfno :     
     312                        # This should never happen, since 
     313                        # CUPS backends don't send anything on their 
     314                        # standard output 
     315                        if outdata :                 
     316                            try : 
     317                                os.write(stdoutfno, outdata) 
    275318                                outdata = "" 
    276                         elif fd == stderrfno : 
    277                             if errdata : 
    278                                 os.write(fd, errdata) 
     319                            except :     
     320                                pass 
     321                        try :         
     322                            pollster.unregister(fromcfno)         
     323                        except KeyError :     
     324                            pass 
     325                        else :     
     326                            os.close(fromcfno) 
     327                    elif fd == cerrfno :     
     328                        # Original CUPS backend has finished  
     329                        # to write informations on its standard error 
     330                        if errdata :                 
     331                            # Try to write remaining info (normally "Ready to print.") 
     332                            try : 
     333                                os.write(stderrfno, errdata) 
    279334                                errdata = "" 
    280                     if (mask & select.POLLIN) or (mask & select.POLLPRI) :      
    281                         data = os.read(fd, 256 * 1024) 
    282                         if fd == infno : 
    283                             indata += data 
    284                             if not data : 
    285                                 end = 1 # this happens with real files 
    286                         elif fd == fromcfno : 
    287                             outdata += data 
    288                         elif fd == cerrfno :     
    289                             errdata += data 
    290         if indata :                 
    291             try : 
    292                 os.write(tocfno, indata) 
    293             except :     
    294                 pass 
    295         sys.stdout.flush()                 
    296         sys.stderr.flush() 
    297         subprocess.fromchild.close() 
    298         subprocess.childerr.close() 
    299         subprocess.tochild.close() 
     335                            except :     
     336                                pass 
     337                        # We are no more interested in this file descriptor         
     338                        try :         
     339                            pollster.unregister(cerrfno)         
     340                        except KeyError :     
     341                            pass 
     342                        else :     
     343                            os.close(cerrfno) 
     344                         
     345            if endinput :             
     346                # We deal with remaining input datas here 
     347                # because EOF can happen in two different 
     348                # situations and I don't want to duplicate 
     349                # code, nor making functions. 
     350                if indata :                 
     351                    try : 
     352                        os.write(tocfno, indata) 
     353                        indata = "" 
     354                    except :     
     355                        pass 
     356                # Again, we're not interested in this file descriptor         
     357                # anymore. 
     358                try :         
     359                    pollster.unregister(tocfno)         
     360                except KeyError :     
     361                    pass 
     362                else :     
     363                    os.close(tocfno) 
     364             
     365        # Input file was a real file, we have to close it.     
    300366        if mustclose : 
    301367            infile.close() 
    302         status = subprocess.wait() 
     368             
     369        # Check exit code of original CUPS backend.     
    303370        if os.WIFEXITED(status) : 
    304371            retcode = os.WEXITSTATUS(status)