xref: /csrg-svn/usr.sbin/lpr/lpd/printjob.c (revision 16762)
113954Ssam #ifndef lint
2*16762Sralph static char sccsid[] = "@(#)printjob.c	4.18 (Berkeley) 07/25/84";
313954Ssam #endif
413954Ssam 
512111Sralph /*
612111Sralph  * printjob -- print jobs in the queue.
712111Sralph  *
812111Sralph  *	NOTE: the lock file is used to pass information to lpq and lprm.
912111Sralph  *	it does not need to be removed because file locks are dynamic.
1012111Sralph  */
1112111Sralph 
1212111Sralph #include "lp.h"
1312111Sralph 
14*16762Sralph #define DORETURN	0	/* absorb fork error */
15*16762Sralph #define DOABORT		1	/* abort if dofork fails */
1612111Sralph 
17*16762Sralph char	title[80];		/* ``pr'' title */
18*16762Sralph FILE	*cfp;			/* control file */
19*16762Sralph int	pfd;			/* printer file descriptor */
20*16762Sralph int	ofd;			/* output filter file descriptor */
21*16762Sralph int	lfd;			/* lock file descriptor */
22*16762Sralph int	pid;			/* pid of lpd process */
23*16762Sralph int	prchild;		/* id of pr process */
24*16762Sralph int	child;			/* id of any filters */
25*16762Sralph int	ofilter;		/* id of output filter, if any */
26*16762Sralph int	tof;			/* true if at top of form */
27*16762Sralph int	remote;			/* true if sending files to remote */
2812111Sralph 
29*16762Sralph char	fromhost[32];		/* user's host machine */
30*16762Sralph char	logname[32];		/* user's login name */
31*16762Sralph char	jobname[100];		/* job or file name */
32*16762Sralph char	class[32];		/* classification field */
33*16762Sralph char	width[10] = "-w";	/* page width in characters */
34*16762Sralph char	length[10] = "-l";	/* page length in lines */
35*16762Sralph char	pxwidth[10] = "-x";	/* page width in pixels */
36*16762Sralph char	pxlength[10] = "-y";	/* page length in pixels */
37*16762Sralph char	indent[10] = "-i0";	/* indentation size in characters */
38*16762Sralph char	tmpfile[] = "errsXXXXXX"; /* file name for filter output */
3912111Sralph 
4012111Sralph printjob()
4112111Sralph {
4212111Sralph 	struct stat stb;
4312111Sralph 	register struct queue *q, **qp;
4412111Sralph 	struct queue **queue;
4512111Sralph 	register int i, nitems;
4612111Sralph 	long pidoff;
47*16762Sralph 	int count = 0;
48*16762Sralph 	extern int abortpr();
4912111Sralph 
5012111Sralph 	init();					/* set up capabilities */
5113442Sralph 	(void) write(1, "", 1);			/* ack that daemon is started */
52*16762Sralph 	setgid(getegid());
5312463Sralph 	pid = getpid();				/* for use with lprm */
5412111Sralph 	setpgrp(0, pid);
55*16762Sralph 	signal(SIGHUP, abortpr);
56*16762Sralph 	signal(SIGINT, abortpr);
57*16762Sralph 	signal(SIGQUIT, abortpr);
58*16762Sralph 	signal(SIGTERM, abortpr);
5912111Sralph 
6015811Sralph 	(void) mktemp(tmpfile);
6115811Sralph 
6212111Sralph 	/*
6312111Sralph 	 * uses short form file names
6412111Sralph 	 */
6512111Sralph 	if (chdir(SD) < 0) {
66*16762Sralph 		syslog(LOG_ERR, "%s: %m", SD);
6712111Sralph 		exit(1);
6812111Sralph 	}
6912463Sralph 	if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
7012463Sralph 		exit(0);		/* printing disabled */
7114150Sralph 	lfd = open(LO, O_WRONLY|O_CREAT, 0644);
7213169Sralph 	if (lfd < 0) {
73*16762Sralph 		syslog(LOG_ERR, "%s: %s: %m", printer, LO);
7413169Sralph 		exit(1);
7513169Sralph 	}
7613169Sralph 	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
7712111Sralph 		if (errno == EWOULDBLOCK)	/* active deamon present */
7812111Sralph 			exit(0);
79*16762Sralph 		syslog(LOG_ERR, "%s: %s: %m", printer, LO);
8012111Sralph 		exit(1);
8112111Sralph 	}
8213148Ssam 	ftruncate(lfd, 0);
8312111Sralph 	/*
8412111Sralph 	 * write process id for others to know
8512111Sralph 	 */
8612111Sralph 	sprintf(line, "%u\n", pid);
8712111Sralph 	pidoff = i = strlen(line);
8812463Sralph 	if (write(lfd, line, i) != i) {
89*16762Sralph 		syslog(LOG_ERR, "%s: %s: %m", printer, LO);
9012111Sralph 		exit(1);
9112111Sralph 	}
9212111Sralph 	/*
9312111Sralph 	 * search the spool directory for work and sort by queue order.
9412111Sralph 	 */
9512111Sralph 	if ((nitems = getq(&queue)) < 0) {
96*16762Sralph 		syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
9712111Sralph 		exit(1);
9812111Sralph 	}
9912463Sralph 	if (nitems == 0)		/* no work to do */
10012111Sralph 		exit(0);
10113169Sralph 	if (stb.st_mode & 01) {		/* reset queue flag */
10213169Sralph 		if (fchmod(lfd, stb.st_mode & 0776) < 0)
103*16762Sralph 			syslog(LOG_ERR, "%s: %s: %m", printer, LO);
10413169Sralph 	}
10512463Sralph 	openpr();			/* open printer or remote */
10612463Sralph again:
10712111Sralph 	/*
10812111Sralph 	 * we found something to do now do it --
10912111Sralph 	 *    write the name of the current control file into the lock file
11012111Sralph 	 *    so the spool queue program can tell what we're working on
11112111Sralph 	 */
11212111Sralph 	for (qp = queue; nitems--; free((char *) q)) {
11312111Sralph 		q = *qp++;
11412111Sralph 		if (stat(q->q_name, &stb) < 0)
11512111Sralph 			continue;
11612463Sralph 	restart:
11712111Sralph 		(void) lseek(lfd, pidoff, 0);
11812111Sralph 		(void) sprintf(line, "%s\n", q->q_name);
11912111Sralph 		i = strlen(line);
12012111Sralph 		if (write(lfd, line, i) != i)
121*16762Sralph 			syslog(LOG_ERR, "%s: %s: %m", printer, LO);
12212111Sralph 		if (!remote)
12312111Sralph 			i = printit(q->q_name);
12412111Sralph 		else
12512111Sralph 			i = sendit(q->q_name);
12612463Sralph 		/*
12713169Sralph 		 * Check to see if we are supposed to stop printing or
12813169Sralph 		 * if we are to rebuild the queue.
12912463Sralph 		 */
13013169Sralph 		if (fstat(lfd, &stb) == 0) {
131*16762Sralph 			/* stop printing before starting next job? */
13213169Sralph 			if (stb.st_mode & 0100)
13313169Sralph 				goto done;
134*16762Sralph 			/* rebuild queue (after lpc topq) */
13513169Sralph 			if (stb.st_mode & 01) {
13613169Sralph 				for (free((char *) q); nitems--; free((char *) q))
13713169Sralph 					q = *qp++;
13813169Sralph 				if (fchmod(lfd, stb.st_mode & 0776) < 0)
139*16762Sralph 					syslog(LOG_WARNING, "%s: %s: %m",
140*16762Sralph 						printer, LO);
14113169Sralph 				break;
14213169Sralph 			}
14313169Sralph 		}
14414150Sralph 		if (i == 0)		/* file ok and printed */
14514150Sralph 			count++;
14614150Sralph 		else if (i > 0) {	/* try reprinting the job */
147*16762Sralph 			syslog(LOG_INFO, "restarting %s", printer);
14812111Sralph 			if (ofilter > 0) {
14912111Sralph 				kill(ofilter, SIGCONT);	/* to be sure */
15012111Sralph 				(void) close(ofd);
15112111Sralph 				while ((i = wait(0)) > 0 && i != ofilter)
15212111Sralph 					;
15312111Sralph 				ofilter = 0;
15412111Sralph 			}
15512463Sralph 			(void) close(pfd);	/* close printer */
15615811Sralph 			if (ftruncate(lfd, pidoff) < 0)
157*16762Sralph 				syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
15812463Sralph 			openpr();		/* try to reopen printer */
15912111Sralph 			goto restart;
16012111Sralph 		}
16112111Sralph 	}
16212111Sralph 	free((char *) queue);
16312463Sralph 	/*
16412463Sralph 	 * search the spool directory for more work.
16512463Sralph 	 */
16612463Sralph 	if ((nitems = getq(&queue)) < 0) {
167*16762Sralph 		syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
16812463Sralph 		exit(1);
16912463Sralph 	}
17012463Sralph 	if (nitems == 0) {		/* no more work to do */
17112463Sralph 	done:
17214150Sralph 		if (count > 0) {	/* Files actually printed */
17314150Sralph 			if (!SF && !tof)
17414150Sralph 				(void) write(ofd, FF, strlen(FF));
17514150Sralph 			if (TR != NULL)		/* output trailer */
17614150Sralph 				(void) write(ofd, TR, strlen(TR));
17714150Sralph 		}
17815811Sralph 		(void) unlink(tmpfile);
17912463Sralph 		exit(0);
18012463Sralph 	}
18112111Sralph 	goto again;
18212111Sralph }
18312111Sralph 
18412111Sralph char	fonts[4][50];	/* fonts for troff */
18512111Sralph 
186*16762Sralph char ifonts[4][18] = {
18712111Sralph 	"/usr/lib/vfont/R",
18812111Sralph 	"/usr/lib/vfont/I",
18912111Sralph 	"/usr/lib/vfont/B",
19012111Sralph 	"/usr/lib/vfont/S"
19112111Sralph };
19212111Sralph 
19312111Sralph /*
19412111Sralph  * The remaining part is the reading of the control file (cf)
19512111Sralph  * and performing the various actions.
19612111Sralph  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
19712111Sralph  * -1 if a non-recoverable error occured.
19812111Sralph  */
19912111Sralph printit(file)
20012111Sralph 	char *file;
20112111Sralph {
20212111Sralph 	register int i;
20312111Sralph 	int bombed = 0;
20412111Sralph 
20512111Sralph 	/*
20612111Sralph 	 * open control file
20712111Sralph 	 */
20812111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
209*16762Sralph 		syslog(LOG_INFO, "%s: %s: %m", printer, file);
21012111Sralph 		return(0);
21112111Sralph 	}
21212111Sralph 	/*
21312111Sralph 	 * Reset troff fonts.
21412111Sralph 	 */
21512111Sralph 	for (i = 0; i < 4; i++)
21612111Sralph 		strcpy(fonts[i], ifonts[i]);
21712111Sralph 
21812111Sralph 	/*
21912111Sralph 	 *      read the control file for work to do
22012111Sralph 	 *
22112111Sralph 	 *      file format -- first character in the line is a command
22212111Sralph 	 *      rest of the line is the argument.
22312111Sralph 	 *      valid commands are:
22412111Sralph 	 *
22512111Sralph 	 *		J -- "job name" on banner page
22612111Sralph 	 *		C -- "class name" on banner page
22712111Sralph 	 *              L -- "literal" user's name to print on banner
22812111Sralph 	 *		T -- "title" for pr
22912111Sralph 	 *		H -- "host name" of machine where lpr was done
23012111Sralph 	 *              P -- "person" user's login name
23112581Sralph 	 *              I -- "indent" amount to indent output
23212111Sralph 	 *              f -- "file name" name of text file to print
23312111Sralph 	 *		l -- "file name" text file with control chars
23412111Sralph 	 *		p -- "file name" text file to print with pr(1)
23512111Sralph 	 *		t -- "file name" troff(1) file to print
23613233Sralph 	 *		n -- "file name" ditroff(1) file to print
23712111Sralph 	 *		d -- "file name" dvi file to print
23812111Sralph 	 *		g -- "file name" plot(1G) file to print
23912111Sralph 	 *		v -- "file name" plain raster file to print
24012111Sralph 	 *		c -- "file name" cifplot file to print
24112111Sralph 	 *		1 -- "R font file" for troff
24212111Sralph 	 *		2 -- "I font file" for troff
24312111Sralph 	 *		3 -- "B font file" for troff
24412111Sralph 	 *		4 -- "S font file" for troff
24512111Sralph 	 *		N -- "name" of file (used by lpq)
24612111Sralph 	 *              U -- "unlink" name of file to remove
24712111Sralph 	 *                    (after we print it. (Pass 2 only)).
24812111Sralph 	 *		M -- "mail" to user when done printing
24912111Sralph 	 *
25012111Sralph 	 *      getline reads a line and expands tabs to blanks
25112111Sralph 	 */
25212111Sralph 
25312111Sralph 	/* pass 1 */
25412111Sralph 
25512111Sralph 	while (getline(cfp))
25612111Sralph 		switch (line[0]) {
25712111Sralph 		case 'H':
25814150Sralph 			strcpy(fromhost, line+1);
25912111Sralph 			if (class[0] == '\0')
26015552Sralph 				strncpy(class, line+1, sizeof(class)-1);
26112111Sralph 			continue;
26212111Sralph 
26312111Sralph 		case 'P':
26415552Sralph 			strncpy(logname, line+1, sizeof(logname)-1);
26512463Sralph 			if (RS) {			/* restricted */
26612463Sralph 				if (getpwnam(logname) == (struct passwd *)0) {
26712463Sralph 					bombed = 2;
26815811Sralph 					sendmail(line+1, bombed);
26912463Sralph 					goto pass2;
27012463Sralph 				}
27112463Sralph 			}
27212111Sralph 			continue;
27312111Sralph 
27412111Sralph 		case 'J':
27512111Sralph 			if (line[1] != '\0')
27615552Sralph 				strncpy(jobname, line+1, sizeof(jobname)-1);
27712111Sralph 			else
27812111Sralph 				strcpy(jobname, " ");
27912111Sralph 			continue;
28012111Sralph 
28112111Sralph 		case 'C':
28212111Sralph 			if (line[1] != '\0')
28315552Sralph 				strncpy(class, line+1, sizeof(class)-1);
28412111Sralph 			else if (class[0] == '\0')
28515811Sralph 				gethostname(class, sizeof(class));
28612111Sralph 			continue;
28712111Sralph 
28812111Sralph 		case 'T':	/* header title for pr */
28915552Sralph 			strncpy(title, line+1, sizeof(title)-1);
29012111Sralph 			continue;
29112111Sralph 
29212111Sralph 		case 'L':	/* identification line */
29312111Sralph 			if (!SH)
29412111Sralph 				banner(line+1, jobname);
29512111Sralph 			continue;
29612111Sralph 
29712111Sralph 		case '1':	/* troff fonts */
29812111Sralph 		case '2':
29912111Sralph 		case '3':
30012111Sralph 		case '4':
30112111Sralph 			if (line[1] != '\0')
30212111Sralph 				strcpy(fonts[line[0]-'1'], line+1);
30312111Sralph 			continue;
30412111Sralph 
30512111Sralph 		case 'W':	/* page width */
30615552Sralph 			strncpy(width+2, line+1, sizeof(width)-3);
30712111Sralph 			continue;
30812111Sralph 
30912581Sralph 		case 'I':	/* indent amount */
31015552Sralph 			strncpy(indent+2, line+1, sizeof(indent)-3);
31112581Sralph 			continue;
31212581Sralph 
31312111Sralph 		default:	/* some file to print */
31415811Sralph 			switch (i = print(line[0], line+1)) {
31515811Sralph 			case -1:
31615811Sralph 				if (!bombed)
31715811Sralph 					bombed = 1;
31815811Sralph 				break;
31915811Sralph 			case 1:
32012111Sralph 				(void) fclose(cfp);
32112111Sralph 				return(1);
32215811Sralph 			case 2:
32315811Sralph 				bombed = 3;
32415811Sralph 				sendmail(logname, bombed);
32515811Sralph 			}
32612111Sralph 			title[0] = '\0';
32712111Sralph 			continue;
32812111Sralph 
32912111Sralph 		case 'N':
33012111Sralph 		case 'U':
33112111Sralph 		case 'M':
33212111Sralph 			continue;
33312111Sralph 		}
33412111Sralph 
33512111Sralph 	/* pass 2 */
33612111Sralph 
33712463Sralph pass2:
33812111Sralph 	fseek(cfp, 0L, 0);
33912111Sralph 	while (getline(cfp))
34012111Sralph 		switch (line[0]) {
34112111Sralph 		case 'M':
34215811Sralph 			if (bombed < 2)		/* already sent if >= 2 */
34315811Sralph 				sendmail(line+1, bombed);
34412111Sralph 			continue;
34512111Sralph 
34612111Sralph 		case 'U':
34712111Sralph 			(void) unlink(line+1);
34812111Sralph 		}
34912111Sralph 	/*
35015811Sralph 	 * clean-up in case another control file exists
35112111Sralph 	 */
35212111Sralph 	(void) fclose(cfp);
35312111Sralph 	(void) unlink(file);
35414150Sralph 	return(bombed ? -1 : 0);
35512111Sralph }
35612111Sralph 
35712111Sralph /*
35812111Sralph  * Print a file.
35913233Sralph  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
36015811Sralph  * Return -1 if a non-recoverable error occured,
36115811Sralph  * 2 if the filter detected some errors (but printed the job anyway),
36215811Sralph  * 1 if we should try to reprint this job and
36312111Sralph  * 0 if all is well.
36412111Sralph  * Note: all filters take stdin as the file, stdout as the printer,
36512111Sralph  * stderr as the log file, and must not ignore SIGINT.
36612111Sralph  */
36712111Sralph print(format, file)
36812111Sralph 	int format;
36912111Sralph 	char *file;
37012111Sralph {
37115811Sralph 	register int n;
37212111Sralph 	register char *prog;
37315811Sralph 	int fi, fo;
37412111Sralph 	char *av[15], buf[BUFSIZ];
37512111Sralph 	int pid, p[2], stopped = 0;
37612111Sralph 	union wait status;
37712111Sralph 
378*16762Sralph 	if ((fi = open(file, O_RDONLY)) < 0)
37912111Sralph 		return(-1);
38012111Sralph 	if (!SF && !tof) {		/* start on a fresh page */
38112111Sralph 		(void) write(ofd, FF, strlen(FF));
38212111Sralph 		tof = 1;
38312111Sralph 	}
38412111Sralph 	if (IF == NULL && (format == 'f' || format == 'l')) {
38512111Sralph 		tof = 0;
38612111Sralph 		while ((n = read(fi, buf, BUFSIZ)) > 0)
38712111Sralph 			if (write(ofd, buf, n) != n) {
38812111Sralph 				(void) close(fi);
38912111Sralph 				return(1);
39012111Sralph 			}
39112111Sralph 		(void) close(fi);
39212111Sralph 		return(0);
39312111Sralph 	}
39412111Sralph 	switch (format) {
39512111Sralph 	case 'p':	/* print file using 'pr' */
39612111Sralph 		if (IF == NULL) {	/* use output filter */
39712111Sralph 			prog = PR;
39812111Sralph 			av[0] = "pr";
39912111Sralph 			av[1] = width;
40012111Sralph 			av[2] = length;
40112111Sralph 			av[3] = "-h";
40212111Sralph 			av[4] = *title ? title : " ";
40312111Sralph 			av[5] = 0;
40412111Sralph 			fo = ofd;
40512111Sralph 			goto start;
40612111Sralph 		}
40712111Sralph 		pipe(p);
40812111Sralph 		if ((prchild = dofork(DORETURN)) == 0) {	/* child */
40912111Sralph 			dup2(fi, 0);		/* file is stdin */
41012111Sralph 			dup2(p[1], 1);		/* pipe is stdout */
41112111Sralph 			for (n = 3; n < NOFILE; n++)
41212111Sralph 				(void) close(n);
41312111Sralph 			execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
414*16762Sralph 			syslog(LOG_ERR, "cannot execl %s", PR);
41512111Sralph 			exit(2);
41612111Sralph 		}
41712111Sralph 		(void) close(p[1]);		/* close output side */
41812111Sralph 		(void) close(fi);
41912111Sralph 		if (prchild < 0) {
42012111Sralph 			prchild = 0;
42112111Sralph 			(void) close(p[0]);
42212111Sralph 			return(-1);
42312111Sralph 		}
42412111Sralph 		fi = p[0];			/* use pipe for input */
42512111Sralph 	case 'f':	/* print plain text file */
42612111Sralph 		prog = IF;
42712111Sralph 		av[1] = width;
42812111Sralph 		av[2] = length;
42912581Sralph 		av[3] = indent;
43012581Sralph 		n = 4;
43112111Sralph 		break;
43212111Sralph 	case 'l':	/* like 'f' but pass control characters */
43312111Sralph 		prog = IF;
43414325Sralph 		av[1] = "-c";
43512111Sralph 		av[2] = width;
43612111Sralph 		av[3] = length;
43712581Sralph 		av[4] = indent;
43812581Sralph 		n = 5;
43912111Sralph 		break;
44012463Sralph 	case 'r':	/* print a fortran text file */
44112463Sralph 		prog = RF;
44212463Sralph 		av[1] = width;
44312463Sralph 		av[2] = length;
44412463Sralph 		n = 3;
44512463Sralph 		break;
44612111Sralph 	case 't':	/* print troff output */
44713233Sralph 	case 'n':	/* print ditroff output */
44812463Sralph 	case 'd':	/* print tex output */
44912111Sralph 		(void) unlink(".railmag");
45012463Sralph 		if ((fo = creat(".railmag", FILMOD)) < 0) {
451*16762Sralph 			syslog(LOG_ERR, "%s: cannot create .railmag", printer);
45212111Sralph 			(void) unlink(".railmag");
45312111Sralph 		} else {
45412111Sralph 			for (n = 0; n < 4; n++) {
45512111Sralph 				if (fonts[n][0] != '/')
45612111Sralph 					(void) write(fo, "/usr/lib/vfont/", 15);
45712111Sralph 				(void) write(fo, fonts[n], strlen(fonts[n]));
45812111Sralph 				(void) write(fo, "\n", 1);
45912111Sralph 			}
46012111Sralph 			(void) close(fo);
46112111Sralph 		}
46213233Sralph 		prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
46312463Sralph 		av[1] = pxwidth;
46412463Sralph 		av[2] = pxlength;
46512463Sralph 		n = 3;
46612111Sralph 		break;
46712111Sralph 	case 'c':	/* print cifplot output */
46812111Sralph 		prog = CF;
46912463Sralph 		av[1] = pxwidth;
47012463Sralph 		av[2] = pxlength;
47112463Sralph 		n = 3;
47212111Sralph 		break;
47312111Sralph 	case 'g':	/* print plot(1G) output */
47412111Sralph 		prog = GF;
47512463Sralph 		av[1] = pxwidth;
47612463Sralph 		av[2] = pxlength;
47712463Sralph 		n = 3;
47812111Sralph 		break;
47912111Sralph 	case 'v':	/* print raster output */
48012111Sralph 		prog = VF;
48112463Sralph 		av[1] = pxwidth;
48212463Sralph 		av[2] = pxlength;
48312463Sralph 		n = 3;
48412111Sralph 		break;
48512111Sralph 	default:
48612111Sralph 		(void) close(fi);
487*16762Sralph 		syslog(LOG_ERR, "%s: illegal format character '%c'",
488*16762Sralph 			printer, format);
48912111Sralph 		return(-1);
49012111Sralph 	}
49112111Sralph 	if ((av[0] = rindex(prog, '/')) != NULL)
49212111Sralph 		av[0]++;
49312111Sralph 	else
49412111Sralph 		av[0] = prog;
49512111Sralph 	av[n++] = "-n";
49612111Sralph 	av[n++] = logname;
49712111Sralph 	av[n++] = "-h";
49814150Sralph 	av[n++] = fromhost;
49912111Sralph 	av[n++] = AF;
50012111Sralph 	av[n] = 0;
50112111Sralph 	fo = pfd;
50212111Sralph 	if (ofilter > 0) {		/* stop output filter */
50312111Sralph 		write(ofd, "\031\1", 2);
50412111Sralph 		while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
50512111Sralph 			;
50612111Sralph 		if (status.w_stopval != WSTOPPED) {
50712111Sralph 			(void) close(fi);
508*16762Sralph 			syslog(LOG_WARNING, "%s: output filter died (%d)",
509*16762Sralph 				printer, status.w_retcode);
51012111Sralph 			return(1);
51112111Sralph 		}
51212111Sralph 		stopped++;
51312111Sralph 	}
51412111Sralph start:
51512111Sralph 	if ((child = dofork(DORETURN)) == 0) {	/* child */
51612111Sralph 		dup2(fi, 0);
51712111Sralph 		dup2(fo, 1);
51815811Sralph 		n = open(tmpfile, O_WRONLY|O_CREAT, 0664);
51915811Sralph 		if (n >= 0)
52015811Sralph 			dup2(n, 2);
52112111Sralph 		for (n = 3; n < NOFILE; n++)
52212111Sralph 			(void) close(n);
52312111Sralph 		execv(prog, av);
524*16762Sralph 		syslog(LOG_ERR, "cannot execv %s", prog);
52512111Sralph 		exit(2);
52612111Sralph 	}
52712111Sralph 	(void) close(fi);
52812111Sralph 	if (child < 0)
52912111Sralph 		status.w_retcode = 100;
53012111Sralph 	else
53112111Sralph 		while ((pid = wait(&status)) > 0 && pid != child)
53212111Sralph 			;
53312111Sralph 	child = 0;
53412111Sralph 	prchild = 0;
53512111Sralph 	if (stopped) {		/* restart output filter */
53612111Sralph 		if (kill(ofilter, SIGCONT) < 0) {
537*16762Sralph 			syslog(LOG_ERR, "cannot restart output filter");
53812111Sralph 			exit(1);
53912111Sralph 		}
54012111Sralph 	}
54112111Sralph 	tof = 0;
54215811Sralph 	if (!WIFEXITED(status)) {
543*16762Sralph 		syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)",
544*16762Sralph 			printer, format, status.w_termsig);
54512111Sralph 		return(-1);
54615811Sralph 	} else if (status.w_retcode > 2) {
547*16762Sralph 		syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)",
548*16762Sralph 			printer, format, status.w_retcode);
54915811Sralph 		return(-1);
55015811Sralph 	} else if (status.w_retcode == 0)
55115811Sralph 		tof = 1;
55215811Sralph 	return(status.w_retcode);
55312111Sralph }
55412111Sralph 
55512111Sralph /*
55612111Sralph  * Send the daemon control file (cf) and any data files.
55712111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
55812111Sralph  * 0 if all is well.
55912111Sralph  */
56012111Sralph sendit(file)
56112111Sralph 	char *file;
56212111Sralph {
56312111Sralph 	register int linelen, err = 0;
56412111Sralph 	char last[132];
56512111Sralph 
56612111Sralph 	/*
56712111Sralph 	 * open control file
56812111Sralph 	 */
569*16762Sralph 	if ((cfp = fopen(file, "r")) == NULL)
57012111Sralph 		return(0);
57112111Sralph 	/*
57212111Sralph 	 *      read the control file for work to do
57312111Sralph 	 *
57412111Sralph 	 *      file format -- first character in the line is a command
57512111Sralph 	 *      rest of the line is the argument.
57612111Sralph 	 *      commands of interest are:
57712111Sralph 	 *
57812111Sralph 	 *            a-z -- "file name" name of file to print
57912111Sralph 	 *              U -- "unlink" name of file to remove
58012111Sralph 	 *                    (after we print it. (Pass 2 only)).
58112111Sralph 	 */
58212111Sralph 
58312111Sralph 	/*
58412111Sralph 	 * pass 1
58512111Sralph 	 */
58612111Sralph 	while (getline(cfp)) {
58712111Sralph 	again:
58812111Sralph 		if (line[0] >= 'a' && line[0] <= 'z') {
58912111Sralph 			strcpy(last, line);
59012111Sralph 			while (linelen = getline(cfp))
59112111Sralph 				if (strcmp(last, line))
59212111Sralph 					break;
59312111Sralph 			if ((err = sendfile('\3', last+1)) > 0) {
59412111Sralph 				(void) fclose(cfp);
59512111Sralph 				return(1);
59612111Sralph 			} else if (err)
59712111Sralph 				break;
59812111Sralph 			if (linelen)
59912111Sralph 				goto again;
60012111Sralph 			break;
60112111Sralph 		}
60212111Sralph 	}
60312111Sralph 	if (!err && sendfile('\2', file) > 0) {
60412111Sralph 		(void) fclose(cfp);
60512111Sralph 		return(1);
60612111Sralph 	}
60712111Sralph 	/*
60812111Sralph 	 * pass 2
60912111Sralph 	 */
61012111Sralph 	fseek(cfp, 0L, 0);
61112111Sralph 	while (getline(cfp))
61212111Sralph 		if (line[0] == 'U')
61312111Sralph 			(void) unlink(line+1);
61412111Sralph 	/*
61512111Sralph 	 * clean-up incase another control file exists
61612111Sralph 	 */
61712111Sralph 	(void) fclose(cfp);
61812111Sralph 	(void) unlink(file);
61912111Sralph 	return(0);
62012111Sralph }
62112111Sralph 
62212111Sralph /*
62312111Sralph  * Send a data file to the remote machine and spool it.
62412111Sralph  * Return positive if we should try resending.
62512111Sralph  */
62612111Sralph sendfile(type, file)
62712111Sralph 	char type, *file;
62812111Sralph {
62912111Sralph 	register int f, i, amt;
63012111Sralph 	struct stat stb;
63112111Sralph 	char buf[BUFSIZ];
632*16762Sralph 	int sizerr, resp;
63312111Sralph 
634*16762Sralph 	if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0)
63512111Sralph 		return(-1);
63612111Sralph 	(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
63712111Sralph 	amt = strlen(buf);
638*16762Sralph 	for (i = 0;  ; i++) {
639*16762Sralph 		if (write(pfd, buf, amt) != amt ||
640*16762Sralph 		    (resp = response()) < 0 || resp == '\1') {
641*16762Sralph 			(void) close(f);
642*16762Sralph 			return(1);
643*16762Sralph 		} else if (resp == '\0')
644*16762Sralph 			break;
645*16762Sralph 		if (i == 0)
646*16762Sralph 			status("no space on remote; waiting for queue to drain");
647*16762Sralph 		if (i == 10)
648*16762Sralph 			syslog(LOG_SALERT, "%s: can't send to %s; queue full",
649*16762Sralph 				printer, RM);
650*16762Sralph 		sleep(5 * 60);
65112692Sralph 	}
652*16762Sralph 	if (i)
653*16762Sralph 		status("sending to %s", RM);
65412111Sralph 	sizerr = 0;
65512111Sralph 	for (i = 0; i < stb.st_size; i += BUFSIZ) {
65612111Sralph 		amt = BUFSIZ;
65712111Sralph 		if (i + amt > stb.st_size)
65812111Sralph 			amt = stb.st_size - i;
65912111Sralph 		if (sizerr == 0 && read(f, buf, amt) != amt)
66012111Sralph 			sizerr = 1;
66112692Sralph 		if (write(pfd, buf, amt) != amt) {
66212692Sralph 			(void) close(f);
66312111Sralph 			return(1);
66412692Sralph 		}
66512111Sralph 	}
66612111Sralph 	(void) close(f);
66712111Sralph 	if (sizerr) {
668*16762Sralph 		syslog(LOG_INFO, "%s: %s: changed size", printer, file);
66912111Sralph 		(void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
670*16762Sralph 		i = -1;
671*16762Sralph 	} else if (write(pfd, "", 1) != 1)
672*16762Sralph 		i = 1;
673*16762Sralph 	else if (response())
674*16762Sralph 		i = 1;
675*16762Sralph 	else
676*16762Sralph 		i = 0;
677*16762Sralph 	return(i);
67812111Sralph }
67912111Sralph 
68012111Sralph /*
68112111Sralph  * Check to make sure there have been no errors and that both programs
68212111Sralph  * are in sync with eachother.
68312111Sralph  * Return non-zero if the connection was lost.
68412111Sralph  */
685*16762Sralph response()
68612111Sralph {
68712111Sralph 	char resp;
68812111Sralph 
689*16762Sralph 	if (read(pfd, &resp, 1) != 1) {
690*16762Sralph 		syslog(LOG_INFO, "%s: lost connection", printer);
691*16762Sralph 		return(-1);
69212111Sralph 	}
693*16762Sralph 	return(resp);
69412111Sralph }
69512111Sralph 
69612111Sralph /*
69712111Sralph  * Banner printing stuff
69812111Sralph  */
69912111Sralph banner(name1, name2)
70012111Sralph 	char *name1, *name2;
70112111Sralph {
70212111Sralph 	time_t tvec;
70312111Sralph 	extern char *ctime();
70412111Sralph 
70512111Sralph 	time(&tvec);
70612111Sralph 	if (!SF && !tof)
70712111Sralph 		(void) write(ofd, FF, strlen(FF));
70812111Sralph 	if (SB) {	/* short banner only */
70912111Sralph 		if (class[0]) {
71012111Sralph 			(void) write(ofd, class, strlen(class));
71112111Sralph 			(void) write(ofd, ":", 1);
71212111Sralph 		}
71312111Sralph 		(void) write(ofd, name1, strlen(name1));
71412111Sralph 		(void) write(ofd, "  Job: ", 7);
71512111Sralph 		(void) write(ofd, name2, strlen(name2));
71612111Sralph 		(void) write(ofd, "  Date: ", 8);
71712111Sralph 		(void) write(ofd, ctime(&tvec), 24);
71812111Sralph 		(void) write(ofd, "\n", 1);
71912111Sralph 	} else {	/* normal banner */
72012111Sralph 		(void) write(ofd, "\n\n\n", 3);
72112111Sralph 		scan_out(ofd, name1, '\0');
72212111Sralph 		(void) write(ofd, "\n\n", 2);
72312111Sralph 		scan_out(ofd, name2, '\0');
72412111Sralph 		if (class[0]) {
72512111Sralph 			(void) write(ofd,"\n\n\n",3);
72612111Sralph 			scan_out(ofd, class, '\0');
72712111Sralph 		}
72812111Sralph 		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
72912111Sralph 		(void) write(ofd, name2, strlen(name2));
73012111Sralph 		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
73112111Sralph 		(void) write(ofd, ctime(&tvec), 24);
73212111Sralph 		(void) write(ofd, "\n", 1);
73312111Sralph 	}
73412111Sralph 	if (!SF)
73512111Sralph 		(void) write(ofd, FF, strlen(FF));
73612111Sralph 	tof = 1;
73712111Sralph }
73812111Sralph 
739*16762Sralph char *
74012111Sralph scnline(key, p, c)
74112111Sralph 	register char key, *p;
74212111Sralph 	char c;
74312111Sralph {
74412111Sralph 	register scnwidth;
74512111Sralph 
74612111Sralph 	for (scnwidth = WIDTH; --scnwidth;) {
74712111Sralph 		key <<= 1;
74812111Sralph 		*p++ = key & 0200 ? c : BACKGND;
74912111Sralph 	}
75012111Sralph 	return (p);
75112111Sralph }
75212111Sralph 
75312111Sralph #define TRC(q)	(((q)-' ')&0177)
75412111Sralph 
75512111Sralph scan_out(scfd, scsp, dlm)
75612111Sralph 	int scfd;
75712111Sralph 	char *scsp, dlm;
75812111Sralph {
75912111Sralph 	register char *strp;
76012111Sralph 	register nchrs, j;
76112111Sralph 	char outbuf[LINELEN+1], *sp, c, cc;
76212111Sralph 	int d, scnhgt;
76312111Sralph 	extern char scnkey[][HEIGHT];	/* in lpdchar.c */
76412111Sralph 
76512111Sralph 	for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
76612111Sralph 		strp = &outbuf[0];
76712111Sralph 		sp = scsp;
76812111Sralph 		for (nchrs = 0; ; ) {
76912111Sralph 			d = dropit(c = TRC(cc = *sp++));
77012111Sralph 			if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
77112111Sralph 				for (j = WIDTH; --j;)
77212111Sralph 					*strp++ = BACKGND;
77312111Sralph 			else
77412111Sralph 				strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
77512111Sralph 			if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
77612111Sralph 				break;
77712111Sralph 			*strp++ = BACKGND;
77812111Sralph 			*strp++ = BACKGND;
77912111Sralph 		}
78012111Sralph 		while (*--strp == BACKGND && strp >= outbuf)
78112111Sralph 			;
78212111Sralph 		strp++;
78312111Sralph 		*strp++ = '\n';
78412111Sralph 		(void) write(scfd, outbuf, strp-outbuf);
78512111Sralph 	}
78612111Sralph }
78712111Sralph 
78812111Sralph dropit(c)
78912111Sralph 	char c;
79012111Sralph {
79112111Sralph 	switch(c) {
79212111Sralph 
79312111Sralph 	case TRC('_'):
79412111Sralph 	case TRC(';'):
79512111Sralph 	case TRC(','):
79612111Sralph 	case TRC('g'):
79712111Sralph 	case TRC('j'):
79812111Sralph 	case TRC('p'):
79912111Sralph 	case TRC('q'):
80012111Sralph 	case TRC('y'):
80112111Sralph 		return (DROP);
80212111Sralph 
80312111Sralph 	default:
80412111Sralph 		return (0);
80512111Sralph 	}
80612111Sralph }
80712111Sralph 
80812111Sralph /*
80912111Sralph  * sendmail ---
81012111Sralph  *   tell people about job completion
81112111Sralph  */
81215811Sralph sendmail(user, bombed)
81315811Sralph 	char *user;
81412111Sralph 	int bombed;
81512111Sralph {
81612111Sralph 	register int i;
81715811Sralph 	int p[2], s;
81812111Sralph 	register char *cp;
81912111Sralph 	char buf[100];
82015811Sralph 	struct stat stb;
82115811Sralph 	FILE *fp;
82212111Sralph 
82312111Sralph 	pipe(p);
82415811Sralph 	if ((s = dofork(DORETURN)) == 0) {		/* child */
82512111Sralph 		dup2(p[0], 0);
82612111Sralph 		for (i = 3; i < NOFILE; i++)
82712111Sralph 			(void) close(i);
82812111Sralph 		if ((cp = rindex(MAIL, '/')) != NULL)
82912111Sralph 			cp++;
83012111Sralph 		else
83112111Sralph 			cp = MAIL;
83215811Sralph 		sprintf(buf, "%s@%s", user, fromhost);
83312111Sralph 		execl(MAIL, cp, buf, 0);
83412111Sralph 		exit(0);
83515811Sralph 	} else if (s > 0) {				/* parent */
83612111Sralph 		dup2(p[1], 1);
83715811Sralph 		printf("To: %s@%s\n", user, fromhost);
83812111Sralph 		printf("Subject: printer job\n\n");
83912111Sralph 		printf("Your printer job ");
84012111Sralph 		if (*jobname)
84112111Sralph 			printf("(%s) ", jobname);
84212463Sralph 		switch (bombed) {
84312463Sralph 		case 0:
84412463Sralph 			printf("\ncompleted successfully\n");
84512463Sralph 			break;
84612463Sralph 		default:
84712463Sralph 		case 1:
84812463Sralph 			printf("\ncould not be printed\n");
84912463Sralph 			break;
85012463Sralph 		case 2:
85112463Sralph 			printf("\ncould not be printed without an account on %s\n", host);
85212463Sralph 			break;
85315811Sralph 		case 3:
85415811Sralph 			if (stat(tmpfile, &stb) < 0 || stb.st_size == 0 ||
85515811Sralph 			    (fp = fopen(tmpfile, "r")) == NULL) {
85615811Sralph 				printf("\nwas printed but had some errors\n");
85715811Sralph 				break;
85815811Sralph 			}
85915811Sralph 			printf("\nwas printed but had the following errors:\n");
86015811Sralph 			while ((i = getc(fp)) != EOF)
86115811Sralph 				putchar(i);
86215811Sralph 			(void) fclose(fp);
86312463Sralph 		}
86412111Sralph 		fflush(stdout);
86512111Sralph 		(void) close(1);
86612111Sralph 	}
86712111Sralph 	(void) close(p[0]);
86812111Sralph 	(void) close(p[1]);
86915811Sralph 	wait(&s);
87012111Sralph }
87112111Sralph 
87212111Sralph /*
87312111Sralph  * dofork - fork with retries on failure
87412111Sralph  */
87512111Sralph dofork(action)
87612111Sralph 	int action;
87712111Sralph {
87812111Sralph 	register int i, pid;
87912111Sralph 
88012111Sralph 	for (i = 0; i < 20; i++) {
88112463Sralph 		if ((pid = fork()) < 0) {
88212111Sralph 			sleep((unsigned)(i*i));
88312463Sralph 			continue;
88412463Sralph 		}
88512463Sralph 		/*
88612463Sralph 		 * Child should run as daemon instead of root
88712463Sralph 		 */
88812463Sralph 		if (pid == 0)
88912463Sralph 			setuid(DU);
89012463Sralph 		return(pid);
89112111Sralph 	}
892*16762Sralph 	syslog(LOG_ERR, "can't fork");
89312111Sralph 
89412111Sralph 	switch (action) {
89512111Sralph 	case DORETURN:
89612111Sralph 		return (-1);
89712111Sralph 	default:
898*16762Sralph 		syslog(LOG_ERR, "bad action (%d) to dofork", action);
89912111Sralph 		/*FALL THRU*/
90012111Sralph 	case DOABORT:
90112111Sralph 		exit(1);
90212111Sralph 	}
90312111Sralph 	/*NOTREACHED*/
90412111Sralph }
90512111Sralph 
90612111Sralph /*
907*16762Sralph  * Kill child processes to abort current job.
90812111Sralph  */
909*16762Sralph abortpr()
91012111Sralph {
91115811Sralph 	(void) unlink(tmpfile);
91212111Sralph 	kill(0, SIGINT);
91312111Sralph 	if (ofilter > 0)
91412111Sralph 		kill(ofilter, SIGCONT);
91512111Sralph 	while (wait(0) > 0)
91612111Sralph 		;
91712111Sralph 	exit(0);
91812111Sralph }
91912111Sralph 
92012111Sralph init()
92112111Sralph {
92212111Sralph 	int status;
92312111Sralph 
92413169Sralph 	if ((status = pgetent(line, printer)) < 0)
92513169Sralph 		fatal("can't open printer description file");
92613169Sralph 	else if (status == 0)
92713169Sralph 		fatal("unknown printer");
92812111Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
92912111Sralph 		LP = DEFDEVLP;
93012111Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
93112463Sralph 		RP = DEFLP;
93212111Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
93312111Sralph 		LO = DEFLOCK;
93412111Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
93512111Sralph 		ST = DEFSTAT;
93612111Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
93712111Sralph 		LF = DEFLOGF;
93812111Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
93912111Sralph 		SD = DEFSPOOL;
94012111Sralph 	if ((DU = pgetnum("du")) < 0)
94112111Sralph 		DU = DEFUID;
94212111Sralph 	if ((FF = pgetstr("ff", &bp)) == NULL)
94312111Sralph 		FF = DEFFF;
94412111Sralph 	if ((PW = pgetnum("pw")) < 0)
94512111Sralph 		PW = DEFWIDTH;
94612111Sralph 	sprintf(&width[2], "%d", PW);
94712111Sralph 	if ((PL = pgetnum("pl")) < 0)
94812111Sralph 		PL = DEFLENGTH;
94912111Sralph 	sprintf(&length[2], "%d", PL);
95012463Sralph 	if ((PX = pgetnum("px")) < 0)
95112463Sralph 		PX = 0;
95212463Sralph 	sprintf(&pxwidth[2], "%d", PX);
95312463Sralph 	if ((PY = pgetnum("py")) < 0)
95412463Sralph 		PY = 0;
95512463Sralph 	sprintf(&pxlength[2], "%d", PY);
95612111Sralph 	RM = pgetstr("rm", &bp);
95712111Sralph 	AF = pgetstr("af", &bp);
95812111Sralph 	OF = pgetstr("of", &bp);
95912111Sralph 	IF = pgetstr("if", &bp);
96012463Sralph 	RF = pgetstr("rf", &bp);
96112111Sralph 	TF = pgetstr("tf", &bp);
96213233Sralph 	NF = pgetstr("nf", &bp);
96312111Sralph 	DF = pgetstr("df", &bp);
96412111Sralph 	GF = pgetstr("gf", &bp);
96512111Sralph 	VF = pgetstr("vf", &bp);
96612111Sralph 	CF = pgetstr("cf", &bp);
96712111Sralph 	TR = pgetstr("tr", &bp);
96812463Sralph 	RS = pgetflag("rs");
96912111Sralph 	SF = pgetflag("sf");
97012111Sralph 	SH = pgetflag("sh");
97112111Sralph 	SB = pgetflag("sb");
97212111Sralph 	RW = pgetflag("rw");
97312111Sralph 	BR = pgetnum("br");
97412111Sralph 	if ((FC = pgetnum("fc")) < 0)
97512111Sralph 		FC = 0;
97612111Sralph 	if ((FS = pgetnum("fs")) < 0)
97712111Sralph 		FS = 0;
97812111Sralph 	if ((XC = pgetnum("xc")) < 0)
97912111Sralph 		XC = 0;
98012111Sralph 	if ((XS = pgetnum("xs")) < 0)
98112111Sralph 		XS = 0;
98212581Sralph 	tof = !pgetflag("fo");
98312111Sralph }
98412111Sralph 
98512463Sralph /*
98612463Sralph  * Acquire line printer or remote connection.
98712463Sralph  */
98812463Sralph openpr()
98912463Sralph {
99012463Sralph 	register int i, n;
991*16762Sralph 	int resp;
99212463Sralph 
99312463Sralph 	if (*LP) {
99412463Sralph 		for (i = 1; ; i = i < 32 ? i << 1 : i) {
99513148Ssam 			pfd = open(LP, RW ? O_RDWR : O_WRONLY);
99612463Sralph 			if (pfd >= 0)
99712463Sralph 				break;
99812463Sralph 			if (errno == ENOENT) {
999*16762Sralph 				syslog(LOG_ERR, "%s: %m", LP);
100012463Sralph 				exit(1);
100112463Sralph 			}
100212463Sralph 			if (i == 1)
100312463Sralph 				status("waiting for %s to become ready (offline ?)", printer);
100412463Sralph 			sleep(i);
100512463Sralph 		}
100612463Sralph 		if (isatty(pfd))
100712463Sralph 			setty();
100812463Sralph 		status("%s is ready and printing", printer);
100912463Sralph 	} else if (RM != NULL) {
1010*16762Sralph 		for (i = 1; ; i = i < 256 ? i << 1 : i) {
1011*16762Sralph 			resp = -1;
101212528Sralph 			pfd = getport(RM);
101312463Sralph 			if (pfd >= 0) {
101412463Sralph 				(void) sprintf(line, "\2%s\n", RP);
101512463Sralph 				n = strlen(line);
1016*16762Sralph 				if (write(pfd, line, n) == n &&
1017*16762Sralph 				    (resp = response()) == '\0')
101812463Sralph 					break;
101916031Sralph 				(void) close(pfd);
102012463Sralph 			}
102116031Sralph 			if (i == 1) {
1022*16762Sralph 				if (resp < 0)
102316031Sralph 					status("waiting for %s to come up", RM);
1024*16762Sralph 				else {
102516031Sralph 					status("waiting for queue to be enabled on %s", RM);
1026*16762Sralph 					i = 256;
1027*16762Sralph 				}
102816031Sralph 			}
102912463Sralph 			sleep(i);
103012463Sralph 		}
103112463Sralph 		status("sending to %s", RM);
103212463Sralph 		remote = 1;
103312463Sralph 	} else {
1034*16762Sralph 		syslog(LOG_ERR, "%s: no line printer device or host name",
1035*16762Sralph 			printer);
103612463Sralph 		exit(1);
103712463Sralph 	}
103812463Sralph 	/*
103912463Sralph 	 * Start up an output filter, if needed.
104012463Sralph 	 */
104112463Sralph 	if (OF) {
104212463Sralph 		int p[2];
104312463Sralph 		char *cp;
104412463Sralph 
104512463Sralph 		pipe(p);
104612463Sralph 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
104712463Sralph 			dup2(p[0], 0);		/* pipe is std in */
104812463Sralph 			dup2(pfd, 1);		/* printer is std out */
104912463Sralph 			for (i = 3; i < NOFILE; i++)
105012463Sralph 				(void) close(i);
105112463Sralph 			if ((cp = rindex(OF, '/')) == NULL)
105212463Sralph 				cp = OF;
105312463Sralph 			else
105412463Sralph 				cp++;
105512463Sralph 			execl(OF, cp, width, length, 0);
1056*16762Sralph 			syslog(LOG_ERR, "%s: %s: %m", printer, OF);
105712463Sralph 			exit(1);
105812463Sralph 		}
105912463Sralph 		(void) close(p[0]);		/* close input side */
106012463Sralph 		ofd = p[1];			/* use pipe for output */
106112463Sralph 	} else {
106212463Sralph 		ofd = pfd;
106312463Sralph 		ofilter = 0;
106412463Sralph 	}
106512463Sralph }
106612463Sralph 
106712111Sralph struct bauds {
106812111Sralph 	int	baud;
106912111Sralph 	int	speed;
107012111Sralph } bauds[] = {
107112111Sralph 	50,	B50,
107212111Sralph 	75,	B75,
107312111Sralph 	110,	B110,
107412111Sralph 	134,	B134,
107512111Sralph 	150,	B150,
107612111Sralph 	200,	B200,
107712111Sralph 	300,	B300,
107812111Sralph 	600,	B600,
107912111Sralph 	1200,	B1200,
108012111Sralph 	1800,	B1800,
108112111Sralph 	2400,	B2400,
108212111Sralph 	4800,	B4800,
108312111Sralph 	9600,	B9600,
108412111Sralph 	19200,	EXTA,
108512111Sralph 	38400,	EXTB,
108612111Sralph 	0,	0
108712111Sralph };
108812111Sralph 
108912111Sralph /*
109012111Sralph  * setup tty lines.
109112111Sralph  */
109212111Sralph setty()
109312111Sralph {
109412111Sralph 	struct sgttyb ttybuf;
109512111Sralph 	register struct bauds *bp;
109612111Sralph 
109712111Sralph 	if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
1098*16762Sralph 		syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer);
109912111Sralph 		exit(1);
110012111Sralph 	}
110112111Sralph 	if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
1102*16762Sralph 		syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer);
110312111Sralph 		exit(1);
110412111Sralph 	}
110512111Sralph 	if (BR > 0) {
110612111Sralph 		for (bp = bauds; bp->baud; bp++)
110712111Sralph 			if (BR == bp->baud)
110812111Sralph 				break;
110912111Sralph 		if (!bp->baud) {
1110*16762Sralph 			syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR);
111112111Sralph 			exit(1);
111212111Sralph 		}
111312111Sralph 		ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
111412111Sralph 	}
111513169Sralph 	ttybuf.sg_flags &= ~FC;
111613169Sralph 	ttybuf.sg_flags |= FS;
111712111Sralph 	if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
1118*16762Sralph 		syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer);
111912111Sralph 		exit(1);
112012111Sralph 	}
112112111Sralph 	if (XC) {
112212111Sralph 		if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
1123*16762Sralph 			syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer);
112412111Sralph 			exit(1);
112512111Sralph 		}
112612111Sralph 	}
112712111Sralph 	if (XS) {
112812111Sralph 		if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
1129*16762Sralph 			syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer);
113012111Sralph 			exit(1);
113112111Sralph 		}
113212111Sralph 	}
113312111Sralph }
113412463Sralph 
113512463Sralph /*VARARGS1*/
113612463Sralph status(msg, a1, a2, a3)
113712463Sralph 	char *msg;
113812463Sralph {
113912463Sralph 	register int fd;
114012463Sralph 	char buf[BUFSIZ];
114112463Sralph 
114212463Sralph 	umask(0);
114313148Ssam 	fd = open(ST, O_WRONLY|O_CREAT, 0664);
1144*16762Sralph 	if (fd < 0 || flock(fd, LOCK_EX) < 0) {
1145*16762Sralph 		syslog(LOG_ERR, "%s: %s: %m", printer, ST);
1146*16762Sralph 		exit(1);
1147*16762Sralph 	}
114813148Ssam 	ftruncate(fd, 0);
114912463Sralph 	sprintf(buf, msg, a1, a2, a3);
115012463Sralph 	strcat(buf, "\n");
115112463Sralph 	(void) write(fd, buf, strlen(buf));
115212463Sralph 	(void) close(fd);
115312463Sralph }
1154