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
85static dev_t	 fdev;		/* device of file pointed to by symlink */
86static ino_t	 fino;		/* inode of file pointed to by symlink */
87static FILE	*cfp;		/* control file */
88static pid_t	 of_pid;	/* process id of output filter, if any */
89static int	 child;		/* id of any filters */
90static int	 job_dfcnt;	/* count of datafiles in current user job */
91static int	 lfd;		/* lock file descriptor */
92static int	 ofd;		/* output filter file descriptor */
93static int	 tfd = -1;	/* output filter temp file output */
94static int	 pfd;		/* prstatic inter file descriptor */
95static int	 prchild;	/* id of pr process */
96static char	 title[80];	/* ``pr'' title */
97static char      locale[80];    /* ``pr'' locale */
98
99/* these two are set from pp->daemon_user, but only if they are needed */
100static char	*daemon_uname;	/* set from pwd->pw_name */
101static int	 daemon_defgid;
102
103static char	class[32];		/* classification field */
104static char	origin_host[MAXHOSTNAMELEN];	/* user's host machine */
105				/* indentation size in static characters */
106static char	indent[10] = "-i0";
107static char	jobname[100];		/* job or file name */
108static char	length[10] = "-l";	/* page length in lines */
109static char	logname[32];		/* user's login name */
110static char	pxlength[10] = "-y";	/* page length in pixels */
111static char	pxwidth[10] = "-x";	/* page width in pixels */
112/* tempstderr is the filename used to catch stderr from exec-ing filters */
113static char	tempstderr[] = "errs.XXXXXXX";
114static char	width[10] = "-w";	/* page width in static characters */
115#define TFILENAME "fltXXXXXX"
116static char	tfile[] = TFILENAME;	/* file name for filter output */
117
118static void	 abortpr(int _signo);
119static void	 alarmhandler(int _signo);
120static void	 banner(struct printer *_pp, char *_name1, char *_name2);
121static int	 dofork(const struct printer *_pp, int _action);
122static int	 dropit(int _c);
123static int	 execfilter(struct printer *_pp, char *_f_cmd, char **_f_av,
124		    int _infd, int _outfd);
125static void	 init(struct printer *_pp);
126static void	 openpr(const struct printer *_pp);
127static void	 opennet(const struct printer *_pp);
128static void	 opentty(const struct printer *_pp);
129static void	 openrem(const struct printer *pp);
130static int	 print(struct printer *_pp, int _format, char *_file);
131static int	 printit(struct printer *_pp, char *_file);
132static void	 pstatus(const struct printer *_pp, const char *_msg, ...)
133		    __printflike(2, 3);
134static char	 response(const struct printer *_pp);
135static void	 scan_out(struct printer *_pp, int _scfd, char *_scsp,
136		    int _dlm);
137static char	*scnline(int _key, char *_p, int _c);
138static int	 sendfile(struct printer *_pp, int _type, char *_file,
139		    char _format, int _copyreq);
140static int	 sendit(struct printer *_pp, char *_file);
141static void	 sendmail(struct printer *_pp, char *_userid, int _bombed);
142static void	 setty(const struct printer *_pp);
143static void	 wait4data(struct printer *_pp, const char *_dfile);
144
145void
146printjob(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 */
256again:
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
361char	fonts[4][50];	/* fonts for troff */
362
363char 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 */
374static int
375printit(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
566pass2:
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 */
603static int
604print(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	}
807start:
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 */
882static int
883sendit(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 */
989static int
990sendfile(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;
1127sendagain:
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
1209return_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
1248static void
1249wait4data(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 */
1338static int
1339execfilter(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 */
1422static char
1423response(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 */
1437static void
1438banner(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
1476static char *
1477scnline(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
1490static void
1491scan_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
1522static int
1523dropit(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 */
1546static void
1547sendmail(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 */
1623static int
1624dofork(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	 */
1680error_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 */
1704static void
1705abortpr(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
1719static void
1720init(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
1734void
1735startprinting(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 */
1760static void
1761openpr(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 */
1827static void
1828opennet(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 */
1879static void
1880opentty(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 */
1908static void
1909openrem(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 */
1949static void
1950setty(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
1980static void
1981pstatus(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
2003void
2004alarmhandler(int signo __unused)
2005{
2006	/* the signal is ignored */
2007	/* (the '__unused' is just to avoid a compile-time warning) */
2008}
2009