1 /***************************************************************************
2  * LPRng - An Extended Print Spooler System
3  *
4  * Copyright 1988-2003, Patrick Powell, San Diego, CA
5  *     papowell@lprng.com
6  * See LICENSE for conditions of use.
7  *
8  ***************************************************************************/
9 
10 #include "lp.h"
11 #include "errorcodes.h"
12 #include "printjob.h"
13 #include "getqueue.h"
14 #include "child.h"
15 #include "fileopen.h"
16 #include "printjob.h"
17 /**** ENDINCLUDE ****/
18 #if defined(HAVE_TCDRAIN)
19 #  if defined(HAVE_TERMIOS_H)
20 #    include <termios.h>
21 #  endif
22 #endif
23 
24 /***************************************************************************
25  * Commentary:
26  * Patrick Powell Sat May 13 08:24:43 PDT 1995
27  *
28  * The following algorithm is used to print a job
29  *
30  * The 'Send_through OF_filter' operation does the following:
31  *  if the of filter process does not exist then we create it
32  *  if the 'suspend_of_filter' flag is true then we add the suspend
33  *     string to the buffer
34  *  we send the buffer to the of filter processes
35  *  if the 'suspend_of_filter' flag is false or the 'end of job' flag
36  *    is true then we wait for the filter to exit.
37  *
38  *   now we put out the various initialization strings
39  *
40  * Leader_on_open_DYN -> buffer;
41  * FF_on_open_DYN     -> buffer;
42  * if( ( Always_banner_DYN || !Suppress_banner) && !Banner_last_DYN ){
43  * 	banner -> buffer
44  * }
45  *
46  * if( OF_FILTER ) buffer-> Send_through_of_filter
47  * else buffer -> output
48  *
49  *  print out the data files
50  * for( i = 0; i < data_files; ++i ){
51  *     if( i > 0 && FF between files && OF Filter ){
52  * 		FF -> buffer
53  *      if( OF_FILTER ) buffer-> Send_through_of_filter
54  *      else buffer -> output
55  *     }
56  *    filter = lookup filter
57  *    if( filter ) Send_file_through_filter( filter )
58  *    else file ->output
59  * }
60  *
61  * if( (Always_banner_DYN || !Suppress_banner) && Banner_last_DYN ){
62  * 	banner -> buffer;
63  * }
64  * Trailer_on_close_DYN -> buffer;
65  * FF_on_close_DYN     -> buffer;
66  *
67  * if( OF_FILTER ) buffer-> Send_through_of_filter(end_of_job as well)
68  * else buffer -> output
69  *
70  ****************************************************************************/
71 
72 static int Run_OF_filter( int send_job_rw_timeout, int *of_pid, int *of_stdin, int *of_stderr,
73 	int output, char **outbuf, int *outmax, int *outlen,
74 	struct job *job, const char *id, int terminate_of,
75 	char *msgbuffer, int msglen );
76 static void Print_banner( const char *name, char *pgm, struct job *job );
77 static int Write_outbuf_to_OF( struct job *job, const char *title,
78 	int of_fd, char *buffer, int outlen,
79 	int of_error, char *msg, int msgmax,
80 	int timeout, int poll_for_status, char *status_file );
81 
82 
83 
84 /****************************************************************************
85  * int Print_job( int output, - output device
86  *   int status_device - read status from this device is > 0
87  *   struct job *job   - job to print
88  *   int timeout       - timeout for job - 0 is no timeout
89  *   int poll_for_status - after write to device, poll for status
90  *
91  * We have a very complex set of IO requirements here.  First, there is
92  * the problem of the device and its status return.  If we have a 'real'
93  * device,  then it is usually opened RW, so we can get status back.
94  * In this case, output == status_device.  If we have a 'filter' as an
95  * output device,  then we arrange to have the filter pipe file descriptor
96  * bidirectional.  This means that the filter can/must also read the
97  * output from the device.
98  *
99  * This implies that output filters used as devices must handle their status
100  * and error reporting themselves,  and provide as little status back on their
101  * STDERR as is possible,  otherwise the pipe will block for them on write.
102  *
103  * So the following is now done:
104  *
105  *  a) if you have a 'real device' which is opened RW then you
106  *     have output == status_device otherwise you have status_device == -1
107  *  b) if you have an output device that requires that you poll it for
108  *     status after every write,  then you set 'poll_for_status'
109  *     This has the effect of temporarily setting 'status_device = -1'
110  *     i.e. - not trying to get status.
111  *  c) If you need to use a filter,  then you pass the output device to the
112  *     filter.  The filter will then need to decide if it can read from
113  *     the device.  After the filter has run and you have 'poll_for_status'
114  *     you should check for status from the device.
115  *  d) timeouts are handled by waiting for IO from either the file descriptor
116  *     OR checking to see if the status file exists and it has been updated.
117  ****************************************************************************/
118 
Print_job(int output,int status_device,struct job * job,int send_job_rw_timeout,int poll_for_status,char * user_filter)119 int Print_job( int output, int status_device, struct job *job,
120 	int send_job_rw_timeout, int poll_for_status, char *user_filter )
121 {
122 	char *FF_str, *leader_str, *trailer_str, *filter;
123 	int i, of_stdin, of_stderr, if_error[2],
124 		of_pid, copy, copies,
125 		do_banner, n, pid, count, fd, tempfd,
126 		files_printed, time_left;
127 
128 	char msg[SMALLBUFFER];
129 	char filter_name[8], filter_title[64], msgbuffer[SMALLBUFFER],
130 		filtermsgbuffer[SMALLBUFFER];
131 	const char *id, *s, *banner_name, *transfername, *openname, *format;
132 	char *t;
133 	struct line_list *datafile, files;
134 	struct stat statb;
135 
136 	of_pid = -1;
137 	msgbuffer[0] = 0;
138 	filtermsgbuffer[0] = 0;
139 	Errorcode = 0;
140 	Init_line_list(&files);
141 	of_stdin = of_stderr = tempfd = fd = -1;
142 	FF_str = leader_str = trailer_str = 0;
143 	files_printed = 0;
144 
145 	DEBUG2( "Print_job: output fd %d", output );
146 	if(DEBUGL5){
147 		LOGDEBUG("Print_job: at start open fd's");
148 		for( i = 0; i < 20; ++i ){
149 			if( fstat(i,&statb) == 0 ){
150 				LOGDEBUG("  fd %d (0%o)", i, (unsigned int)(statb.st_mode&S_IFMT));
151 			}
152 		}
153 	}
154 	if(DEBUGL2) Dump_job( "Print_job", job );
155 	id = Find_str_value(&job->info,IDENTIFIER);
156 	if( id == 0 ) id = Find_str_value(&job->info,XXCFTRANSFERNAME);
157 
158 	DEBUG2("Print_job: OF_Filter_DYN '%s'", OF_Filter_DYN );
159 
160 	/* clear output buffer */
161 	Init_buf(&Outbuf, &Outmax, &Outlen );
162 
163 	FF_str = Fix_str( Form_feed_DYN );
164 	leader_str = Fix_str( Leader_on_open_DYN );
165 	trailer_str = Fix_str( Trailer_on_close_DYN );
166 
167 	/* Leader_on_open_DYN -> output; */
168 	if( leader_str ) Put_buf_str( leader_str, &Outbuf, &Outmax, &Outlen );
169 
170 	/* FF_on_open_DYN -> output; */
171 	if( FF_on_open_DYN ) Put_buf_str( FF_str, &Outbuf, &Outmax, &Outlen );
172 
173 	/*
174 	 * if SupressHeader then no banner
175 	 * if AlwaysBanner then get user name
176 	 */
177 
178 
179 	banner_name = Find_str_value(&job->info, BNRNAME );
180 	if( Always_banner_DYN && banner_name == 0 ){
181 		/* we are always going to do a banner; get the user name */
182 		/* need a name to use */
183 		banner_name = Find_str_value( &job->info,LOGNAME);
184 		if( banner_name == 0 ) banner_name = "ANONYMOUS";
185 		Set_str_value(&job->info,BNRNAME,banner_name);
186 	}
187 	/* suppress header overrides everything */
188 	do_banner = (!Suppress_header_DYN && banner_name);
189 
190 	/* now we have a banner, is it at start or end? */
191 	DEBUG2("Print_job: do_banner %d, :hl=%d, :bs=%s, :be=%s, banner_name '%s'",
192 			do_banner, Banner_last_DYN, Banner_start_DYN, Banner_end_DYN, banner_name );
193 	if( do_banner && Generate_banner_DYN ){
194 		Add_banner_to_job( job );
195 		do_banner = 0;
196 		Outlen = 0;
197 	}
198 	if( do_banner && !Banner_last_DYN ){
199 		Print_banner( banner_name, Banner_start_DYN, job );
200 	}
201 
202 	DEBUG2("Print_job: setup %d bytes '%s'", Outlen, Outbuf );
203 
204 	msgbuffer[0] = 0;
205 	/* do we need an OF filter? */
206 	Set_block_io( output );
207 	if( OF_Filter_DYN ){
208 		if( Run_OF_filter( send_job_rw_timeout, &of_pid, &of_stdin, &of_stderr,
209 			output, &Outbuf, &Outmax, &Outlen,
210 			job, id, 0,
211 			msgbuffer, sizeof(msgbuffer)-1 ) ){
212 			goto exit;
213 		}
214 	} else if( Outlen ){
215 		/* no filter - direct to device */
216 		n = Write_outbuf_to_OF(job,"LP",output, Outbuf, Outlen,
217 			status_device, msgbuffer, sizeof(msgbuffer)-1,
218 			send_job_rw_timeout, poll_for_status, Status_file_DYN );
219 		if( n ){
220 			Errorcode = JFAIL;
221 			setstatus(job, "LP device write error '%s'", Server_status(n));
222 			goto exit;
223 		}
224 	}
225 	Init_buf(&Outbuf, &Outmax, &Outlen );
226 
227 	/*
228 	 *  print out the data files
229 	 */
230 
231 	for( count = 0; count < job->datafiles.count; ++count ){
232 		datafile = (void *)job->datafiles.list[count];
233 		if(DEBUGL4)Dump_line_list("Print_job - datafile", datafile );
234 
235 		Set_block_io( output );
236 		transfername = Find_str_value(datafile,DFTRANSFERNAME);
237 		openname = Find_str_value(datafile,OPENNAME);
238 		if( !openname ) openname = transfername;
239 		format = Find_str_value(datafile,FORMAT);
240 		copies = Find_flag_value(datafile,COPIES);
241 		if( copies == 0 ) copies = 1;
242 
243 		Set_str_value(&job->info,FORMAT,format);
244 		Set_str_value(&job->info,DF_NAME,transfername);
245 
246 		s = Find_str_value(datafile,"N");
247 		Set_str_value(&job->info,"N",s);
248 
249 		/*
250 		 * now we check to see if there is an input filter
251 		 */
252 		plp_snprintf(filter_name,sizeof(filter_name), "%s","if");
253 		filter_name[0] = cval(format);
254 		filter = user_filter;
255 		switch( cval(format) ){
256 			case 'p': case 'f': case 'l':
257 				filter_name[0] = 'i';
258 				if( !filter ) filter = IF_Filter_DYN;
259 				break;
260 			case 'a': case 'i': case 'o': case 's':
261 				setstatus(job, "bad data file format '%c', using 'f' format", cval(format) );
262 				filter_name[0] = 'i';
263 				if( !filter ) filter = IF_Filter_DYN;
264 				format = "f";
265 				break;
266 		}
267 		if( !filter ){
268 			filter = Find_str_value(&PC_entry_line_list, filter_name );
269 		}
270 		if( !filter){
271 			filter = Find_str_value(&Config_line_list,filter_name );
272 		}
273 		if( filter == 0 ) filter = Filter_DYN;
274 		DEBUG3("Print_job: format '%s', filter '%s'", format, filter );
275 
276 		uppercase(filter_name);
277 		if( filter ){
278 			s = filter;
279 			if( cval(s) == '(' ){
280 				++s;
281 				while( isspace(cval(s))) ++s;
282 			} else {
283 				if( !(s = strchr(filter,'/')) ) s = filter;
284 			}
285 			plp_snprintf(msg, sizeof(msg), "%s", s );
286 			if( (t = strpbrk(msg,Whitespace)) ) *t = 0;
287 			if( (t = strrchr(msg,'/')) ) memmove(msg,t+1,strlen(t+1)+1);
288 		} else {
289 			plp_snprintf(msg, sizeof(msg), "%s", "none - passthrough" );
290 		}
291 		plp_snprintf(filter_title,sizeof(filter_title), "%s filter '%s'",
292 			filter_name, msg );
293 
294 		if( fd >= 0 ) close(fd); fd = -1;
295 		if( !Is_server && openname == 0 ){
296 			fd = 0;
297 			DEBUG3("Print_job: taking file from STDIN" );
298 		} else if( (fd = Checkread( openname, &statb )) < 0 ){
299 			Errorcode = JFAIL;
300 			logmsg( LOG_ERR, "Print_job: job '%s', cannot open data file '%s'",
301 				id, openname );
302 			goto end_of_job;
303 		}
304 		setstatus(job, "processing '%s', size %0.0f, format '%s', %s",
305 			transfername, (double)statb.st_size, format, filter_title );
306 		if( cval(format) == 'p' ){
307 			DEBUG3("Print_job: using 'p' formatter '%s'", Pr_program_DYN );
308 			setstatus(job, "format 'p' pretty printer '%s'", Pr_program_DYN);
309 			if( Pr_program_DYN == 0 ){
310 				setstatus(job, "no 'p' format filter available" );
311 				Errorcode = JABORT;
312 				goto end_of_job;
313 			}
314 			tempfd = Make_temp_fd(0);
315 			n = Filter_file( send_job_rw_timeout, fd, tempfd, "PR_PROGRAM",
316 				Pr_program_DYN, 0, job, 0, 1 );
317 			if( n ){
318 				Errorcode = JABORT;
319 				logerr(LOG_INFO, "Print_job:  could not make '%s' process",
320 					Pr_program_DYN );
321 				goto end_of_job;
322 			}
323 			if( tempfd != fd ){
324 				if( dup2(tempfd,fd) == -1 ){
325 					Errorcode = JABORT;
326 					logerr(LOG_INFO, "Print_job:  dup2(%d,%d) failed", tempfd, fd );
327 				}
328 				close(tempfd);
329 			}
330 			if( fstat(fd, &statb ) == -1 ){
331 				Errorcode = JABORT;
332 				logerr(LOG_INFO, "Print_job: fstat() failed");
333 			}
334 			setstatus(job, "data file '%s', size now %0.0f",
335 				transfername, (double)statb.st_size );
336 		}
337 		for( copy = 0; copy < copies; ++copy ){
338 			if( fd && lseek(fd,0,SEEK_SET) == -1 ){
339 				Errorcode = JABORT;
340 				logerr(LOG_INFO, "Print_job:  lseek tempfd failed");
341 				goto end_of_job;
342 			}
343 			if( fstat(fd, &statb ) == -1 ){
344 				Errorcode = JABORT;
345 				logerr(LOG_INFO, "Print_job: fstat() failed");
346 			}
347 			DEBUG1("Print_job: copy %d, data file '%s', size now %0.0f", copy,
348 				transfername, (double)statb.st_size );
349 			if( copies > 1 ){
350 				setstatus(job, "doing copy %d of %d", copy+1, copies );
351 			}
352 			if(DEBUGL5){
353 				LOGDEBUG("Print_job: doing '%s' open fd's", openname);
354 				for( i = 0; i < 20; ++i ) if( fstat(i,&statb) == 0 )
355 					 LOGDEBUG("  fd %d (0%o)", i, (unsigned int)(statb.st_mode&S_IFMT));
356 			}
357 			Init_buf(&Outbuf, &Outmax, &Outlen );
358 			if( files_printed++ && (!No_FF_separator_DYN || FF_separator_DYN) && FF_str ){
359 				/* FF separator -> of_fd; */
360 				setstatus(job, "printing '%s' FF separator ",id);
361 				Put_buf_str( FF_str, &Outbuf, &Outmax, &Outlen );
362 			}
363 			/* do we have output for the OF device/filter ? */
364 			if( Outlen > 0 ){
365 				Set_block_io( output );
366 				/* yes */
367 				if( OF_Filter_DYN ){
368 					/* send it to the OF filter */
369 					if( Run_OF_filter( send_job_rw_timeout, &of_pid, &of_stdin, &of_stderr,
370 						output, &Outbuf, &Outmax, &Outlen,
371 						job, id, 0,
372 						msgbuffer, sizeof(msgbuffer)-1 ) ){
373 						goto exit;
374 					}
375 				} else {
376 					/* send it to the OF device */
377 					n = Write_outbuf_to_OF(job,"LP",output, Outbuf, Outlen,
378 						status_device, msgbuffer, sizeof(msgbuffer)-1,
379 						send_job_rw_timeout, poll_for_status, Status_file_DYN );
380 					if( n ){
381 						Errorcode = n;
382 						setstatus(job, "error writing to device '%s'",
383 							Server_status(n));
384 						goto end_of_job;
385 					}
386 				}
387 				Init_buf(&Outbuf, &Outmax, &Outlen );
388 			}
389 
390 			Set_block_io( output );
391 			if( filter ){
392 				DEBUG3("Print_job: format '%s' starting filter '%s'",
393 					format, filter );
394 				DEBUG2("Print_job: filter_stderr_to_status_file %d, ps '%s'",
395 					Filter_stderr_to_status_file_DYN, Status_file_DYN );
396 				if_error[0] = if_error[1] = -1;
397 				if( Filter_stderr_to_status_file_DYN && Status_file_DYN && *Status_file_DYN ){
398 					if_error[1] = Checkwrite( Status_file_DYN, &statb, O_WRONLY|O_APPEND, 0, 0 );
399 				} else if( pipe( if_error ) == -1 ){
400 					Errorcode = JFAIL;
401 					logerr(LOG_INFO, "Print_job: pipe() failed");
402 					goto end_of_job;
403 				}
404 				Max_open(if_error[0]); Max_open(if_error[1]);
405 				DEBUG3("Print_job: %s fd if_error[%d,%d]", filter_title,
406 					 if_error[0], if_error[1] );
407 				s = 0;
408 				if( Backwards_compatible_filter_DYN ) s = BK_filter_options_DYN;
409 				if( s == 0 ) s = Filter_options_DYN;
410 
411 				Free_line_list(&files);
412 				Check_max(&files, 10 );
413 				files.list[files.count++] = Cast_int_to_voidstar(fd);		/* stdin */
414 				files.list[files.count++] = Cast_int_to_voidstar(output);	/* stdout */
415 				files.list[files.count++] = Cast_int_to_voidstar(if_error[1]);	/* stderr */
416 				if( (pid = Make_passthrough( filter, s, &files, job, 0 )) < 0 ){
417 					Errorcode = JFAIL;
418 					logerr(LOG_INFO, "Print_job:  could not make %s process",
419 						filter_title );
420 					goto end_of_job;
421 				}
422 				files.count = 0;
423 				Free_line_list(&files);
424 
425 				if( (close(if_error[1]) == -1 ) ){
426 					Errorcode = JFAIL;
427 					logerr_die(LOG_INFO, "Print_job: X5 close(%d) failed",
428 						if_error[1]);
429 				}
430 				if_error[1] = -1;
431 				Init_buf(&Outbuf, &Outmax, &Outlen );
432 
433 				filtermsgbuffer[0] = 0;
434 				if( if_error[0] != -1 ){
435 					n = Get_status_from_OF(job,filter_title,pid,
436 						if_error[0], filtermsgbuffer, sizeof(filtermsgbuffer)-1,
437 						send_job_rw_timeout, 0, 0, Status_file_DYN );
438 					if( filtermsgbuffer[0] ){
439 						setstatus(job, "%s filter msg - '%s'", filter_title, filtermsgbuffer );
440 					}
441 					if( n ){
442 						Errorcode = n;
443 						setstatus(job, "%s filter problems, error '%s'",
444 							filter_title, Server_status(n));
445 						goto end_of_job;
446 					}
447 					close(if_error[0]);
448 					if_error[0] = -1;
449 				}
450 				time_left = send_job_rw_timeout;
451 				while(1){
452 					/* now we get the exit status for the filter */
453 					n = Wait_for_pid( pid, filter_title, 0, time_left );
454 					switch(n){
455 						case JSUCC: break;
456 						case JTIMEOUT:
457 							/* get the timeout value */
458 							if( send_job_rw_timeout > 0
459 								&& Status_file_DYN
460 								&& !stat(Status_file_DYN, &statb) ){
461 								int delta = time(0) - statb.st_mtime;
462 								/* OK, we need to wait a bit longer */
463 								if( delta < send_job_rw_timeout ){
464 									time_left = send_job_rw_timeout - delta;
465 									continue;
466 								}
467 							}
468 						default:
469 							Errorcode = n;
470 							setstatus(job, "%s filter exit status '%s'",
471 								filter_title, Server_status(n));
472 							goto end_of_job;
473 					}
474 					setstatus(job, "%s filter finished", filter_title );
475 					break;
476 				}
477 			} else {
478 				/* we write to the output device, and then get status */
479 				DEBUG3("Print_job: format '%s' no filter, reading from %d",
480 					format, fd );
481 				Init_buf(&Outbuf, &Outmax, &Outlen );
482 				while( (Outlen = Read_fd_len_timeout(send_job_rw_timeout,fd,Outbuf,Outmax)) > 0 ){
483 					Outbuf[Outlen] = 0;
484 					n = Write_outbuf_to_OF(job,"LP",output, Outbuf, Outlen,
485 						status_device, msgbuffer, sizeof(msgbuffer)-1,
486 						send_job_rw_timeout, poll_for_status, Status_file_DYN );
487 					if( n ){
488 						Errorcode = JFAIL;
489 						setstatus(job, "error '%s'", Server_status(n));
490 						goto end_of_job;
491 					}
492 				}
493 				if( Outlen < 0 ){
494 					Errorcode = JFAIL;
495 					setstatus(job, "error reading file '%s'", Errormsg(errno));
496 					goto end_of_job;
497 				}
498 				Outlen = 0;
499 			}
500 			DEBUG3("Print_job: finished copy");
501 		}
502 		DEBUG3("Print_job: finished file");
503 	}
504 
505 	/*
506 	 * now we do the end
507 	 */
508  end_of_job:
509 
510 	DEBUG3("Print_job: end of job");
511 	Init_buf(&Outbuf, &Outmax, &Outlen );
512 
513 	/* check for the banner at the end */
514 
515 	if( do_banner && (Banner_last_DYN || Banner_end_DYN) ){
516 		Print_banner( banner_name, Banner_end_DYN, job );
517 	}
518 
519 	/*
520 	 * FF_on_close_DYN     -> of_fd;
521 	 */
522 	if( FF_on_close_DYN ) Put_buf_str( FF_str, &Outbuf, &Outmax, &Outlen );
523 
524 	/*
525 	 * Trailer_on_close_DYN -> of_fd;
526 	 */
527 	if( trailer_str ) Put_buf_str( trailer_str, &Outbuf, &Outmax, &Outlen );
528 
529 	/*
530 	 * close the OF Filters
531 	 */
532 
533 	Set_block_io( output );
534 	if( OF_Filter_DYN ){
535 		if( Run_OF_filter( send_job_rw_timeout, &of_pid, &of_stdin, &of_stderr,
536 			output, &Outbuf, &Outmax, &Outlen,
537 			job, id, 1,
538 			msgbuffer, sizeof(msgbuffer)-1 ) ){
539 			goto exit;
540 		}
541 	} else {
542 		if( Outlen ){
543 			n = Write_outbuf_to_OF(job,"LP",output, Outbuf, Outlen,
544 				status_device, msgbuffer, sizeof(msgbuffer)-1,
545 				send_job_rw_timeout, poll_for_status, Status_file_DYN );
546 			if( n && Errorcode == 0 ){
547 				Errorcode = JFAIL;
548 				setstatus(job, "LP device write error '%s'", Errormsg(errno));
549 				goto exit;
550 			}
551 		}
552 		if( msgbuffer[0] ){
553 			setstatus(job, "%s filter msg - '%s'", "LP", msgbuffer );
554 		}
555 	}
556 	Init_buf(&Outbuf, &Outmax, &Outlen );
557 #ifdef HAVE_TCDRAIN
558 	if( isatty( output ) && tcdrain( output ) == -1 ){
559 		logerr_die(LOG_INFO, "Print_job: tcdrain failed");
560 	}
561 #endif
562 	setstatus(job, "printing finished");
563 
564  exit:
565 	Init_buf(&Outbuf, &Outmax, &Outlen );
566 	if( Outbuf ) free(Outbuf); Outbuf = 0;
567 	if(FF_str) free(FF_str);
568 	if(leader_str) free(leader_str);
569 	if(trailer_str) free(trailer_str);
570 	if( of_stdin != -1 ) close(of_stdin); of_stdin = -1;
571 	if( of_stderr != -1 ) close(of_stderr); of_stderr = -1;
572 	if( tempfd != -1 ) close(tempfd); tempfd = -1;
573 	if( fd != -1 ) close(fd); fd = -1;
574 	if(DEBUGL3){
575 		LOGDEBUG("Print_job: at end open fd's");
576 		for( i = 0; i < 20; ++i ){
577 			if( fstat(i,&statb) == 0 ){
578 				LOGDEBUG("  fd %d (0%o)", i, (unsigned int)(statb.st_mode&S_IFMT));
579 			}
580 		}
581 	}
582 	return( Errorcode );
583 }
584 
585 /*
586  * int Create_OF_filter( int *of_stdin, int *of_stderr )
587  *  of_stdin = STDIN of filter (writable)
588  *  of_stderr = STDERR of filter (readable)
589  *   - we create the OF filter and return the PID
590  *  RETURNS:
591  *
592  */
593 
594  static const char *Filter_stop = "\031\001";
595 
Run_OF_filter(int send_job_rw_timeout,int * of_pid,int * of_stdin,int * of_stderr,int output,char ** outbuf,int * outmax,int * outlen,struct job * job,const char * id,int terminate_of,char * msgbuffer,int msglen)596 static int Run_OF_filter( int send_job_rw_timeout, int *of_pid, int *of_stdin, int *of_stderr,
597 	int output, char **outbuf, int *outmax, int *outlen,
598 	struct job *job, const char *id, int terminate_of,
599 	char *msgbuffer, int msglen )
600 {
601 	char msg[SMALLBUFFER];
602 	char *s;
603 	int of_error[2], of_fd[2], n, time_left;
604 	struct stat statb;
605 	struct line_list files;
606 
607 	if( *of_pid < 0 ){
608 		Init_line_list(&files);
609 		of_fd[0] = of_fd[1] = of_error[0] = of_error[1] = -1;
610 		*of_stdin = *of_stderr = -1;
611 		if( !(s = strchr( OF_Filter_DYN, '/' )) ) s = OF_Filter_DYN;
612 		plp_snprintf( msg, sizeof(msg), "%s", s );
613 		if( (s = strpbrk( msg, Whitespace )) ) *s = 0;
614 		if( (s = strrchr( msg, '/')) ){
615 			memmove( msg, s+1, safestrlen(s)+1 );
616 		}
617 		setstatus(job, "printing '%s' starting OF '%s'", id, msg );
618 		if( pipe( of_fd ) == -1 ){
619 			Errorcode = JFAIL;
620 			logerr(LOG_INFO, "Run_OF_filter: pipe() failed");
621 			goto exit;
622 		}
623 		Max_open(of_fd[0]); Max_open(of_fd[1]);
624 		DEBUG2("Run_OF_filter: errors_to_ps %d, ps '%s'", Filter_stderr_to_status_file_DYN,
625 			Status_file_DYN );
626 		of_error[0] = of_error[1] = -1;
627 		if( Filter_stderr_to_status_file_DYN && Status_file_DYN && *Status_file_DYN ){
628 			of_error[1] = Checkwrite( Status_file_DYN, &statb, O_WRONLY|O_APPEND, 0, 0 );
629 		} else if( pipe( of_error ) == -1 ){
630 			Errorcode = JFAIL;
631 			logerr(LOG_INFO, "Run_OF_filter: pipe() failed");
632 			goto exit;
633 		}
634 		Max_open(of_error[0]); Max_open(of_error[1]);
635 		DEBUG3("Run_OF_filter: fd of_fd[%d,%d], of_error[%d,%d]",
636 			of_fd[0], of_fd[1], of_error[0], of_error[1] );
637 
638 		/* set format */
639 		Set_str_value(&job->info,FORMAT,"o");
640 		/* set up file descriptors */
641 
642 		s = 0;
643 		if( Backwards_compatible_filter_DYN ) s = BK_of_filter_options_DYN;
644 		if( s == 0 ) s = OF_filter_options_DYN;
645 		if( s == 0 ) s = Filter_options_DYN;
646 
647 		Check_max(&files,10);
648 		files.list[files.count++] = Cast_int_to_voidstar(of_fd[0]);	/* stdin */
649 		files.list[files.count++] = Cast_int_to_voidstar(output);	/* stdout */
650 		files.list[files.count++] = Cast_int_to_voidstar(of_error[1]);	/* stderr */
651 		if( (*of_pid = Make_passthrough( OF_Filter_DYN, s,&files, job, 0 ))<0){
652 			Errorcode = JFAIL;
653 			logerr(LOG_INFO, "Run_OF_filter: could not create OF process");
654 			goto exit;
655 		}
656 		files.count = 0;
657 		Free_line_list(&files);
658 
659 		DEBUG3("Run_OF_filter: OF pid %d", *of_pid );
660 		if( of_fd[0] > 0 &&  (close( of_fd[0] ) == -1 ) ){
661 			Errorcode = JFAIL;
662 			logerr(LOG_INFO, "Run_OF_filter: X0 close(%d) failed", of_fd[0]);
663 			goto exit;
664 		}
665 		of_fd[0] = -1;
666 		if( of_error[1] > 0 && (close( of_error[1] ) == -1 ) ){
667 			Errorcode = JFAIL;
668 			logerr(LOG_INFO, "Run_OF_filter: X1 close(%d) failed", of_error[1]);
669 			goto exit;
670 		}
671 		of_error[1] = -1;
672 		DEBUG3("Run_OF_filter: writing init to OF pid '%d', count %d", *of_pid, *outlen );
673 
674 		*of_stderr = of_error[0];
675 		*of_stdin = of_fd[1];
676 	} else {
677 		DEBUG3("Run_OF_filter: SIGCONT to to OF pid '%d'", *of_pid );
678 		kill( *of_pid, SIGCONT );
679 	}
680 	if( Suspend_OF_filter_DYN && !terminate_of ){
681 		DEBUG3("Run_OF_filter: stopping OF pid '%d'", *of_pid );
682 		Put_buf_str( Filter_stop, outbuf, outmax, outlen );
683 		n = Write_outbuf_to_OF(job,"OF",*of_stdin,
684 			*outbuf, *outlen,
685 			*of_stderr, msgbuffer, msglen,
686 			send_job_rw_timeout, 0, Status_file_DYN );
687 		if( n == 0 ){
688 			n = Get_status_from_OF(job,"OF",*of_pid,
689 				*of_stderr, msgbuffer, msglen,
690 				send_job_rw_timeout, 1, Filter_poll_interval_DYN, Status_file_DYN );
691 		}
692 		if( n != JSUSP ){
693 			Errorcode = n;
694 			setstatus(job, "OF filter problems, error '%s'", Server_status(n));
695 			goto exit;
696 		}
697 		setstatus(job, "OF filter suspended" );
698 	} else {
699 		DEBUG3("Run_OF_filter: end OF pid '%d'", *of_pid );
700 		n = Write_outbuf_to_OF(job,"OF",*of_stdin,
701 			*outbuf, *outlen,
702 			*of_stderr, msgbuffer, msglen,
703 			send_job_rw_timeout, 0, Status_file_DYN );
704 		if( n ){
705 			Errorcode = n;
706 			setstatus(job, "OF filter problems, error '%s'", Server_status(n));
707 			goto exit;
708 		}
709 		close( *of_stdin );
710 		*of_stdin = -1;
711 		n = Get_status_from_OF(job,"OF",*of_pid,
712 			*of_stderr, msgbuffer, msglen,
713 			send_job_rw_timeout, 0, 0, Status_file_DYN );
714 		if( n ){
715 			Errorcode = n;
716 			setstatus(job, "OF filter problems, error '%s'", Server_status(n));
717 			goto exit;
718 		}
719 		close( *of_stderr );
720 		*of_stderr = -1;
721 		/* now we get the exit status for the filter */
722 		time_left = send_job_rw_timeout;
723 		while(1){
724 			/* now we get the exit status for the filter */
725 			n = Wait_for_pid( *of_pid, "OF", 0, time_left );
726 			switch(n){
727 				case JSUCC: break;
728 				case JTIMEOUT:
729 					/* get the timeout value */
730 					if( send_job_rw_timeout > 0
731 						&& Status_file_DYN
732 						&& !stat(Status_file_DYN, &statb) ){
733 						int delta = time(0) - statb.st_mtime;
734 						/* OK, we need to wait a bit longer */
735 						if( delta < send_job_rw_timeout ){
736 							time_left = send_job_rw_timeout - delta;
737 							continue;
738 						}
739 					}
740 				default:
741 					Errorcode = n;
742 					setstatus(job, "%s filter exit status '%s'",
743 						"OF", Server_status(n));
744 					goto exit;
745 			}
746 			setstatus(job, "%s filter finished", "OF" );
747 			break;
748 		}
749 		*of_pid = -1;
750 	}
751 	return( 0 );
752  exit:
753 	return( -1 );
754 }
755 
756 /*
757  * Print a banner
758  * check for a small or large banner as necessary
759  */
760 
Print_banner(const char * name,char * pgm,struct job * job)761 static void Print_banner( const char *name, char *pgm, struct job *job )
762 {
763 	char buffer[LARGEBUFFER];
764 	int len, n;
765 	char *bl = 0;
766 	int tempfd;
767 
768 	/*
769 	 * print the banner
770 	 */
771 	if(DEBUGL3){
772 		struct stat statb; int i;
773 		LOGDEBUG("Print_banner: at start open fd's");
774 		for( i = 0; i < 20; ++i ){
775 			if( fstat(i,&statb) == 0 ){
776 				LOGDEBUG("  fd %d (0%o)", i, (unsigned int)(statb.st_mode&S_IFMT));
777 			}
778 		}
779 	}
780 	if( !pgm ) pgm = Banner_printer_DYN;
781 
782 	DEBUG2( "Print_banner: name '%s', pgm '%s', sb=%d, Banner_line_DYN '%s'",
783 		name, pgm, Short_banner_DYN, Banner_line_DYN );
784 
785 	if( !pgm && !Short_banner_DYN ){
786 		return;
787 	}
788 
789  	if( pgm ){
790 		/* we now need to create a banner */
791 		setstatus(job, "creating banner");
792 
793 		tempfd = Make_temp_fd(0);
794 		n = Filter_file( Send_job_rw_timeout_DYN, -1, tempfd, "BANNER",
795 			pgm, Filter_options_DYN, job, 0, 1 );
796 		if( n ){
797 			Errorcode = JFAIL;
798 			logerr_die(LOG_INFO,
799 			"Print_banner: banner pgr '%s' exit status '%s'",
800 			pgm, Server_status(n));
801 		}
802 
803 		if( lseek(tempfd,0,SEEK_SET) == -1 ){
804 			Errorcode = JFAIL;
805 			logerr_die(LOG_INFO, "Print_banner: fseek(%d) failed", tempfd);
806 		}
807 		len = Outlen;
808 		while( (n = ok_read(tempfd, buffer, sizeof(buffer))) > 0 ){
809 			Put_buf_len(buffer, n, &Outbuf, &Outmax, &Outlen );
810 		}
811 		if( (close(tempfd) == -1 ) ){
812 			Errorcode = JFAIL;
813 			logerr_die(LOG_INFO, "Print_banner: Xa close(%d) failed",
814 				tempfd);
815 		}
816 		DEBUG4("Print_banner: BANNER '%s'", Outbuf+len);
817 	} else {
818 		struct line_list l;
819 		Init_line_list(&l);
820 		setstatus(job, "inserting short banner line");
821 		Add_line_list(&l,Banner_line_DYN,0,0,0);
822 		Fix_dollars(&l,job,1,Filter_options_DYN);
823 		bl = safestrdup2(l.list[0],"\n",__FILE__,__LINE__);
824 		Put_buf_str( bl, &Outbuf, &Outmax, &Outlen );
825 		Free_line_list(&l);
826 		if( bl ) free(bl); bl = 0;
827 	}
828 	if(DEBUGL3){
829 		struct stat statb; int i;
830 		LOGDEBUG("Print_banner: at end open fd's");
831 		for( i = 0; i < 20; ++i ){
832 			if( fstat(i,&statb) == 0 ){
833 				LOGDEBUG("  fd %d (0%o)", i, (unsigned int)(statb.st_mode&S_IFMT));
834 			}
835 		}
836 	}
837 }
838 
839 /*
840  * Write_outbuf_to_OF(
841  * int of_fd, buffer, outlen     - write to this
842  * int of_error  - read status from this
843  * char *msg, int msgmax - status storage area
844  * int timeout   - timeout
845  *                 nnn - wait this long
846  *                 0   - wait indefinitely
847  *                 -1  - do not wait
848  * poll for status
849  * )
850  * We write the output buffer to the OF process, and then wait for it to
851  * either exit or suspend itself.
852  *     JSUCC    = 0
853  *     JTIMEOUT  - timeout
854  *     JWRERR     -  (-1 originally) - error reading or writing
855  *     JRDERR     -  (-1 originally) - error reading or writing
856  */
857 
Write_outbuf_to_OF(struct job * job,const char * title,int of_fd,char * buffer,int outlen,int of_error,char * msg,int msgmax,int timeout,int poll_for_status,char * status_file)858 static int Write_outbuf_to_OF( struct job *job, const char *title,
859 	int of_fd, char *buffer, int outlen,
860 	int of_error, char *msg, int msgmax,
861 	int timeout, int poll_for_status, char *status_file )
862 {
863 	time_t start_time, current_time;
864 	int msglen, return_status, count, elapsed, left;
865 	struct stat statb;
866 	char *s;
867 
868 	DEBUG3(
869 		"Write_outbuf_to_OF: len %d, of_fd %d, of_error %d, timeout %d, poll_for_status %d",
870 		outlen, of_fd, of_error, timeout, poll_for_status );
871 
872 	start_time = time((void *)0);
873 	return_status = 0;
874 	if( outlen == 0 ) return return_status;
875 	if( of_fd >= 0 && fstat( of_fd, &statb ) ){
876 		Errorcode = JABORT;
877 		logerr_die(LOG_INFO, "Write_outbuf_to_OF: %s, of_fd %d closed!",
878 		title, of_fd );
879 	}
880 	if( of_error > 0 && fstat( of_error, &statb ) ){
881 		logerr(LOG_INFO, "Write_outbuf_to_OF: %s, of_error %d closed!",
882 			title, of_error );
883 		of_error = -1;
884 	}
885 	if( of_error < 0 ){
886 		return_status = Write_fd_len_timeout( timeout, of_fd, buffer, outlen );
887 		DEBUG4("Write_outbuf_to_OF: Write_fd_len_timeout result %d", return_status );
888 	} else if( poll_for_status ){
889 		return_status = Write_fd_len_timeout( timeout, of_fd, buffer, outlen );
890 		DEBUG4("Write_outbuf_to_OF: Write_fd_len_timeout result %d", return_status );
891 		do {
892 			msglen = safestrlen(msg);
893 			if( msglen >= msgmax ){
894 				setstatus(job, "%s filter msg - '%s'", title, msg );
895 				msg[0] = 0;
896 				msglen = 0;
897 			}
898 			count = -1;
899 			/* we put a 1 second timeout here, just to make sure */
900 			Set_block_io( of_error );
901 			count = Read_fd_len_timeout( 1, of_error, msg+msglen, msgmax-msglen );
902 			Set_nonblock_io( of_error );
903 			if( count > 0 ){
904 				msglen += count;
905 				msg[msglen] = 0;
906 				while( (s = safestrchr(msg,'\n')) ){
907 					*s++ = 0;
908 					setstatus(job, "%s filter msg - '%s'", title, msg );
909 					memmove(msg,s,safestrlen(s)+1);
910 				}
911 			}
912 		} while( count > 0 );
913 	} else while( return_status == 0 && outlen > 0 ){
914 		left = timeout;
915 		if( timeout > 0 ){
916 			current_time = time((void *)0);
917 			elapsed = current_time - start_time;
918 			left = timeout - elapsed;
919 			if( left <= 0 ){
920 				if( status_file && !stat(status_file, &statb) ){
921 					int interval = current_time - statb.st_mtime;
922 					if( interval < timeout ){
923 						start_time = statb.st_mtime;
924 						elapsed = current_time - start_time;
925 						left = timeout - elapsed;
926 					} else {
927 						return_status = JTIMEOUT;
928 						break;
929 					}
930 				} else {
931 					return_status = JTIMEOUT;
932 					break;
933 				}
934 			}
935 		}
936 		msglen = safestrlen(msg);
937 		if( msglen >= msgmax ){
938 			setstatus(job, "%s filter msg - '%s'", title, msg );
939 			msg[0] = 0;
940 			msglen = 0;
941 		}
942 		count = -1;	/* number read into msg buffer */
943 		DEBUG4("Write_outbuf_to_OF: writing %d", outlen );
944 		return_status = Read_write_timeout( of_error, msg+msglen, msgmax-msglen, &count,
945 			of_fd, &buffer, &outlen, left );
946 		DEBUG4("Write_outbuf_to_OF: return_status %d, count %d, '%s'",
947 			return_status, count, msg);
948 		if( DEBUGL4 ){
949 			char smb[32]; plp_snprintf(smb,sizeof(smb), "%s",msg);
950 			logDebug("Write_outbuf_to_OF: writing '%s...'", smb );
951 		}
952 		if( count > 0 ){
953 			msglen += count;
954 			msg[msglen] = 0;
955 			s = msg;
956 			while( (s = safestrchr(msg,'\n')) ){
957 				*s++ = 0;
958 				setstatus(job, "%s filter msg - '%s'", title, msg );
959 				memmove(msg,s,safestrlen(s)+1);
960 			}
961 		}
962 	}
963 	if( return_status < 0 ) return_status = JWRERR;
964 	DEBUG3("Write_outbuf_to_OF: after write return_status %d, of_fd %d, of_error %d",
965 		return_status, of_fd, of_error );
966 	/* read and see if there is any status coming back */
967 	return( return_status );
968 }
969 
970 /*
971  * int Get_status_from_OF( struct job *job, char *title, int of_pid,
972  *    int of_error, char *msg, int msgmax,
973  *	  int timeout, int suspend, int max_wait )
974  * return:
975  *   0 successful
976  *   JTIMEOUT - timeout
977  */
978 
Get_status_from_OF(struct job * job,const char * title,int of_pid,int of_error,char * msg,int msgmax,int timeout,int suspend,int max_wait,char * status_file)979 int Get_status_from_OF( struct job *job, const char *title, int of_pid,
980 	int of_error, char *msg, int msgmax,
981 	int timeout, int suspend, int max_wait, char *status_file )
982 {
983 	time_t start_time, current_time;
984 	int m, msglen, return_status, count, elapsed, left, done;
985 	struct stat statb;
986 	char *s;
987 
988 	start_time = time((void *)0);
989 	DEBUG3( "Get_status_from_OF: pid %d, of_error %d, timeout %d",
990 		of_pid, of_error, timeout );
991 
992 	return_status = 0;
993 
994 	if( fstat( of_error, &statb ) ){
995 		Errorcode = JABORT;
996 		logerr_die(LOG_INFO, "Get_status_from_OF: %s, of_error %d closed!",
997 			title, of_error );
998 	}
999 
1000 	done = 0;
1001 	left = timeout;
1002 	while( !done ){
1003 		if( timeout > 0 ){
1004 			current_time = time((void *)0);
1005 			elapsed = current_time - start_time;
1006 			left = timeout - elapsed;
1007 			if( left <= 0 ){
1008 				if( status_file && !stat(status_file, &statb) ){
1009 					int interval = current_time - statb.st_mtime;
1010 					if( interval < timeout ){
1011 						start_time = statb.st_mtime;
1012 						elapsed = current_time - start_time;
1013 						left = timeout - elapsed;
1014 					} else {
1015 						return_status = JTIMEOUT;
1016 						break;
1017 					}
1018 				} else {
1019 					return_status = JTIMEOUT;
1020 					break;
1021 				}
1022 			}
1023 		}
1024 		DEBUG3("Get_status_from_OF: waiting for '%s', left %d secs for pid %d",
1025 			suspend?"suspend":"exit", left, of_pid );
1026 		count = -1;
1027 		m = 0;
1028 		/* we see if we have output */
1029 		if( suspend ){
1030 			/* poll for process suspend status */
1031 			left = max_wait>0?max_wait:1;
1032 			DEBUG3("Get_status_from_OF: polling interval %d", left );
1033 			return_status = Wait_for_pid( of_pid, title, suspend, left );
1034 			DEBUG4("Get_status_from_OF: return_status '%s'", Server_status(return_status));
1035 			/* we do a poll, just to see if the process is blocked because the
1036 			 * pipe is full.  We may need to read the pipe to clear out the buffer
1037 			 * so it can exit.  This is really an unusual condition,  but it can happen.
1038 			 */
1039 			if( return_status != JTIMEOUT ){
1040 				done = 1;
1041 			}
1042 			DEBUG4("Get_status_from_OF: now reading, after suspend" );
1043 			do{
1044 				msglen = safestrlen(msg);
1045 				if( msglen >= msgmax ){
1046 					setstatus(job, "%s filter msg - '%s'", title, msg );
1047 					msg[0] = 0;
1048 					msglen = 0;
1049 				}
1050 				count = -1;
1051 				Set_nonblock_io( of_error );
1052 				count = ok_read( of_error, msg+msglen, msgmax-msglen );
1053 				Set_block_io( of_error );
1054 				if( count > 0 ){
1055 					while( (s = safestrchr(msg,'\n')) ){
1056 						*s++ = 0;
1057 						setstatus(job, "%s filter msg - '%s'", title, msg );
1058 						memmove(msg,s,safestrlen(s)+1);
1059 					}
1060 				}
1061 			} while( count > 0 );
1062 		} else do {
1063 			/* now we read the error output, just in case there is something there */
1064 			DEBUG4("Get_status_from_OF: now reading on fd %d, left %d",
1065 				of_error, left );
1066 			msglen = safestrlen(msg);
1067 			if( msglen >= msgmax ){
1068 				setstatus(job, "%s filter msg - '%s'", title, msg );
1069 				msg[0] = 0;
1070 				msglen = 0;
1071 			}
1072 			Set_block_io( of_error );
1073 			count = Read_fd_len_timeout( left, of_error, msg+msglen, msgmax-msglen );
1074 			if( count > 0 ){
1075 				msglen += count;
1076 				msg[msglen] = 0;
1077 				s = msg;
1078 				while( (s = safestrchr(msg,'\n')) ){
1079 					*s++ = 0;
1080 					setstatus(job, "%s filter msg - '%s'", title, msg );
1081 					memmove(msg,s,safestrlen(s)+1);
1082 				}
1083 			} else if( count == 0 ){
1084 				done = 1;
1085 			}
1086 		} while( count > 0 );
1087 	}
1088 	return(return_status);
1089 }
1090 
1091 /****************************************************************************
1092  * int Wait_for_pid( int of_pid, char *name, int suspend, int timeout )
1093  * of_pid     = pid of the process
1094  * name       = name for messages
1095  * suspend    = 1 if you want to wait for suspend, now exit
1096  * timeout    = length of time to wait - 0 is infinite, -1 is none
1097  *
1098  * returns:
1099  *  JSUCC = 0  - successful error code exit
1100  *  JSUSP      - successful suspend
1101  *  JSIGNAL    - signal exit code
1102  *    >0       - exit code
1103  *  JTIMEOUT   - EINTR error, probably a timeout
1104  *  JCHILD     - ECHILD error
1105  *  JNOWAIT    - nonblocking check, no status
1106  *
1107  ****************************************************************************/
1108 
Wait_for_pid(int of_pid,const char * name,int suspend,int timeout)1109 int Wait_for_pid( int of_pid, const char *name, int suspend, int timeout )
1110 {
1111 	int pid, err, return_code;
1112  	plp_status_t ps_status;
1113 
1114 	DEBUG2("Wait_for_pid: name '%s', pid %d, suspend %d, timeout %d",
1115 		name, of_pid, suspend, timeout );
1116 	errno = 0;
1117 	memset(&ps_status,0,sizeof(ps_status));
1118 	if( timeout > 0 ){
1119 		Set_timeout_break( timeout );
1120 		pid = plp_waitpid(of_pid,&ps_status,suspend?WUNTRACED:0 );
1121 		err = errno;
1122 		Clear_timeout();
1123 	} else if( timeout == 0 ){
1124 		pid = plp_waitpid(of_pid,&ps_status,suspend?WUNTRACED:0);
1125 		err = errno;
1126 	} else {
1127 		pid = plp_waitpid(of_pid,&ps_status,(suspend?WUNTRACED:0)|WNOHANG);
1128 		err = errno;
1129 	}
1130 	DEBUG2("Wait_for_pid: pid %d exit status '%s'",
1131 		pid, Decode_status(&ps_status));
1132 	return_code = 0;
1133 	if( pid > 0 ){
1134 		if( WIFSTOPPED(ps_status) ){
1135 			return_code = JSUSP;
1136 			DEBUG1("Wait_for_pid: %s filter suspended", name );
1137 		} else if( WIFEXITED(ps_status) ){
1138 			return_code = WEXITSTATUS(ps_status);
1139 			if( return_code > 0 && return_code < 32 ) return_code += JFAIL-1;
1140 			DEBUG3( "Wait_for_pid: %s filter exited with status %d",
1141 				name, return_code);
1142 		} else if( WIFSIGNALED(ps_status) ){
1143 			int n;
1144 			n = WTERMSIG(ps_status);
1145 			logmsg(LOG_INFO,
1146 				"Wait_for_pid: %s filter died with signal '%s'",name,
1147 				Sigstr(n));
1148 			return_code = JSIGNAL;
1149 		} else {
1150 			return_code = JABORT;
1151 			logmsg(LOG_INFO,
1152 				"Wait_for_pid: %s filter did strange things",name);
1153 		}
1154 	} else if( pid < 0 ){
1155 		/* you got an error, and it was ECHILD or EINTR
1156 		 * if it was EINTR, you want to know
1157 		 */
1158 		if( err == EINTR ) return_code = JTIMEOUT;
1159 		else return_code = JCHILD;
1160 	} else {
1161 		return_code = JNOWAIT;
1162 	}
1163 	DEBUG1("Wait_for_pid: returning '%s', exit status '%s'",
1164 		Server_status(return_code), Decode_status(&ps_status) );
1165 	errno = err;
1166 	return( return_code );
1167 }
1168 
1169 /* moved here from lpd_jobs.c as it is now called also here and lpd_jobs.c
1170  * is only linked into the server, not the clients - brl*/
1171 
Add_banner_to_job(struct job * job)1172 void Add_banner_to_job( struct job *job )
1173 {
1174 	const char *banner_name;
1175 	char *tempfile;
1176 	struct line_list *lp;
1177 	int tempfd;
1178 
1179 	Errorcode = 0;
1180     banner_name = Find_str_value(&job->info, BNRNAME );
1181     if( banner_name == 0 ){
1182         banner_name = Find_str_value( &job->info,LOGNAME);
1183 	}
1184 	if( banner_name == 0 ) banner_name = "ANONYMOUS";
1185 	Set_str_value(&job->info,BNRNAME,banner_name);
1186     banner_name = Find_str_value(&job->info, BNRNAME );
1187 	DEBUG1("Add_banner_to_job: banner name '%s'", banner_name );
1188 	if( !Banner_last_DYN ){
1189 		DEBUG1("Add_banner_to_job: banner at start");
1190 		Init_buf(&Outbuf, &Outmax, &Outlen );
1191 		Print_banner( banner_name, Banner_start_DYN, job );
1192         tempfd = Make_temp_fd(&tempfile);
1193 		if( Write_fd_len( tempfd, Outbuf, Outlen ) < 0 ){
1194 			logerr(LOG_INFO, "Add_banner_to_job: write to '%s' failed", tempfile );
1195 			Errorcode = JABORT;
1196 			return;
1197 		}
1198 		close(tempfd);
1199 		lp = malloc_or_die(sizeof(lp[0]),__FILE__,__LINE__);
1200 		memset(lp,0,sizeof(lp[0]));
1201 		Check_max(&job->datafiles,1);
1202 		memmove( &job->datafiles.list[1], &job->datafiles.list[0],
1203 			job->datafiles.count * sizeof(job->datafiles.list[0]) );
1204 		job->datafiles.list[0] = (void *)lp;
1205 		++job->datafiles.count;
1206 
1207 		Set_str_value(lp,OPENNAME,tempfile);
1208 		Set_str_value(lp,DFTRANSFERNAME,tempfile);
1209 		Set_str_value(lp,"N","BANNER");
1210 		Set_str_value(lp,FORMAT,"f");
1211 	}
1212 	if( Banner_last_DYN || Banner_end_DYN) {
1213 		Init_buf(&Outbuf, &Outmax, &Outlen );
1214 		Print_banner( banner_name, Banner_end_DYN, job );
1215         tempfd = Make_temp_fd(&tempfile);
1216 		if( Write_fd_len( tempfd, Outbuf, Outlen ) < 0 ){
1217 			logerr(LOG_INFO, "Add_banner_to_job: write to '%s' failed", tempfile );
1218 			Errorcode = JABORT;
1219 			return;
1220 		}
1221 		close(tempfd);
1222 		lp = malloc_or_die(sizeof(lp[0]),__FILE__,__LINE__);
1223 		memset(lp,0,sizeof(lp[0]));
1224 		Check_max(&job->datafiles,1);
1225 		job->datafiles.list[job->datafiles.count] = (void *)lp;
1226 		++job->datafiles.count;
1227 		Set_str_value(lp,OPENNAME,tempfile);
1228 		Set_str_value(lp,DFTRANSFERNAME,tempfile);
1229 		Set_str_value(lp,"N","BANNER");
1230 		Set_str_value(lp,FORMAT,"f");
1231 	}
1232 	if(DEBUGL3)Dump_job("Add_banner_to_job", job);
1233 }
1234