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