1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #ifndef lint
34 static const char copyright[] =
35 "@(#) Copyright (c) 1983, 1993\n\
36 The Regents of the University of California. All rights reserved.\n";
37 #endif /* not lint */
38
39 #if 0
40 #ifndef lint
41 static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95";
42 #endif /* not lint */
43 #endif
44
45 #include "lp.cdefs.h" /* A cross-platform version of <sys/cdefs.h> */
46 __FBSDID("$FreeBSD$");
47
48 /*
49 * printjob -- print jobs in the queue.
50 *
51 * NOTE: the lock file is used to pass information to lpq and lprm.
52 * it does not need to be removed because file locks are dynamic.
53 */
54
55 #include <sys/param.h>
56 #include <sys/wait.h>
57 #include <sys/stat.h>
58 #include <sys/types.h>
59
60 #include <pwd.h>
61 #include <unistd.h>
62 #include <signal.h>
63 #include <syslog.h>
64 #include <fcntl.h>
65 #include <dirent.h>
66 #include <err.h>
67 #include <errno.h>
68 #include <inttypes.h>
69 #include <stdio.h>
70 #include <string.h>
71 #include <stdlib.h>
72 #include <sys/ioctl.h>
73 #include <termios.h>
74 #include <time.h>
75 #include "lp.h"
76 #include "lp.local.h"
77 #include "pathnames.h"
78 #include "extern.h"
79
80 #define DORETURN 0 /* dofork should return "can't fork" error */
81 #define DOABORT 1 /* dofork should just die if fork() fails */
82
83 /*
84 * The buffer size to use when reading/writing spool files.
85 */
86 #define SPL_BUFSIZ BUFSIZ
87
88 /*
89 * Error tokens
90 */
91 #define REPRINT -2
92 #define ERROR -1
93 #define OK 0
94 #define FATALERR 1
95 #define NOACCT 2
96 #define FILTERERR 3
97 #define ACCESS 4
98
99 static dev_t fdev; /* device of file pointed to by symlink */
100 static ino_t fino; /* inode of file pointed to by symlink */
101 static FILE *cfp; /* control file */
102 static pid_t of_pid; /* process id of output filter, if any */
103 static int child; /* id of any filters */
104 static int job_dfcnt; /* count of datafiles in current user job */
105 static int lfd; /* lock file descriptor */
106 static int ofd; /* output filter file descriptor */
107 static int tfd = -1; /* output filter temp file output */
108 static int pfd; /* prstatic inter file descriptor */
109 static int prchild; /* id of pr process */
110 static char title[80]; /* ``pr'' title */
111 static char locale[80]; /* ``pr'' locale */
112
113 /* these two are set from pp->daemon_user, but only if they are needed */
114 static char *daemon_uname; /* set from pwd->pw_name */
115 static int daemon_defgid;
116
117 static char class[32]; /* classification field */
118 static char origin_host[MAXHOSTNAMELEN]; /* user's host machine */
119 /* indentation size in static characters */
120 static char indent[10] = "-i0";
121 static char jobname[100]; /* job or file name */
122 static char length[10] = "-l"; /* page length in lines */
123 static char logname[32]; /* user's login name */
124 static char pxlength[10] = "-y"; /* page length in pixels */
125 static char pxwidth[10] = "-x"; /* page width in pixels */
126 /* tempstderr is the filename used to catch stderr from exec-ing filters */
127 static char tempstderr[] = "errs.XXXXXXX";
128 static char width[10] = "-w"; /* page width in static characters */
129 #define TFILENAME "fltXXXXXX"
130 static char tfile[] = TFILENAME; /* file name for filter output */
131
132 static void abortpr(int _signo);
133 static void alarmhandler(int _signo);
134 static void banner(struct printer *_pp, char *_name1, char *_name2);
135 static int dofork(const struct printer *_pp, int _action);
136 static int dropit(int _c);
137 static int execfilter(struct printer *_pp, char *_f_cmd, char **_f_av,
138 int _infd, int _outfd);
139 static void init(struct printer *_pp);
140 static void openpr(const struct printer *_pp);
141 static void opennet(const struct printer *_pp);
142 static void opentty(const struct printer *_pp);
143 static void openrem(const struct printer *pp);
144 static int print(struct printer *_pp, int _format, char *_file);
145 static int printit(struct printer *_pp, char *_file);
146 static void pstatus(const struct printer *_pp, const char *_msg, ...)
147 __printflike(2, 3);
148 static char response(const struct printer *_pp);
149 static void scan_out(struct printer *_pp, int _scfd, char *_scsp,
150 int _dlm);
151 static char *scnline(int _key, char *_p, int _c);
152 static int sendfile(struct printer *_pp, int _type, char *_file,
153 char _format, int _copyreq);
154 static int sendit(struct printer *_pp, char *_file);
155 static void sendmail(struct printer *_pp, char *_userid, int _bombed);
156 static void setty(const struct printer *_pp);
157 static void wait4data(struct printer *_pp, const char *_dfile);
158
159 void
printjob(struct printer * pp)160 printjob(struct printer *pp)
161 {
162 struct stat stb;
163 register struct jobqueue *q, **qp;
164 struct jobqueue **queue;
165 register int i, nitems;
166 off_t pidoff;
167 pid_t printpid;
168 int errcnt, jobcount, statok, tempfd;
169
170 jobcount = 0;
171 init(pp); /* set up capabilities */
172 (void) write(STDOUT_FILENO, "", 1); /* ack that daemon is started */
173 (void) close(STDERR_FILENO); /* set up log file */
174 if (open(pp->log_file, O_WRONLY|O_APPEND, LOG_FILE_MODE) < 0) {
175 syslog(LOG_ERR, "%s: open(%s): %m", pp->printer,
176 pp->log_file);
177 (void) open(_PATH_DEVNULL, O_WRONLY);
178 }
179 if(setgid(getegid()) != 0) err(1, "setgid() failed");
180 printpid = getpid(); /* for use with lprm */
181 setpgid((pid_t)0, printpid);
182
183 /*
184 * At initial lpd startup, printjob may be called with various
185 * signal handlers in effect. After that initial startup, any
186 * calls to printjob will have a *different* set of signal-handlers
187 * in effect. Make sure all handlers are the ones we want.
188 */
189 signal(SIGCHLD, SIG_DFL);
190 signal(SIGHUP, abortpr);
191 signal(SIGINT, abortpr);
192 signal(SIGQUIT, abortpr);
193 signal(SIGTERM, abortpr);
194
195 /*
196 * uses short form file names
197 */
198 if (chdir(pp->spool_dir) < 0) {
199 syslog(LOG_ERR, "%s: chdir(%s): %m", pp->printer,
200 pp->spool_dir);
201 exit(1);
202 }
203 statok = stat(pp->lock_file, &stb);
204 if (statok == 0 && (stb.st_mode & LFM_PRINT_DIS))
205 exit(0); /* printing disabled */
206 umask(S_IWOTH);
207 lfd = open(pp->lock_file, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK,
208 LOCK_FILE_MODE);
209 if (lfd < 0) {
210 if (errno == EWOULDBLOCK) /* active daemon present */
211 exit(0);
212 syslog(LOG_ERR, "%s: open(%s): %m", pp->printer,
213 pp->lock_file);
214 exit(1);
215 }
216 /*
217 * If the initial call to stat() failed, then lock_file will have
218 * been created by open(). Update &stb to match that new file.
219 */
220 if (statok != 0)
221 statok = stat(pp->lock_file, &stb);
222 /* turn off non-blocking mode (was turned on for lock effects only) */
223 if (fcntl(lfd, F_SETFL, 0) < 0) {
224 syslog(LOG_ERR, "%s: fcntl(%s): %m", pp->printer,
225 pp->lock_file);
226 exit(1);
227 }
228 ftruncate(lfd, 0);
229 /*
230 * write process id for others to know
231 */
232 sprintf(line, "%u\n", printpid);
233 pidoff = i = strlen(line);
234 if (write(lfd, line, i) != i) {
235 syslog(LOG_ERR, "%s: write(%s): %m", pp->printer,
236 pp->lock_file);
237 exit(1);
238 }
239 /*
240 * search the spool directory for work and sort by queue order.
241 */
242 if ((nitems = getq(pp, &queue)) < 0) {
243 syslog(LOG_ERR, "%s: can't scan %s", pp->printer,
244 pp->spool_dir);
245 exit(1);
246 }
247 if (nitems == 0) /* no work to do */
248 exit(0);
249 if (stb.st_mode & LFM_RESET_QUE) { /* reset queue flag */
250 if (fchmod(lfd, stb.st_mode & ~LFM_RESET_QUE) < 0)
251 syslog(LOG_ERR, "%s: fchmod(%s): %m", pp->printer,
252 pp->lock_file);
253 }
254
255 /* create a file which will be used to hold stderr from filters */
256 if ((tempfd = mkstemp(tempstderr)) == -1) {
257 syslog(LOG_ERR, "%s: mkstemp(%s): %m", pp->printer,
258 tempstderr);
259 exit(1);
260 }
261 if ((i = fchmod(tempfd, 0664)) == -1) {
262 syslog(LOG_ERR, "%s: fchmod(%s): %m", pp->printer,
263 tempstderr);
264 exit(1);
265 }
266 /* lpd doesn't need it to be open, it just needs it to exist */
267 close(tempfd);
268
269 openpr(pp); /* open printer or remote */
270 again:
271 /*
272 * we found something to do now do it --
273 * write the name of the current control file into the lock file
274 * so the spool queue program can tell what we're working on
275 */
276 for (qp = queue; nitems--; free((char *) q)) {
277 q = *qp++;
278 if (stat(q->job_cfname, &stb) < 0)
279 continue;
280 errcnt = 0;
281 restart:
282 (void) lseek(lfd, pidoff, 0);
283 (void) snprintf(line, sizeof(line), "%s\n", q->job_cfname);
284 i = strlen(line);
285 if (write(lfd, line, i) != i)
286 syslog(LOG_ERR, "%s: write(%s): %m", pp->printer,
287 pp->lock_file);
288 if (!pp->remote)
289 i = printit(pp, q->job_cfname);
290 else
291 i = sendit(pp, q->job_cfname);
292 /*
293 * Check to see if we are supposed to stop printing or
294 * if we are to rebuild the queue.
295 */
296 if (fstat(lfd, &stb) == 0) {
297 /* stop printing before starting next job? */
298 if (stb.st_mode & LFM_PRINT_DIS)
299 goto done;
300 /* rebuild queue (after lpc topq) */
301 if (stb.st_mode & LFM_RESET_QUE) {
302 for (free(q); nitems--; free(q))
303 q = *qp++;
304 if (fchmod(lfd, stb.st_mode & ~LFM_RESET_QUE)
305 < 0)
306 syslog(LOG_WARNING,
307 "%s: fchmod(%s): %m",
308 pp->printer, pp->lock_file);
309 break;
310 }
311 }
312 if (i == OK) /* all files of this job printed */
313 jobcount++;
314 else if (i == REPRINT && ++errcnt < 5) {
315 /* try reprinting the job */
316 syslog(LOG_INFO, "restarting %s", pp->printer);
317 if (of_pid > 0) {
318 kill(of_pid, SIGCONT); /* to be sure */
319 (void) close(ofd);
320 while ((i = wait(NULL)) > 0 && i != of_pid)
321 ;
322 if (i < 0)
323 syslog(LOG_WARNING, "%s: after kill(of=%d), wait() returned: %m",
324 pp->printer, of_pid);
325 of_pid = 0;
326 }
327 (void) close(pfd); /* close printer */
328 if (ftruncate(lfd, pidoff) < 0)
329 syslog(LOG_WARNING, "%s: ftruncate(%s): %m",
330 pp->printer, pp->lock_file);
331 openpr(pp); /* try to reopen printer */
332 goto restart;
333 } else {
334 syslog(LOG_WARNING, "%s: job could not be %s (%s)",
335 pp->printer,
336 pp->remote ? "sent to remote host" : "printed",
337 q->job_cfname);
338 if (i == REPRINT) {
339 /* ensure we don't attempt this job again */
340 (void) unlink(q->job_cfname);
341 q->job_cfname[0] = 'd';
342 (void) unlink(q->job_cfname);
343 if (logname[0])
344 sendmail(pp, logname, FATALERR);
345 }
346 }
347 }
348 free(queue);
349 /*
350 * search the spool directory for more work.
351 */
352 if ((nitems = getq(pp, &queue)) < 0) {
353 syslog(LOG_ERR, "%s: can't scan %s", pp->printer,
354 pp->spool_dir);
355 exit(1);
356 }
357 if (nitems == 0) { /* no more work to do */
358 done:
359 if (jobcount > 0) { /* jobs actually printed */
360 if (!pp->no_formfeed && !pp->tof)
361 (void) write(ofd, pp->form_feed,
362 strlen(pp->form_feed));
363 if (pp->trailer != NULL) /* output trailer */
364 (void) write(ofd, pp->trailer,
365 strlen(pp->trailer));
366 }
367 (void) close(ofd);
368 (void) wait(NULL);
369 (void) unlink(tempstderr);
370 exit(0);
371 }
372 goto again;
373 }
374
375 char fonts[4][50]; /* fonts for troff */
376
377 char ifonts[4][40] = {
378 _PATH_VFONTR,
379 _PATH_VFONTI,
380 _PATH_VFONTB,
381 _PATH_VFONTS,
382 };
383
384 /*
385 * The remaining part is the reading of the control file (cf)
386 * and performing the various actions.
387 */
388 static int
printit(struct printer * pp,char * file)389 printit(struct printer *pp, char *file)
390 {
391 register int i;
392 char *cp;
393 int bombed, didignorehdr;
394
395 bombed = OK;
396 didignorehdr = 0;
397 /*
398 * open control file; ignore if no longer there.
399 */
400 if ((cfp = fopen(file, "r")) == NULL) {
401 syslog(LOG_INFO, "%s: fopen(%s): %m", pp->printer, file);
402 return (OK);
403 }
404 /*
405 * Reset troff fonts.
406 */
407 for (i = 0; i < 4; i++)
408 strcpy(fonts[i], ifonts[i]);
409 sprintf(&width[2], "%ld", pp->page_width);
410 strcpy(indent+2, "0");
411
412 /* initialize job-specific count of datafiles processed */
413 job_dfcnt = 0;
414
415 /*
416 * read the control file for work to do
417 *
418 * file format -- first character in the line is a command
419 * rest of the line is the argument.
420 * valid commands are:
421 *
422 * S -- "stat info" for symbolic link protection
423 * J -- "job name" on banner page
424 * C -- "class name" on banner page
425 * L -- "literal" user's name to print on banner
426 * T -- "title" for pr
427 * H -- "host name" of machine where lpr was done
428 * P -- "person" user's login name
429 * I -- "indent" amount to indent output
430 * R -- laser dpi "resolution"
431 * f -- "file name" name of text file to print
432 * l -- "file name" text file with control chars
433 * o -- "file name" postscript file, according to
434 * the RFC. Here it is treated like an 'f'.
435 * p -- "file name" text file to print with pr(1)
436 * t -- "file name" troff(1) file to print
437 * n -- "file name" ditroff(1) file to print
438 * d -- "file name" dvi file to print
439 * g -- "file name" plot(1G) file to print
440 * v -- "file name" plain raster file to print
441 * c -- "file name" cifplot file to print
442 * 1 -- "R font file" for troff
443 * 2 -- "I font file" for troff
444 * 3 -- "B font file" for troff
445 * 4 -- "S font file" for troff
446 * N -- "name" of file (used by lpq)
447 * U -- "unlink" name of file to remove
448 * (after we print it. (Pass 2 only)).
449 * M -- "mail" to user when done printing
450 * Z -- "locale" for pr
451 *
452 * get_line reads a line and expands tabs to blanks
453 */
454
455 /* pass 1 */
456
457 while (get_line(cfp))
458 switch (line[0]) {
459 case 'H':
460 strlcpy(origin_host, line + 1, sizeof(origin_host));
461 if (class[0] == '\0') {
462 strlcpy(class, line+1, sizeof(class));
463 }
464 continue;
465
466 case 'P':
467 strlcpy(logname, line + 1, sizeof(logname));
468 if (pp->restricted) { /* restricted */
469 if (getpwnam(logname) == NULL) {
470 bombed = NOACCT;
471 sendmail(pp, line+1, bombed);
472 goto pass2;
473 }
474 }
475 continue;
476
477 case 'S':
478 cp = line+1;
479 i = 0;
480 while (*cp >= '0' && *cp <= '9')
481 i = i * 10 + (*cp++ - '0');
482 fdev = i;
483 cp++;
484 i = 0;
485 while (*cp >= '0' && *cp <= '9')
486 i = i * 10 + (*cp++ - '0');
487 fino = i;
488 continue;
489
490 case 'J':
491 if (line[1] != '\0') {
492 strlcpy(jobname, line + 1, sizeof(jobname));
493 } else
494 strcpy(jobname, " ");
495 continue;
496
497 case 'C':
498 if (line[1] != '\0')
499 strlcpy(class, line + 1, sizeof(class));
500 else if (class[0] == '\0') {
501 /* XXX - why call gethostname instead of
502 * just strlcpy'ing local_host? */
503 gethostname(class, sizeof(class));
504 class[sizeof(class) - 1] = '\0';
505 }
506 continue;
507
508 case 'T': /* header title for pr */
509 strlcpy(title, line + 1, sizeof(title));
510 continue;
511
512 case 'L': /* identification line */
513 if (!pp->no_header && !pp->header_last)
514 banner(pp, line+1, jobname);
515 continue;
516
517 case '1': /* troff fonts */
518 case '2':
519 case '3':
520 case '4':
521 if (line[1] != '\0') {
522 strlcpy(fonts[line[0]-'1'], line + 1,
523 (size_t)50);
524 }
525 continue;
526
527 case 'W': /* page width */
528 strlcpy(width+2, line + 1, sizeof(width) - 2);
529 continue;
530
531 case 'I': /* indent amount */
532 strlcpy(indent+2, line + 1, sizeof(indent) - 2);
533 continue;
534
535 case 'Z': /* locale for pr */
536 strlcpy(locale, line + 1, sizeof(locale));
537 continue;
538
539 default: /* some file to print */
540 /* only lowercase cmd-codes include a file-to-print */
541 if ((line[0] < 'a') || (line[0] > 'z')) {
542 /* ignore any other lines */
543 if (lflag <= 1)
544 continue;
545 if (!didignorehdr) {
546 syslog(LOG_INFO, "%s: in %s :",
547 pp->printer, file);
548 didignorehdr = 1;
549 }
550 syslog(LOG_INFO, "%s: ignoring line: '%c' %s",
551 pp->printer, line[0], &line[1]);
552 continue;
553 }
554 i = print(pp, line[0], line+1);
555 switch (i) {
556 case ERROR:
557 if (bombed == OK)
558 bombed = FATALERR;
559 break;
560 case REPRINT:
561 (void) fclose(cfp);
562 return (REPRINT);
563 case FILTERERR:
564 case ACCESS:
565 bombed = i;
566 sendmail(pp, logname, bombed);
567 }
568 title[0] = '\0';
569 continue;
570
571 case 'N':
572 case 'U':
573 case 'M':
574 case 'R':
575 continue;
576 }
577
578 /* pass 2 */
579
580 pass2:
581 fseek(cfp, 0L, 0);
582 while (get_line(cfp))
583 switch (line[0]) {
584 case 'L': /* identification line */
585 if (!pp->no_header && pp->header_last)
586 banner(pp, line+1, jobname);
587 continue;
588
589 case 'M':
590 if (bombed < NOACCT) /* already sent if >= NOACCT */
591 sendmail(pp, line+1, bombed);
592 continue;
593
594 case 'U':
595 if (strchr(line+1, '/'))
596 continue;
597 (void) unlink(line+1);
598 }
599 /*
600 * clean-up in case another control file exists
601 */
602 (void) fclose(cfp);
603 (void) unlink(file);
604 return (bombed == OK ? OK : ERROR);
605 }
606
607 /*
608 * Print a file.
609 * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
610 * Return -1 if a non-recoverable error occurred,
611 * 2 if the filter detected some errors (but printed the job anyway),
612 * 1 if we should try to reprint this job and
613 * 0 if all is well.
614 * Note: all filters take stdin as the file, stdout as the printer,
615 * stderr as the log file, and must not ignore SIGINT.
616 */
617 static int
print(struct printer * pp,int format,char * file)618 print(struct printer *pp, int format, char *file)
619 {
620 register int n, i;
621 register char *prog;
622 int fi, fo;
623 FILE *fp;
624 char *av[15], buf[SPL_BUFSIZ];
625 pid_t wpid;
626 int p[2], retcode, stopped, wstatus, wstatus_set;
627 struct stat stb;
628
629 /* Make sure the entire data file has arrived. */
630 wait4data(pp, file);
631
632 if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0) {
633 syslog(LOG_INFO, "%s: unable to open %s ('%c' line)",
634 pp->printer, file, format);
635 return (ERROR);
636 }
637 /*
638 * Check to see if data file is a symbolic link. If so, it should
639 * still point to the same file or someone is trying to print
640 * something he shouldn't.
641 */
642 if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 &&
643 (stb.st_dev != fdev || stb.st_ino != fino))
644 return (ACCESS);
645
646 job_dfcnt++; /* increment datafile counter for this job */
647 stopped = 0; /* output filter is not stopped */
648
649 /* everything seems OK, start it up */
650 if (!pp->no_formfeed && !pp->tof) { /* start on a fresh page */
651 (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
652 pp->tof = 1;
653 }
654 if (pp->filters[LPF_INPUT] == NULL
655 && (format == 'f' || format == 'l' || format == 'o')) {
656 pp->tof = 0;
657 while ((n = read(fi, buf, SPL_BUFSIZ)) > 0)
658 if (write(ofd, buf, n) != n) {
659 (void) close(fi);
660 return (REPRINT);
661 }
662 (void) close(fi);
663 return (OK);
664 }
665 switch (format) {
666 case 'p': /* print file using 'pr' */
667 if (pp->filters[LPF_INPUT] == NULL) { /* use output filter */
668 prog = _PATH_PR;
669 i = 0;
670 av[i++] = "pr";
671 av[i++] = width;
672 av[i++] = length;
673 av[i++] = "-h";
674 av[i++] = *title ? title : " ";
675 av[i++] = "-L";
676 av[i++] = *locale ? locale : "C";
677 av[i++] = "-F";
678 av[i] = NULL;
679 fo = ofd;
680 goto start;
681 }
682 pipe(p);
683 if ((prchild = dofork(pp, DORETURN)) == 0) { /* child */
684 dup2(fi, STDIN_FILENO); /* file is stdin */
685 dup2(p[1], STDOUT_FILENO); /* pipe is stdout */
686 closelog();
687 closeallfds(3);
688 execl(_PATH_PR, "pr", width, length,
689 "-h", *title ? title : " ",
690 "-L", *locale ? locale : "C",
691 "-F", (char *)0);
692 syslog(LOG_ERR, "cannot execl %s", _PATH_PR);
693 exit(2);
694 }
695 (void) close(p[1]); /* close output side */
696 (void) close(fi);
697 if (prchild < 0) {
698 prchild = 0;
699 (void) close(p[0]);
700 return (ERROR);
701 }
702 fi = p[0]; /* use pipe for input */
703 case 'f': /* print plain text file */
704 prog = pp->filters[LPF_INPUT];
705 av[1] = width;
706 av[2] = length;
707 av[3] = indent;
708 n = 4;
709 break;
710 case 'o': /* print postscript file */
711 /*
712 * Treat this as a "plain file with control characters", and
713 * assume the standard LPF_INPUT filter will recognize that
714 * the data is postscript and know what to do with it. These
715 * 'o'-file requests could come from MacOS 10.1 systems.
716 * (later versions of MacOS 10 will explicitly use 'l')
717 * A postscript file can contain binary data, which is why 'l'
718 * is somewhat more appropriate than 'f'.
719 */
720 /* FALLTHROUGH */
721 case 'l': /* like 'f' but pass control characters */
722 prog = pp->filters[LPF_INPUT];
723 av[1] = "-c";
724 av[2] = width;
725 av[3] = length;
726 av[4] = indent;
727 n = 5;
728 break;
729 case 'r': /* print a fortran text file */
730 prog = pp->filters[LPF_FORTRAN];
731 av[1] = width;
732 av[2] = length;
733 n = 3;
734 break;
735 case 't': /* print troff output */
736 case 'n': /* print ditroff output */
737 case 'd': /* print tex output */
738 (void) unlink(".railmag");
739 if ((fo = creat(".railmag", FILMOD)) < 0) {
740 syslog(LOG_ERR, "%s: cannot create .railmag",
741 pp->printer);
742 (void) unlink(".railmag");
743 } else {
744 for (n = 0; n < 4; n++) {
745 if (fonts[n][0] != '/')
746 (void) write(fo, _PATH_VFONT,
747 sizeof(_PATH_VFONT) - 1);
748 (void) write(fo, fonts[n], strlen(fonts[n]));
749 (void) write(fo, "\n", 1);
750 }
751 (void) close(fo);
752 }
753 prog = (format == 't') ? pp->filters[LPF_TROFF]
754 : ((format == 'n') ? pp->filters[LPF_DITROFF]
755 : pp->filters[LPF_DVI]);
756 av[1] = pxwidth;
757 av[2] = pxlength;
758 n = 3;
759 break;
760 case 'c': /* print cifplot output */
761 prog = pp->filters[LPF_CIFPLOT];
762 av[1] = pxwidth;
763 av[2] = pxlength;
764 n = 3;
765 break;
766 case 'g': /* print plot(1G) output */
767 prog = pp->filters[LPF_GRAPH];
768 av[1] = pxwidth;
769 av[2] = pxlength;
770 n = 3;
771 break;
772 case 'v': /* print raster output */
773 prog = pp->filters[LPF_RASTER];
774 av[1] = pxwidth;
775 av[2] = pxlength;
776 n = 3;
777 break;
778 default:
779 (void) close(fi);
780 syslog(LOG_ERR, "%s: illegal format character '%c'",
781 pp->printer, format);
782 return (ERROR);
783 }
784 if (prog == NULL) {
785 (void) close(fi);
786 syslog(LOG_ERR,
787 "%s: no filter found in printcap for format character '%c'",
788 pp->printer, format);
789 return (ERROR);
790 }
791 if ((av[0] = strrchr(prog, '/')) != NULL)
792 av[0]++;
793 else
794 av[0] = prog;
795 av[n++] = "-n";
796 av[n++] = logname;
797 av[n++] = "-h";
798 av[n++] = origin_host;
799 av[n++] = pp->acct_file;
800 av[n] = NULL;
801 fo = pfd;
802 if (of_pid > 0) { /* stop output filter */
803 write(ofd, "\031\1", 2);
804 while ((wpid =
805 wait3(&wstatus, WUNTRACED, 0)) > 0 && wpid != of_pid)
806 ;
807 if (wpid < 0)
808 syslog(LOG_WARNING,
809 "%s: after stopping 'of', wait3() returned: %m",
810 pp->printer);
811 else if (!WIFSTOPPED(wstatus)) {
812 (void) close(fi);
813 syslog(LOG_WARNING, "%s: output filter died "
814 "(pid=%d retcode=%d termsig=%d)",
815 pp->printer, of_pid, WEXITSTATUS(wstatus),
816 WTERMSIG(wstatus));
817 return (REPRINT);
818 }
819 stopped++;
820 }
821 start:
822 if ((child = dofork(pp, DORETURN)) == 0) { /* child */
823 dup2(fi, STDIN_FILENO);
824 dup2(fo, STDOUT_FILENO);
825 /* setup stderr for the filter (child process)
826 * so it goes to our temporary errors file */
827 n = open(tempstderr, O_WRONLY|O_TRUNC, 0664);
828 if (n >= 0)
829 dup2(n, STDERR_FILENO);
830 closelog();
831 closeallfds(3);
832 execv(prog, av);
833 syslog(LOG_ERR, "%s: cannot execv(%s): %m", pp->printer,
834 prog);
835 exit(2);
836 }
837 (void) close(fi);
838 wstatus_set = 0;
839 if (child < 0)
840 retcode = 100;
841 else {
842 while ((wpid = wait(&wstatus)) > 0 && wpid != child)
843 ;
844 if (wpid < 0) {
845 retcode = 100;
846 syslog(LOG_WARNING,
847 "%s: after execv(%s), wait() returned: %m",
848 pp->printer, prog);
849 } else {
850 wstatus_set = 1;
851 retcode = WEXITSTATUS(wstatus);
852 }
853 }
854 child = 0;
855 prchild = 0;
856 if (stopped) { /* restart output filter */
857 if (kill(of_pid, SIGCONT) < 0) {
858 syslog(LOG_ERR, "cannot restart output filter");
859 exit(1);
860 }
861 }
862 pp->tof = 0;
863
864 /* Copy the filter's output to "lf" logfile */
865 if ((fp = fopen(tempstderr, "r"))) {
866 while (fgets(buf, sizeof(buf), fp))
867 fputs(buf, stderr);
868 fclose(fp);
869 }
870
871 if (wstatus_set && !WIFEXITED(wstatus)) {
872 syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d)",
873 pp->printer, format, WTERMSIG(wstatus));
874 return (ERROR);
875 }
876 switch (retcode) {
877 case 0:
878 pp->tof = 1;
879 return (OK);
880 case 1:
881 return (REPRINT);
882 case 2:
883 return (ERROR);
884 default:
885 syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)",
886 pp->printer, format, retcode);
887 return (FILTERERR);
888 }
889 }
890
891 /*
892 * Send the daemon control file (cf) and any data files.
893 * Return -1 if a non-recoverable error occurred, 1 if a recoverable error and
894 * 0 if all is well.
895 */
896 static int
sendit(struct printer * pp,char * file)897 sendit(struct printer *pp, char *file)
898 {
899 int dfcopies, err, i;
900 char *cp, last[sizeof(line)];
901
902 /*
903 * open control file
904 */
905 if ((cfp = fopen(file, "r")) == NULL)
906 return (OK);
907
908 /* initialize job-specific count of datafiles processed */
909 job_dfcnt = 0;
910
911 /*
912 * read the control file for work to do
913 *
914 * file format -- first character in the line is a command
915 * rest of the line is the argument.
916 * commands of interest are:
917 *
918 * a-z -- "file name" name of file to print
919 * U -- "unlink" name of file to remove
920 * (after we print it. (Pass 2 only)).
921 */
922
923 /*
924 * pass 1
925 */
926 err = OK;
927 while (get_line(cfp)) {
928 again:
929 if (line[0] == 'S') {
930 cp = line+1;
931 i = 0;
932 while (*cp >= '0' && *cp <= '9')
933 i = i * 10 + (*cp++ - '0');
934 fdev = i;
935 cp++;
936 i = 0;
937 while (*cp >= '0' && *cp <= '9')
938 i = i * 10 + (*cp++ - '0');
939 fino = i;
940 } else if (line[0] == 'H') {
941 strlcpy(origin_host, line + 1, sizeof(origin_host));
942 if (class[0] == '\0') {
943 strlcpy(class, line + 1, sizeof(class));
944 }
945 } else if (line[0] == 'P') {
946 strlcpy(logname, line + 1, sizeof(logname));
947 if (pp->restricted) { /* restricted */
948 if (getpwnam(logname) == NULL) {
949 sendmail(pp, line+1, NOACCT);
950 err = ERROR;
951 break;
952 }
953 }
954 } else if (line[0] == 'I') {
955 strlcpy(indent+2, line + 1, sizeof(indent) - 2);
956 } else if (line[0] >= 'a' && line[0] <= 'z') {
957 dfcopies = 1;
958 strcpy(last, line);
959 while ((i = get_line(cfp)) != 0) {
960 if (strcmp(last, line) != 0)
961 break;
962 dfcopies++;
963 }
964 switch (sendfile(pp, '\3', last+1, *last, dfcopies)) {
965 case OK:
966 if (i)
967 goto again;
968 break;
969 case REPRINT:
970 (void) fclose(cfp);
971 return (REPRINT);
972 case ACCESS:
973 sendmail(pp, logname, ACCESS);
974 case ERROR:
975 err = ERROR;
976 }
977 break;
978 }
979 }
980 if (err == OK && sendfile(pp, '\2', file, '\0', 1) > 0) {
981 (void) fclose(cfp);
982 return (REPRINT);
983 }
984 /*
985 * pass 2
986 */
987 fseek(cfp, 0L, 0);
988 while (get_line(cfp))
989 if (line[0] == 'U' && !strchr(line+1, '/'))
990 (void) unlink(line+1);
991 /*
992 * clean-up in case another control file exists
993 */
994 (void) fclose(cfp);
995 (void) unlink(file);
996 return (err);
997 }
998
999 /*
1000 * Send a data file to the remote machine and spool it.
1001 * Return positive if we should try resending.
1002 */
1003 static int
sendfile(struct printer * pp,int type,char * file,char format,int copyreq)1004 sendfile(struct printer *pp, int type, char *file, char format, int copyreq)
1005 {
1006 int i, amt;
1007 struct stat stb;
1008 char *av[15], *filtcmd;
1009 char buf[SPL_BUFSIZ], opt_c[4], opt_h[4], opt_n[4];
1010 int copycnt, filtstat, narg, resp, sfd, sfres, sizerr, statrc;
1011
1012 /* Make sure the entire data file has arrived. */
1013 wait4data(pp, file);
1014
1015 statrc = lstat(file, &stb);
1016 if (statrc < 0) {
1017 syslog(LOG_ERR, "%s: error from lstat(%s): %m",
1018 pp->printer, file);
1019 return (ERROR);
1020 }
1021 sfd = open(file, O_RDONLY);
1022 if (sfd < 0) {
1023 syslog(LOG_ERR, "%s: error from open(%s,O_RDONLY): %m",
1024 pp->printer, file);
1025 return (ERROR);
1026 }
1027 /*
1028 * Check to see if data file is a symbolic link. If so, it should
1029 * still point to the same file or someone is trying to print something
1030 * he shouldn't.
1031 */
1032 if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(sfd, &stb) == 0 &&
1033 (stb.st_dev != fdev || stb.st_ino != fino)) {
1034 close(sfd);
1035 return (ACCESS);
1036 }
1037
1038 /* Everything seems OK for reading the file, now to send it */
1039 filtcmd = NULL;
1040 sizerr = 0;
1041 tfd = -1;
1042 if (type == '\3') {
1043 /*
1044 * Type == 3 means this is a datafile, not a control file.
1045 * Increment the counter of data-files in this job, and
1046 * then check for input or output filters (which are only
1047 * applied to datafiles, not control files).
1048 */
1049 job_dfcnt++;
1050
1051 /*
1052 * Note that here we are filtering datafiles, one at a time,
1053 * as they are sent to the remote machine. Here, the *only*
1054 * difference between an input filter (`if=') and an output
1055 * filter (`of=') is the argument list that the filter is
1056 * started up with. Here, the output filter is executed
1057 * for each individual file as it is sent. This is not the
1058 * same as local print queues, where the output filter is
1059 * started up once, and then all jobs are passed thru that
1060 * single invocation of the output filter.
1061 *
1062 * Also note that a queue for a remote-machine can have an
1063 * input filter or an output filter, but not both.
1064 */
1065 if (pp->filters[LPF_INPUT]) {
1066 filtcmd = pp->filters[LPF_INPUT];
1067 av[0] = filtcmd;
1068 narg = 0;
1069 strcpy(opt_c, "-c");
1070 strcpy(opt_h, "-h");
1071 strcpy(opt_n, "-n");
1072 if (format == 'l')
1073 av[++narg] = opt_c;
1074 av[++narg] = width;
1075 av[++narg] = length;
1076 av[++narg] = indent;
1077 av[++narg] = opt_n;
1078 av[++narg] = logname;
1079 av[++narg] = opt_h;
1080 av[++narg] = origin_host;
1081 av[++narg] = pp->acct_file;
1082 av[++narg] = NULL;
1083 } else if (pp->filters[LPF_OUTPUT]) {
1084 filtcmd = pp->filters[LPF_OUTPUT];
1085 av[0] = filtcmd;
1086 narg = 0;
1087 av[++narg] = width;
1088 av[++narg] = length;
1089 av[++narg] = NULL;
1090 }
1091 }
1092 if (filtcmd) {
1093 /*
1094 * If there is an input or output filter, we have to run
1095 * the datafile thru that filter and store the result as
1096 * a temporary spool file, because the protocol requires
1097 * that we send the remote host the file-size before we
1098 * start to send any of the data.
1099 */
1100 strcpy(tfile, TFILENAME);
1101 tfd = mkstemp(tfile);
1102 if (tfd == -1) {
1103 syslog(LOG_ERR, "%s: mkstemp(%s): %m", pp->printer,
1104 TFILENAME);
1105 sfres = ERROR;
1106 goto return_sfres;
1107 }
1108 filtstat = execfilter(pp, filtcmd, av, sfd, tfd);
1109
1110 /* process the return-code from the filter */
1111 switch (filtstat) {
1112 case 0:
1113 break;
1114 case 1:
1115 sfres = REPRINT;
1116 goto return_sfres;
1117 case 2:
1118 sfres = ERROR;
1119 goto return_sfres;
1120 default:
1121 syslog(LOG_WARNING,
1122 "%s: filter '%c' exited (retcode=%d)",
1123 pp->printer, format, filtstat);
1124 sfres = FILTERERR;
1125 goto return_sfres;
1126 }
1127 statrc = fstat(tfd, &stb); /* to find size of tfile */
1128 if (statrc < 0) {
1129 syslog(LOG_ERR,
1130 "%s: error processing 'if', fstat(%s): %m",
1131 pp->printer, tfile);
1132 sfres = ERROR;
1133 goto return_sfres;
1134 }
1135 close(sfd);
1136 sfd = tfd;
1137 lseek(sfd, 0, SEEK_SET);
1138 }
1139
1140 copycnt = 0;
1141 sendagain:
1142 copycnt++;
1143
1144 if (copycnt < 2)
1145 (void) sprintf(buf, "%c%" PRId64 " %s\n", type, stb.st_size,
1146 file);
1147 else
1148 (void) sprintf(buf, "%c%" PRId64 " %s_c%d\n", type, stb.st_size,
1149 file, copycnt);
1150 amt = strlen(buf);
1151 for (i = 0; ; i++) {
1152 if (write(pfd, buf, amt) != amt ||
1153 (resp = response(pp)) < 0 || resp == '\1') {
1154 sfres = REPRINT;
1155 goto return_sfres;
1156 } else if (resp == '\0')
1157 break;
1158 if (i == 0)
1159 pstatus(pp,
1160 "no space on remote; waiting for queue to drain");
1161 if (i == 10)
1162 syslog(LOG_ALERT, "%s: can't send to %s; queue full",
1163 pp->printer, pp->remote_host);
1164 sleep(5 * 60);
1165 }
1166 if (i)
1167 pstatus(pp, "sending to %s", pp->remote_host);
1168 /*
1169 * XXX - we should change trstat_init()/trstat_write() to include
1170 * the copycnt in the statistics record it may write.
1171 */
1172 if (type == '\3')
1173 trstat_init(pp, file, job_dfcnt);
1174 for (i = 0; i < stb.st_size; i += SPL_BUFSIZ) {
1175 amt = SPL_BUFSIZ;
1176 if (i + amt > stb.st_size)
1177 amt = stb.st_size - i;
1178 if (sizerr == 0 && read(sfd, buf, amt) != amt)
1179 sizerr = 1;
1180 if (write(pfd, buf, amt) != amt) {
1181 sfres = REPRINT;
1182 goto return_sfres;
1183 }
1184 }
1185
1186 if (sizerr) {
1187 syslog(LOG_INFO, "%s: %s: changed size", pp->printer, file);
1188 /* tell recvjob to ignore this file */
1189 (void) write(pfd, "\1", 1);
1190 sfres = ERROR;
1191 goto return_sfres;
1192 }
1193 if (write(pfd, "", 1) != 1 || response(pp)) {
1194 sfres = REPRINT;
1195 goto return_sfres;
1196 }
1197 if (type == '\3') {
1198 trstat_write(pp, TR_SENDING, stb.st_size, logname,
1199 pp->remote_host, origin_host);
1200 /*
1201 * Usually we only need to send one copy of a datafile,
1202 * because the control-file will simply print the same
1203 * file multiple times. However, some printers ignore
1204 * the control file, and simply print each data file as
1205 * it arrives. For such "remote hosts", we need to
1206 * transfer the same data file multiple times. Such a
1207 * a host is indicated by adding 'rc' to the printcap
1208 * entry.
1209 * XXX - Right now this ONLY works for remote hosts which
1210 * do ignore the name of the data file, because
1211 * this sends the file multiple times with slight
1212 * changes to the filename. To do this right would
1213 * require that we also rewrite the control file
1214 * to match those filenames.
1215 */
1216 if (pp->resend_copies && (copycnt < copyreq)) {
1217 lseek(sfd, 0, SEEK_SET);
1218 goto sendagain;
1219 }
1220 }
1221 sfres = OK;
1222
1223 return_sfres:
1224 (void)close(sfd);
1225 if (tfd != -1) {
1226 /*
1227 * If tfd is set, then it is the same value as sfd, and
1228 * therefore it is already closed at this point. All
1229 * we need to do is remove the temporary file.
1230 */
1231 tfd = -1;
1232 unlink(tfile);
1233 }
1234 return (sfres);
1235 }
1236
1237 /*
1238 * Some print servers send the control-file first, and then start sending the
1239 * matching data file(s). That is not the correct order. If some queue is
1240 * already printing an active job, then when that job is finished the queue
1241 * may proceed to the control file of any incoming print job. This turns
1242 * into a race between the process which is receiving the data file, and the
1243 * process which is actively printing the very same file. When the remote
1244 * server sends files in the wrong order, it is even possible that a queue
1245 * will start to print a data file before the file has been created!
1246 *
1247 * So before we start to print() or send() a data file, we call this routine
1248 * to make sure the data file is not still changing in size. Note that this
1249 * problem will only happen for jobs arriving from a remote host, and that
1250 * the process which has decided to print this job (and is thus making this
1251 * check) is *not* the process which is receiving the job.
1252 *
1253 * A second benefit of this is that any incoming job is guaranteed to appear
1254 * in a queue listing for at least a few seconds after it has arrived. Some
1255 * lpr implementations get confused if they send a job and it disappears
1256 * from the queue before they can check on it.
1257 */
1258 #define MAXWAIT_ARRIVE 16 /* max to wait for the file to *exist* */
1259 #define MAXWAIT_4DATA (20*60) /* max to wait for it to stop changing */
1260 #define MINWAIT_4DATA 4 /* This value must be >= 1 */
1261 #define DEBUG_MINWAIT 1
1262 static void
wait4data(struct printer * pp,const char * dfile)1263 wait4data(struct printer *pp, const char *dfile)
1264 {
1265 const char *cp;
1266 int statres;
1267 u_int sleepreq;
1268 size_t dlen, hlen;
1269 time_t amtslept, cur_time, prev_mtime;
1270 struct stat statdf;
1271
1272 /* Skip these checks if the print job is from the local host. */
1273 dlen = strlen(dfile);
1274 hlen = strlen(local_host);
1275 if (dlen > hlen) {
1276 cp = dfile + dlen - hlen;
1277 if (strcmp(cp, local_host) == 0)
1278 return;
1279 }
1280
1281 /*
1282 * If this data file does not exist, then wait up to MAXWAIT_ARRIVE
1283 * seconds for it to arrive.
1284 */
1285 amtslept = 0;
1286 statres = stat(dfile, &statdf);
1287 while (statres < 0 && amtslept < MAXWAIT_ARRIVE) {
1288 if (amtslept == 0)
1289 pstatus(pp, "Waiting for data file from remote host");
1290 amtslept += MINWAIT_4DATA - sleep(MINWAIT_4DATA);
1291 statres = stat(dfile, &statdf);
1292 }
1293 if (statres < 0) {
1294 /* The file still does not exist, so just give up on it. */
1295 syslog(LOG_WARNING, "%s: wait4data() abandoned wait for %s",
1296 pp->printer, dfile);
1297 return;
1298 }
1299
1300 /*
1301 * The file exists, so keep waiting until the data file has not
1302 * changed for some reasonable amount of time. Extra care is
1303 * taken when computing wait-times, just in case there are data
1304 * files with a last-modify time in the future. While that is
1305 * very unlikely to happen, it can happen when the system has
1306 * a flakey time-of-day clock.
1307 */
1308 prev_mtime = statdf.st_mtime;
1309 cur_time = time(NULL);
1310 if (statdf.st_mtime >= cur_time - MINWAIT_4DATA) {
1311 if (statdf.st_mtime >= cur_time) /* some TOD oddity */
1312 sleepreq = MINWAIT_4DATA;
1313 else
1314 sleepreq = cur_time - statdf.st_mtime;
1315 if (amtslept == 0)
1316 pstatus(pp, "Waiting for data file from remote host");
1317 amtslept += sleepreq - sleep(sleepreq);
1318 statres = stat(dfile, &statdf);
1319 }
1320 sleepreq = MINWAIT_4DATA;
1321 while (statres == 0 && amtslept < MAXWAIT_4DATA) {
1322 if (statdf.st_mtime == prev_mtime)
1323 break;
1324 prev_mtime = statdf.st_mtime;
1325 amtslept += sleepreq - sleep(sleepreq);
1326 statres = stat(dfile, &statdf);
1327 }
1328
1329 if (statres != 0)
1330 syslog(LOG_WARNING, "%s: %s disappeared during wait4data()",
1331 pp->printer, dfile);
1332 else if (amtslept > MAXWAIT_4DATA)
1333 syslog(LOG_WARNING,
1334 "%s: %s still changing after %lu secs in wait4data()",
1335 pp->printer, dfile, (unsigned long)amtslept);
1336 #if DEBUG_MINWAIT
1337 else if (amtslept > MINWAIT_4DATA)
1338 syslog(LOG_INFO, "%s: slept %lu secs in wait4data(%s)",
1339 pp->printer, (unsigned long)amtslept, dfile);
1340 #endif
1341 }
1342 #undef MAXWAIT_ARRIVE
1343 #undef MAXWAIT_4DATA
1344 #undef MINWAIT_4DATA
1345
1346 /*
1347 * This routine is called to execute one of the filters as was
1348 * specified in a printcap entry. While the child-process will read
1349 * all of 'infd', it is up to the caller to close that file descriptor
1350 * in the parent process.
1351 */
1352 static int
execfilter(struct printer * pp,char * f_cmd,char * f_av[],int infd,int outfd)1353 execfilter(struct printer *pp, char *f_cmd, char *f_av[], int infd, int outfd)
1354 {
1355 pid_t fpid, wpid;
1356 int errfd, retcode, wstatus;
1357 FILE *errfp;
1358 char buf[BUFSIZ], *slash;
1359
1360 fpid = dofork(pp, DORETURN);
1361 if (fpid != 0) {
1362 /*
1363 * This is the parent process, which just waits for the child
1364 * to complete and then returns the result. Note that it is
1365 * the child process which reads the input stream.
1366 */
1367 if (fpid < 0)
1368 retcode = 100;
1369 else {
1370 while ((wpid = wait(&wstatus)) > 0 &&
1371 wpid != fpid)
1372 ;
1373 if (wpid < 0) {
1374 retcode = 100;
1375 syslog(LOG_WARNING,
1376 "%s: after execv(%s), wait() returned: %m",
1377 pp->printer, f_cmd);
1378 } else
1379 retcode = WEXITSTATUS(wstatus);
1380 }
1381
1382 /*
1383 * Copy everything the filter wrote to stderr from our
1384 * temporary errors file to the "lf=" logfile.
1385 */
1386 errfp = fopen(tempstderr, "r");
1387 if (errfp) {
1388 while (fgets(buf, sizeof(buf), errfp))
1389 fputs(buf, stderr);
1390 fclose(errfp);
1391 }
1392
1393 return (retcode);
1394 }
1395
1396 /*
1397 * This is the child process, which is the one that executes the
1398 * given filter.
1399 */
1400 /*
1401 * If the first parameter has any slashes in it, then change it
1402 * to point to the first character after the last slash.
1403 */
1404 slash = strrchr(f_av[0], '/');
1405 if (slash != NULL)
1406 f_av[0] = slash + 1;
1407 /*
1408 * XXX - in the future, this should setup an explicit list of
1409 * environment variables and use execve()!
1410 */
1411
1412 /*
1413 * Setup stdin, stdout, and stderr as we want them when the filter
1414 * is running. Stderr is setup so it points to a temporary errors
1415 * file, and the parent process will copy that temporary file to
1416 * the real logfile after the filter completes.
1417 */
1418 dup2(infd, STDIN_FILENO);
1419 dup2(outfd, STDOUT_FILENO);
1420 errfd = open(tempstderr, O_WRONLY|O_TRUNC, 0664);
1421 if (errfd >= 0)
1422 dup2(errfd, STDERR_FILENO);
1423 closelog();
1424 closeallfds(3);
1425 execv(f_cmd, f_av);
1426 syslog(LOG_ERR, "%s: cannot execv(%s): %m", pp->printer, f_cmd);
1427 exit(2);
1428 /* NOTREACHED */
1429 }
1430
1431 /*
1432 * Check to make sure there have been no errors and that both programs
1433 * are in sync with eachother.
1434 * Return non-zero if the connection was lost.
1435 */
1436 static char
response(const struct printer * pp)1437 response(const struct printer *pp)
1438 {
1439 char resp;
1440
1441 if (read(pfd, &resp, 1) != 1) {
1442 syslog(LOG_INFO, "%s: lost connection", pp->printer);
1443 return (-1);
1444 }
1445 return (resp);
1446 }
1447
1448 /*
1449 * Banner printing stuff
1450 */
1451 static void
banner(struct printer * pp,char * name1,char * name2)1452 banner(struct printer *pp, char *name1, char *name2)
1453 {
1454 time_t tvec;
1455
1456 time(&tvec);
1457 if (!pp->no_formfeed && !pp->tof)
1458 (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
1459 if (pp->short_banner) { /* short banner only */
1460 if (class[0]) {
1461 (void) write(ofd, class, strlen(class));
1462 (void) write(ofd, ":", 1);
1463 }
1464 (void) write(ofd, name1, strlen(name1));
1465 (void) write(ofd, " Job: ", 7);
1466 (void) write(ofd, name2, strlen(name2));
1467 (void) write(ofd, " Date: ", 8);
1468 (void) write(ofd, ctime(&tvec), 24);
1469 (void) write(ofd, "\n", 1);
1470 } else { /* normal banner */
1471 (void) write(ofd, "\n\n\n", 3);
1472 scan_out(pp, ofd, name1, '\0');
1473 (void) write(ofd, "\n\n", 2);
1474 scan_out(pp, ofd, name2, '\0');
1475 if (class[0]) {
1476 (void) write(ofd,"\n\n\n",3);
1477 scan_out(pp, ofd, class, '\0');
1478 }
1479 (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15);
1480 (void) write(ofd, name2, strlen(name2));
1481 (void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
1482 (void) write(ofd, ctime(&tvec), 24);
1483 (void) write(ofd, "\n", 1);
1484 }
1485 if (!pp->no_formfeed)
1486 (void) write(ofd, pp->form_feed, strlen(pp->form_feed));
1487 pp->tof = 1;
1488 }
1489
1490 static char *
scnline(int key,char * p,int c)1491 scnline(int key, char *p, int c)
1492 {
1493 register int scnwidth;
1494
1495 for (scnwidth = WIDTH; --scnwidth;) {
1496 key <<= 1;
1497 *p++ = key & 0200 ? c : BACKGND;
1498 }
1499 return (p);
1500 }
1501
1502 #define TRC(q) (((q)-' ')&0177)
1503
1504 static void
scan_out(struct printer * pp,int scfd,char * scsp,int dlm)1505 scan_out(struct printer *pp, int scfd, char *scsp, int dlm)
1506 {
1507 register char *strp;
1508 register int nchrs, j;
1509 char outbuf[LINELEN+1], *sp, c, cc;
1510 int d, scnhgt;
1511
1512 for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
1513 strp = &outbuf[0];
1514 sp = scsp;
1515 for (nchrs = 0; ; ) {
1516 d = dropit(c = TRC(cc = *sp++));
1517 if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
1518 for (j = WIDTH; --j;)
1519 *strp++ = BACKGND;
1520 else
1521 strp = scnline(scnkey[(int)c][scnhgt-1-d], strp, cc);
1522 if (*sp == dlm || *sp == '\0' ||
1523 nchrs++ >= pp->page_width/(WIDTH+1)-1)
1524 break;
1525 *strp++ = BACKGND;
1526 *strp++ = BACKGND;
1527 }
1528 while (*--strp == BACKGND && strp >= outbuf)
1529 ;
1530 strp++;
1531 *strp++ = '\n';
1532 (void) write(scfd, outbuf, strp-outbuf);
1533 }
1534 }
1535
1536 static int
dropit(int c)1537 dropit(int c)
1538 {
1539 switch(c) {
1540
1541 case TRC('_'):
1542 case TRC(';'):
1543 case TRC(','):
1544 case TRC('g'):
1545 case TRC('j'):
1546 case TRC('p'):
1547 case TRC('q'):
1548 case TRC('y'):
1549 return (DROP);
1550
1551 default:
1552 return (0);
1553 }
1554 }
1555
1556 /*
1557 * sendmail ---
1558 * tell people about job completion
1559 */
1560 static void
sendmail(struct printer * pp,char * userid,int bombed)1561 sendmail(struct printer *pp, char *userid, int bombed)
1562 {
1563 register int i;
1564 int p[2], s;
1565 register const char *cp;
1566 struct stat stb;
1567 FILE *fp;
1568
1569 pipe(p);
1570 if ((s = dofork(pp, DORETURN)) == 0) { /* child */
1571 dup2(p[0], STDIN_FILENO);
1572 closelog();
1573 closeallfds(3);
1574 if ((cp = strrchr(_PATH_SENDMAIL, '/')) != NULL)
1575 cp++;
1576 else
1577 cp = _PATH_SENDMAIL;
1578 execl(_PATH_SENDMAIL, cp, "-t", (char *)0);
1579 _exit(0);
1580 } else if (s > 0) { /* parent */
1581 dup2(p[1], STDOUT_FILENO);
1582 printf("To: %s@%s\n", userid, origin_host);
1583 printf("Subject: %s printer job \"%s\"\n", pp->printer,
1584 *jobname ? jobname : "<unknown>");
1585 printf("Reply-To: root@%s\n\n", local_host);
1586 printf("Your printer job ");
1587 if (*jobname)
1588 printf("(%s) ", jobname);
1589
1590 switch (bombed) {
1591 case OK:
1592 cp = "OK";
1593 printf("\ncompleted successfully\n");
1594 break;
1595 default:
1596 case FATALERR:
1597 cp = "FATALERR";
1598 printf("\ncould not be printed\n");
1599 break;
1600 case NOACCT:
1601 cp = "NOACCT";
1602 printf("\ncould not be printed without an account on %s\n",
1603 local_host);
1604 break;
1605 case FILTERERR:
1606 cp = "FILTERERR";
1607 if (stat(tempstderr, &stb) < 0 || stb.st_size == 0
1608 || (fp = fopen(tempstderr, "r")) == NULL) {
1609 printf("\nhad some errors and may not have printed\n");
1610 break;
1611 }
1612 printf("\nhad the following errors and may not have printed:\n");
1613 while ((i = getc(fp)) != EOF)
1614 putchar(i);
1615 (void) fclose(fp);
1616 break;
1617 case ACCESS:
1618 cp = "ACCESS";
1619 printf("\nwas not printed because it was not linked to the original file\n");
1620 }
1621 fflush(stdout);
1622 (void) close(STDOUT_FILENO);
1623 } else {
1624 syslog(LOG_WARNING, "unable to send mail to %s: %m", userid);
1625 return;
1626 }
1627 (void) close(p[0]);
1628 (void) close(p[1]);
1629 wait(NULL);
1630 syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)",
1631 userid, *jobname ? jobname : "<unknown>", pp->printer, cp);
1632 }
1633
1634 /*
1635 * dofork - fork with retries on failure
1636 */
1637 static int
dofork(const struct printer * pp,int action)1638 dofork(const struct printer *pp, int action)
1639 {
1640 pid_t forkpid;
1641 int i, fail;
1642 struct passwd *pwd;
1643
1644 forkpid = -1;
1645 if (daemon_uname == NULL) {
1646 pwd = getpwuid(pp->daemon_user);
1647 if (pwd == NULL) {
1648 syslog(LOG_ERR, "%s: Can't lookup default daemon uid (%ld) in password file",
1649 pp->printer, pp->daemon_user);
1650 goto error_ret;
1651 }
1652 daemon_uname = strdup(pwd->pw_name);
1653 daemon_defgid = pwd->pw_gid;
1654 }
1655
1656 for (i = 0; i < 20; i++) {
1657 forkpid = fork();
1658 if (forkpid < 0) {
1659 sleep((unsigned)(i*i));
1660 continue;
1661 }
1662 /*
1663 * Child should run as daemon instead of root
1664 */
1665 if (forkpid == 0) {
1666 errno = 0;
1667 fail = initgroups(daemon_uname, daemon_defgid);
1668 if (fail) {
1669 syslog(LOG_ERR, "%s: initgroups(%s,%u): %m",
1670 pp->printer, daemon_uname, daemon_defgid);
1671 break;
1672 }
1673 fail = setgid(daemon_defgid);
1674 if (fail) {
1675 syslog(LOG_ERR, "%s: setgid(%u): %m",
1676 pp->printer, daemon_defgid);
1677 break;
1678 }
1679 fail = setuid(pp->daemon_user);
1680 if (fail) {
1681 syslog(LOG_ERR, "%s: setuid(%ld): %m",
1682 pp->printer, pp->daemon_user);
1683 break;
1684 }
1685 }
1686 return (forkpid);
1687 }
1688
1689 /*
1690 * An error occurred. If the error is in the child process, then
1691 * this routine MUST always exit(). DORETURN only effects how
1692 * errors should be handled in the parent process.
1693 */
1694 error_ret:
1695 if (forkpid == 0) {
1696 syslog(LOG_ERR, "%s: dofork(): aborting child process...",
1697 pp->printer);
1698 exit(1);
1699 }
1700 syslog(LOG_ERR, "%s: dofork(): failure in fork", pp->printer);
1701
1702 sleep(1); /* throttle errors, as a safety measure */
1703 switch (action) {
1704 case DORETURN:
1705 return (-1);
1706 default:
1707 syslog(LOG_ERR, "bad action (%d) to dofork", action);
1708 /* FALLTHROUGH */
1709 case DOABORT:
1710 exit(1);
1711 }
1712 /*NOTREACHED*/
1713 }
1714
1715 /*
1716 * Kill child processes to abort current job.
1717 */
1718 static void
abortpr(int signo __unused)1719 abortpr(int signo __unused)
1720 {
1721
1722 (void) unlink(tempstderr);
1723 kill(0, SIGINT);
1724 if (of_pid > 0)
1725 kill(of_pid, SIGCONT);
1726 while (wait(NULL) > 0)
1727 ;
1728 if (of_pid > 0 && tfd != -1)
1729 unlink(tfile);
1730 exit(0);
1731 }
1732
1733 static void
init(struct printer * pp)1734 init(struct printer *pp)
1735 {
1736 char *s;
1737
1738 sprintf(&width[2], "%ld", pp->page_width);
1739 sprintf(&length[2], "%ld", pp->page_length);
1740 sprintf(&pxwidth[2], "%ld", pp->page_pwidth);
1741 sprintf(&pxlength[2], "%ld", pp->page_plength);
1742 if ((s = checkremote(pp)) != NULL) {
1743 syslog(LOG_WARNING, "%s", s);
1744 free(s);
1745 }
1746 }
1747
1748 void
startprinting(const char * printer)1749 startprinting(const char *printer)
1750 {
1751 struct printer myprinter, *pp = &myprinter;
1752 int status;
1753
1754 init_printer(pp);
1755 status = getprintcap(printer, pp);
1756 switch(status) {
1757 case PCAPERR_OSERR:
1758 syslog(LOG_ERR, "can't open printer description file: %m");
1759 exit(1);
1760 case PCAPERR_NOTFOUND:
1761 syslog(LOG_ERR, "unknown printer: %s", printer);
1762 exit(1);
1763 case PCAPERR_TCLOOP:
1764 fatal(pp, "potential reference loop detected in printcap file");
1765 default:
1766 break;
1767 }
1768 printjob(pp);
1769 }
1770
1771 /*
1772 * Acquire line printer or remote connection.
1773 */
1774 static void
openpr(const struct printer * pp)1775 openpr(const struct printer *pp)
1776 {
1777 int p[2];
1778 char *cp;
1779
1780 if (pp->remote) {
1781 openrem(pp);
1782 /*
1783 * Lpd does support the setting of 'of=' filters for
1784 * jobs going to remote machines, but that does not
1785 * have the same meaning as 'of=' does when handling
1786 * local print queues. For remote machines, all 'of='
1787 * filter processing is handled in sendfile(), and that
1788 * does not use these global "output filter" variables.
1789 */
1790 ofd = -1;
1791 of_pid = 0;
1792 return;
1793 } else if (*pp->lp) {
1794 if (strchr(pp->lp, '@') != NULL)
1795 opennet(pp);
1796 else
1797 opentty(pp);
1798 } else {
1799 syslog(LOG_ERR, "%s: no line printer device or host name",
1800 pp->printer);
1801 exit(1);
1802 }
1803
1804 /*
1805 * Start up an output filter, if needed.
1806 */
1807 if (pp->filters[LPF_OUTPUT] && !pp->filters[LPF_INPUT] && !of_pid) {
1808 pipe(p);
1809 if (pp->remote) {
1810 strcpy(tfile, TFILENAME);
1811 tfd = mkstemp(tfile);
1812 }
1813 if ((of_pid = dofork(pp, DOABORT)) == 0) { /* child */
1814 dup2(p[0], STDIN_FILENO); /* pipe is std in */
1815 /* tfile/printer is stdout */
1816 dup2(pp->remote ? tfd : pfd, STDOUT_FILENO);
1817 closelog();
1818 closeallfds(3);
1819 if ((cp = strrchr(pp->filters[LPF_OUTPUT], '/')) == NULL)
1820 cp = pp->filters[LPF_OUTPUT];
1821 else
1822 cp++;
1823 execl(pp->filters[LPF_OUTPUT], cp, width, length,
1824 (char *)0);
1825 syslog(LOG_ERR, "%s: execl(%s): %m", pp->printer,
1826 pp->filters[LPF_OUTPUT]);
1827 exit(1);
1828 }
1829 (void) close(p[0]); /* close input side */
1830 ofd = p[1]; /* use pipe for output */
1831 } else {
1832 ofd = pfd;
1833 of_pid = 0;
1834 }
1835 }
1836
1837 /*
1838 * Printer connected directly to the network
1839 * or to a terminal server on the net
1840 */
1841 static void
opennet(const struct printer * pp)1842 opennet(const struct printer *pp)
1843 {
1844 register int i;
1845 int resp;
1846 u_long port;
1847 char *ep;
1848 void (*savealrm)(int);
1849
1850 port = strtoul(pp->lp, &ep, 0);
1851 if (*ep != '@' || port > 65535) {
1852 syslog(LOG_ERR, "%s: bad port number: %s", pp->printer,
1853 pp->lp);
1854 exit(1);
1855 }
1856 ep++;
1857
1858 for (i = 1; ; i = i < 256 ? i << 1 : i) {
1859 resp = -1;
1860 savealrm = signal(SIGALRM, alarmhandler);
1861 alarm(pp->conn_timeout);
1862 pfd = getport(pp, ep, port);
1863 alarm(0);
1864 (void)signal(SIGALRM, savealrm);
1865 if (pfd < 0 && errno == ECONNREFUSED)
1866 resp = 1;
1867 else if (pfd >= 0) {
1868 /*
1869 * need to delay a bit for rs232 lines
1870 * to stabilize in case printer is
1871 * connected via a terminal server
1872 */
1873 delay(500);
1874 break;
1875 }
1876 if (i == 1) {
1877 if (resp < 0)
1878 pstatus(pp, "waiting for %s to come up",
1879 pp->lp);
1880 else
1881 pstatus(pp,
1882 "waiting for access to printer on %s",
1883 pp->lp);
1884 }
1885 sleep(i);
1886 }
1887 pstatus(pp, "sending to %s port %lu", ep, port);
1888 }
1889
1890 /*
1891 * Printer is connected to an RS232 port on this host
1892 */
1893 static void
opentty(const struct printer * pp)1894 opentty(const struct printer *pp)
1895 {
1896 register int i;
1897
1898 for (i = 1; ; i = i < 32 ? i << 1 : i) {
1899 pfd = open(pp->lp, pp->rw ? O_RDWR : O_WRONLY);
1900 if (pfd >= 0) {
1901 delay(500);
1902 break;
1903 }
1904 if (errno == ENOENT) {
1905 syslog(LOG_ERR, "%s: %m", pp->lp);
1906 exit(1);
1907 }
1908 if (i == 1)
1909 pstatus(pp,
1910 "waiting for %s to become ready (offline?)",
1911 pp->printer);
1912 sleep(i);
1913 }
1914 if (isatty(pfd))
1915 setty(pp);
1916 pstatus(pp, "%s is ready and printing", pp->printer);
1917 }
1918
1919 /*
1920 * Printer is on a remote host
1921 */
1922 static void
openrem(const struct printer * pp)1923 openrem(const struct printer *pp)
1924 {
1925 register int i;
1926 int resp;
1927 void (*savealrm)(int);
1928
1929 for (i = 1; ; i = i < 256 ? i << 1 : i) {
1930 resp = -1;
1931 savealrm = signal(SIGALRM, alarmhandler);
1932 alarm(pp->conn_timeout);
1933 pfd = getport(pp, pp->remote_host, 0);
1934 alarm(0);
1935 (void)signal(SIGALRM, savealrm);
1936 if (pfd >= 0) {
1937 if ((writel(pfd, "\2", pp->remote_queue, "\n",
1938 (char *)0)
1939 == 2 + strlen(pp->remote_queue))
1940 && (resp = response(pp)) == 0)
1941 break;
1942 (void) close(pfd);
1943 }
1944 if (i == 1) {
1945 if (resp < 0)
1946 pstatus(pp, "waiting for %s to come up",
1947 pp->remote_host);
1948 else {
1949 pstatus(pp,
1950 "waiting for queue to be enabled on %s",
1951 pp->remote_host);
1952 i = 256;
1953 }
1954 }
1955 sleep(i);
1956 }
1957 pstatus(pp, "sending to %s", pp->remote_host);
1958 }
1959
1960 /*
1961 * setup tty lines.
1962 */
1963 static void
setty(const struct printer * pp)1964 setty(const struct printer *pp)
1965 {
1966 struct termios ttybuf;
1967
1968 if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
1969 syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", pp->printer);
1970 exit(1);
1971 }
1972 if (tcgetattr(pfd, &ttybuf) < 0) {
1973 syslog(LOG_ERR, "%s: tcgetattr: %m", pp->printer);
1974 exit(1);
1975 }
1976 if (pp->baud_rate > 0)
1977 cfsetspeed(&ttybuf, pp->baud_rate);
1978 if (pp->mode_set) {
1979 char *s = strdup(pp->mode_set), *tmp;
1980
1981 while ((tmp = strsep(&s, ",")) != NULL) {
1982 (void) msearch(tmp, &ttybuf);
1983 }
1984 }
1985 if (pp->mode_set != 0 || pp->baud_rate > 0) {
1986 if (tcsetattr(pfd, TCSAFLUSH, &ttybuf) == -1) {
1987 syslog(LOG_ERR, "%s: tcsetattr: %m", pp->printer);
1988 }
1989 }
1990 }
1991
1992 #include <stdarg.h>
1993
1994 static void
pstatus(const struct printer * pp,const char * msg,...)1995 pstatus(const struct printer *pp, const char *msg, ...)
1996 {
1997 int fd;
1998 char *buf;
1999 va_list ap;
2000 va_start(ap, msg);
2001
2002 umask(S_IWOTH);
2003 fd = open(pp->status_file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE);
2004 if (fd < 0) {
2005 syslog(LOG_ERR, "%s: open(%s): %m", pp->printer,
2006 pp->status_file);
2007 exit(1);
2008 }
2009 ftruncate(fd, 0);
2010 vasprintf(&buf, msg, ap);
2011 va_end(ap);
2012 writel(fd, buf, "\n", (char *)0);
2013 close(fd);
2014 free(buf);
2015 }
2016
2017 void
alarmhandler(int signo __unused)2018 alarmhandler(int signo __unused)
2019 {
2020 /* the signal is ignored */
2021 /* (the '__unused' is just to avoid a compile-time warning) */
2022 }
2023