Changeset 1185 for pykota/trunk/bin/cupspykota
- Timestamp:
- 11/14/03 23:05:12 (20 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/bin/cupspykota
r1184 r1185 24 24 # 25 25 # $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 # 26 30 # Revision 1.6 2003/11/14 20:13:11 jalet 27 31 # We exit the loop too soon. … … 147 151 return "%s >/dev/null" % (cmdline % locals()) 148 152 149 def sigterm_handler(signum, frame) :150 """Handler for SIGTERM."""151 sys.stderr.write("INFO: PyKota backend aborted.")152 sys.exit(1)153 154 153 def main(thebackend) : 155 154 """Do it, and do it right !""" … … 157 156 # CUPS backends ignore SIGPIPE and exit(1) on SIGTERM 158 157 # 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. 160 162 signal.signal(signal.SIGPIPE, signal.SIG_IGN) 161 signal.signal(signal.SIGTERM, sig term_handler)163 signal.signal(signal.SIGTERM, signal.SIG_IGN) 162 164 163 165 # … … 226 228 thebackend.accounter.beginJob(printer, user) 227 229 228 # executes original backend 230 # Now it becomes tricky... 231 232 # First ensure that we have a file object as input 229 233 mustclose = 0 230 234 if thebackend.inputfile is not None : … … 236 240 else : 237 241 infile = sys.stdin 242 243 # Find the real backend pathname 238 244 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. 241 250 infno = infile.fileno() 242 251 stdoutfno = sys.stdout.fileno() … … 245 254 tocfno = subprocess.tochild.fileno() 246 255 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() 247 260 pollster.register(infno, select.POLLIN | select.POLLPRI) 248 261 pollster.register(fromcfno, select.POLLIN | select.POLLPRI) … … 251 264 pollster.register(stderrfno, select.POLLOUT) 252 265 pollster.register(tocfno, select.POLLOUT) 266 267 # Initialize our buffers 253 268 indata = "" 254 269 outdata = "" 255 270 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) 275 318 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) 279 334 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. 300 366 if mustclose : 301 367 infile.close() 302 status = subprocess.wait() 368 369 # Check exit code of original CUPS backend. 303 370 if os.WIFEXITED(status) : 304 371 retcode = os.WEXITSTATUS(status)