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