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