xref: /csrg-svn/usr.sbin/lpr/lpd/printjob.c (revision 13442)
1*13442Sralph /*	printjob.c	4.10	83/06/29	*/
212111Sralph /*
312111Sralph  * printjob -- print jobs in the queue.
412111Sralph  *
512111Sralph  *	NOTE: the lock file is used to pass information to lpq and lprm.
612111Sralph  *	it does not need to be removed because file locks are dynamic.
712111Sralph  */
812111Sralph 
912111Sralph #include "lp.h"
1012111Sralph 
1112877Sralph #define DORETURN	0		/* absorb fork error */
1212877Sralph #define DOABORT		1		/* abort if dofork fails */
1312111Sralph 
1412877Sralph static char	title[80];		/* ``pr'' title */
1512877Sralph static FILE	*cfp;			/* control file */
1612877Sralph static int	pfd;			/* printer file descriptor */
1712877Sralph static int	ofd;			/* output filter file descriptor */
1812877Sralph static int	lfd;			/* lock file descriptor */
1912877Sralph static int	pid;			/* pid of lpd process */
2012877Sralph static int	prchild;		/* id of pr process */
2112877Sralph static int	child;			/* id of any filters */
2212877Sralph static int	ofilter;		/* id of output filter, if any */
2312877Sralph static int	tof;			/* true if at top of form */
2412877Sralph static int	remote;			/* true if sending files to remote */
2512111Sralph 
2612877Sralph static char	logname[32];		/* user's login name */
2712877Sralph static char	jobname[32];		/* job or file name */
2812877Sralph static char	class[32];		/* classification field */
2912877Sralph static char	width[10] = "-w";	/* page width in characters */
3012877Sralph static char	length[10] = "-l";	/* page length in lines */
3112877Sralph static char	pxwidth[10] = "-x";	/* page width in pixels */
3212877Sralph static char	pxlength[10] = "-y";	/* page length in pixels */
3312877Sralph static char	indent[10] = "-i0";	/* indentation size in characters */
3412111Sralph 
3512111Sralph printjob()
3612111Sralph {
3712111Sralph 	struct stat stb;
3812111Sralph 	register struct queue *q, **qp;
3912111Sralph 	struct queue **queue;
4012111Sralph 	register int i, nitems;
4112111Sralph 	long pidoff;
4212111Sralph 	extern int onintr();
4312111Sralph 
4412111Sralph 	init();					/* set up capabilities */
45*13442Sralph 	(void) write(1, "", 1);			/* ack that daemon is started */
4612877Sralph 	(void) close(1);			/* set up log file */
4712877Sralph 	(void) close(2);
4813148Ssam 	if (open(LF, O_WRONLY|O_APPEND) < 0)
4913148Ssam 		(void) open("/dev/null", O_WRONLY);
5012877Sralph 	dup(1);
5112463Sralph 	pid = getpid();				/* for use with lprm */
5212111Sralph 	setpgrp(0, pid);
5313148Ssam 	signal(SIGINT, onintr);
5412111Sralph 
5512111Sralph 	/*
5612111Sralph 	 * uses short form file names
5712111Sralph 	 */
5812111Sralph 	if (chdir(SD) < 0) {
5912111Sralph 		log("cannot chdir to %s", SD);
6012111Sralph 		exit(1);
6112111Sralph 	}
6212463Sralph 	if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
6312463Sralph 		exit(0);		/* printing disabled */
6413169Sralph 	lfd = open(LO, O_WRONLY|O_CREAT|O_TRUNC, 0644);
6513169Sralph 	if (lfd < 0) {
6613169Sralph 		log("cannot create %s", LO);
6713169Sralph 		exit(1);
6813169Sralph 	}
6913169Sralph 	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
7012111Sralph 		if (errno == EWOULDBLOCK)	/* active deamon present */
7112111Sralph 			exit(0);
7213169Sralph 		log("cannot lock %s", LO);
7312111Sralph 		exit(1);
7412111Sralph 	}
7513148Ssam 	ftruncate(lfd, 0);
7612111Sralph 	/*
7712111Sralph 	 * write process id for others to know
7812111Sralph 	 */
7912111Sralph 	sprintf(line, "%u\n", pid);
8012111Sralph 	pidoff = i = strlen(line);
8112463Sralph 	if (write(lfd, line, i) != i) {
8212111Sralph 		log("cannot write daemon pid");
8312111Sralph 		exit(1);
8412111Sralph 	}
8512111Sralph 	/*
8612111Sralph 	 * search the spool directory for work and sort by queue order.
8712111Sralph 	 */
8812111Sralph 	if ((nitems = getq(&queue)) < 0) {
8912111Sralph 		log("can't scan spool directory %s", SD);
9012111Sralph 		exit(1);
9112111Sralph 	}
9212463Sralph 	if (nitems == 0)		/* no work to do */
9312111Sralph 		exit(0);
9413169Sralph 	if (stb.st_mode & 01) {		/* reset queue flag */
9513169Sralph 		if (fchmod(lfd, stb.st_mode & 0776) < 0)
9613169Sralph 			log("cannot chmod %s", LO);
9713169Sralph 	}
9812463Sralph 	openpr();			/* open printer or remote */
9912463Sralph again:
10012111Sralph 	/*
10112111Sralph 	 * we found something to do now do it --
10212111Sralph 	 *    write the name of the current control file into the lock file
10312111Sralph 	 *    so the spool queue program can tell what we're working on
10412111Sralph 	 */
10512111Sralph 	for (qp = queue; nitems--; free((char *) q)) {
10612111Sralph 		q = *qp++;
10712111Sralph 		if (stat(q->q_name, &stb) < 0)
10812111Sralph 			continue;
10912463Sralph 	restart:
11012111Sralph 		(void) lseek(lfd, pidoff, 0);
11112111Sralph 		(void) sprintf(line, "%s\n", q->q_name);
11212111Sralph 		i = strlen(line);
11312111Sralph 		if (write(lfd, line, i) != i)
11412111Sralph 			log("can't write (%d) control file name", errno);
11512111Sralph 		if (!remote)
11612111Sralph 			i = printit(q->q_name);
11712111Sralph 		else
11812111Sralph 			i = sendit(q->q_name);
11912463Sralph 		/*
12013169Sralph 		 * Check to see if we are supposed to stop printing or
12113169Sralph 		 * if we are to rebuild the queue.
12212463Sralph 		 */
12313169Sralph 		if (fstat(lfd, &stb) == 0) {
12413169Sralph 			if (stb.st_mode & 0100)
12513169Sralph 				goto done;
12613169Sralph 			if (stb.st_mode & 01) {
12713169Sralph 				for (free((char *) q); nitems--; free((char *) q))
12813169Sralph 					q = *qp++;
12913169Sralph 				if (fchmod(lfd, stb.st_mode & 0776) < 0)
13013169Sralph 					log("cannot chmod %s", LO);
13113169Sralph 				break;
13213169Sralph 			}
13313169Sralph 		}
13412463Sralph 		/*
13512463Sralph 		 * Check to see if we should try reprinting the job.
13612463Sralph 		 */
13712463Sralph 		if (i > 0) {
13812111Sralph 			log("restarting");
13912111Sralph 			if (ofilter > 0) {
14012111Sralph 				kill(ofilter, SIGCONT);	/* to be sure */
14112111Sralph 				(void) close(ofd);
14212111Sralph 				while ((i = wait(0)) > 0 && i != ofilter)
14312111Sralph 					;
14412111Sralph 				ofilter = 0;
14512111Sralph 			}
14612463Sralph 			(void) close(pfd);	/* close printer */
14712463Sralph 			(void) lseek(lfd, pidoff, 0);
14812463Sralph 			if (write(lfd, "\n", 1) != 1)
14912463Sralph 				log("can't write (%d) control file name", errno);
15012463Sralph 			openpr();		/* try to reopen printer */
15112111Sralph 			goto restart;
15212111Sralph 		}
15312111Sralph 	}
15412111Sralph 	free((char *) queue);
15512463Sralph 	/*
15612463Sralph 	 * search the spool directory for more work.
15712463Sralph 	 */
15812463Sralph 	if ((nitems = getq(&queue)) < 0) {
15912463Sralph 		log("can't scan spool directory %s", SD);
16012463Sralph 		exit(1);
16112463Sralph 	}
16212463Sralph 	if (nitems == 0) {		/* no more work to do */
16312463Sralph 	done:
16412463Sralph 		if (!SF && !tof)
16512463Sralph 			(void) write(ofd, FF, strlen(FF));
16612463Sralph 		if (TR != NULL)		/* output trailer */
16712463Sralph 			(void) write(ofd, TR, strlen(TR));
16812463Sralph 		exit(0);
16912463Sralph 	}
17012111Sralph 	goto again;
17112111Sralph }
17212111Sralph 
17312111Sralph char	fonts[4][50];	/* fonts for troff */
17412111Sralph 
17512111Sralph static char ifonts[4][18] = {
17612111Sralph 	"/usr/lib/vfont/R",
17712111Sralph 	"/usr/lib/vfont/I",
17812111Sralph 	"/usr/lib/vfont/B",
17912111Sralph 	"/usr/lib/vfont/S"
18012111Sralph };
18112111Sralph 
18212111Sralph /*
18312111Sralph  * The remaining part is the reading of the control file (cf)
18412111Sralph  * and performing the various actions.
18512111Sralph  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
18612111Sralph  * -1 if a non-recoverable error occured.
18712111Sralph  */
18812877Sralph static
18912111Sralph printit(file)
19012111Sralph 	char *file;
19112111Sralph {
19212111Sralph 	register int i;
19312111Sralph 	int bombed = 0;
19412111Sralph 
19512111Sralph 	/*
19612111Sralph 	 * open control file
19712111Sralph 	 */
19812111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
19912111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
20012111Sralph 		return(0);
20112111Sralph 	}
20212111Sralph 	/*
20312111Sralph 	 * Reset troff fonts.
20412111Sralph 	 */
20512111Sralph 	for (i = 0; i < 4; i++)
20612111Sralph 		strcpy(fonts[i], ifonts[i]);
20712111Sralph 
20812111Sralph 	/*
20912111Sralph 	 *      read the control file for work to do
21012111Sralph 	 *
21112111Sralph 	 *      file format -- first character in the line is a command
21212111Sralph 	 *      rest of the line is the argument.
21312111Sralph 	 *      valid commands are:
21412111Sralph 	 *
21512111Sralph 	 *		J -- "job name" on banner page
21612111Sralph 	 *		C -- "class name" on banner page
21712111Sralph 	 *              L -- "literal" user's name to print on banner
21812111Sralph 	 *		T -- "title" for pr
21912111Sralph 	 *		H -- "host name" of machine where lpr was done
22012111Sralph 	 *              P -- "person" user's login name
22112581Sralph 	 *              I -- "indent" amount to indent output
22212111Sralph 	 *              f -- "file name" name of text file to print
22312111Sralph 	 *		l -- "file name" text file with control chars
22412111Sralph 	 *		p -- "file name" text file to print with pr(1)
22512111Sralph 	 *		t -- "file name" troff(1) file to print
22613233Sralph 	 *		n -- "file name" ditroff(1) file to print
22712111Sralph 	 *		d -- "file name" dvi file to print
22812111Sralph 	 *		g -- "file name" plot(1G) file to print
22912111Sralph 	 *		v -- "file name" plain raster file to print
23012111Sralph 	 *		c -- "file name" cifplot file to print
23112111Sralph 	 *		1 -- "R font file" for troff
23212111Sralph 	 *		2 -- "I font file" for troff
23312111Sralph 	 *		3 -- "B font file" for troff
23412111Sralph 	 *		4 -- "S font file" for troff
23512111Sralph 	 *		N -- "name" of file (used by lpq)
23612111Sralph 	 *              U -- "unlink" name of file to remove
23712111Sralph 	 *                    (after we print it. (Pass 2 only)).
23812111Sralph 	 *		M -- "mail" to user when done printing
23912111Sralph 	 *
24012111Sralph 	 *      getline reads a line and expands tabs to blanks
24112111Sralph 	 */
24212111Sralph 
24312111Sralph 	/* pass 1 */
24412111Sralph 
24512111Sralph 	while (getline(cfp))
24612111Sralph 		switch (line[0]) {
24712111Sralph 		case 'H':
24812111Sralph 			strcpy(host, line+1);
24912111Sralph 			if (class[0] == '\0')
25012111Sralph 				strcpy(class, line+1);
25112111Sralph 			continue;
25212111Sralph 
25312111Sralph 		case 'P':
25412111Sralph 			strcpy(logname, line+1);
25512463Sralph 			if (RS) {			/* restricted */
25612463Sralph 				if (getpwnam(logname) == (struct passwd *)0) {
25712463Sralph 					bombed = 2;
25812463Sralph 					sendmail(bombed);
25912463Sralph 					goto pass2;
26012463Sralph 				}
26112463Sralph 			}
26212111Sralph 			continue;
26312111Sralph 
26412111Sralph 		case 'J':
26512111Sralph 			if (line[1] != '\0')
26612111Sralph 				strcpy(jobname, line+1);
26712111Sralph 			else
26812111Sralph 				strcpy(jobname, " ");
26912111Sralph 			continue;
27012111Sralph 
27112111Sralph 		case 'C':
27212111Sralph 			if (line[1] != '\0')
27312111Sralph 				strcpy(class, line+1);
27412111Sralph 			else if (class[0] == '\0')
27512111Sralph 				gethostname(class, sizeof (class));
27612111Sralph 			continue;
27712111Sralph 
27812111Sralph 		case 'T':	/* header title for pr */
27912111Sralph 			strcpy(title, line+1);
28012111Sralph 			continue;
28112111Sralph 
28212111Sralph 		case 'L':	/* identification line */
28312111Sralph 			if (!SH)
28412111Sralph 				banner(line+1, jobname);
28512111Sralph 			continue;
28612111Sralph 
28712111Sralph 		case '1':	/* troff fonts */
28812111Sralph 		case '2':
28912111Sralph 		case '3':
29012111Sralph 		case '4':
29112111Sralph 			if (line[1] != '\0')
29212111Sralph 				strcpy(fonts[line[0]-'1'], line+1);
29312111Sralph 			continue;
29412111Sralph 
29512111Sralph 		case 'W':	/* page width */
29612111Sralph 			strcpy(width+2, line+1);
29712111Sralph 			continue;
29812111Sralph 
29912581Sralph 		case 'I':	/* indent amount */
30012581Sralph 			strcpy(indent+2, line+1);
30112581Sralph 			continue;
30212581Sralph 
30312111Sralph 		default:	/* some file to print */
30412111Sralph 			if ((i = print(line[0], line+1)) > 0) {
30512111Sralph 				(void) fclose(cfp);
30612111Sralph 				return(1);
30712111Sralph 			} else if (i < 0)
30812111Sralph 				bombed = 1;
30912111Sralph 			title[0] = '\0';
31012111Sralph 			continue;
31112111Sralph 
31212111Sralph 		case 'N':
31312111Sralph 		case 'U':
31412111Sralph 		case 'M':
31512111Sralph 			continue;
31612111Sralph 		}
31712111Sralph 
31812111Sralph 	/* pass 2 */
31912111Sralph 
32012463Sralph pass2:
32112111Sralph 	fseek(cfp, 0L, 0);
32212111Sralph 	while (getline(cfp))
32312111Sralph 		switch (line[0]) {
32412111Sralph 		case 'M':
32512463Sralph 			if (bombed != 2)		/* already sent if 2 */
32612463Sralph 				sendmail(bombed);
32712111Sralph 			continue;
32812111Sralph 
32912111Sralph 		case 'U':
33012111Sralph 			(void) unlink(line+1);
33112111Sralph 		}
33212111Sralph 	/*
33312111Sralph 	 * clean-up incase another control file exists
33412111Sralph 	 */
33512111Sralph 	(void) fclose(cfp);
33612111Sralph 	(void) unlink(file);
33712111Sralph 	return(0);
33812111Sralph }
33912111Sralph 
34012111Sralph /*
34112111Sralph  * Print a file.
34213233Sralph  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
34312111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
34412111Sralph  * 0 if all is well.
34512111Sralph  * Note: all filters take stdin as the file, stdout as the printer,
34612111Sralph  * stderr as the log file, and must not ignore SIGINT.
34712111Sralph  */
34812877Sralph static
34912111Sralph print(format, file)
35012111Sralph 	int format;
35112111Sralph 	char *file;
35212111Sralph {
35312111Sralph 	register int n, fi, fo;
35412111Sralph 	register char *prog;
35512111Sralph 	char *av[15], buf[BUFSIZ];
35612111Sralph 	int pid, p[2], stopped = 0;
35712111Sralph 	union wait status;
35812111Sralph 
35913148Ssam 	if ((fi = open(file, O_RDONLY)) < 0) {
36012111Sralph 		log("%s: open failure <errno = %d>", file, errno);
36112111Sralph 		return(-1);
36212111Sralph 	}
36312111Sralph 	if (!SF && !tof) {		/* start on a fresh page */
36412111Sralph 		(void) write(ofd, FF, strlen(FF));
36512111Sralph 		tof = 1;
36612111Sralph 	}
36712111Sralph 	if (IF == NULL && (format == 'f' || format == 'l')) {
36812111Sralph 		tof = 0;
36912111Sralph 		while ((n = read(fi, buf, BUFSIZ)) > 0)
37012111Sralph 			if (write(ofd, buf, n) != n) {
37112111Sralph 				(void) close(fi);
37212111Sralph 				return(1);
37312111Sralph 			}
37412111Sralph 		(void) close(fi);
37512111Sralph 		return(0);
37612111Sralph 	}
37712111Sralph 	switch (format) {
37812111Sralph 	case 'p':	/* print file using 'pr' */
37912111Sralph 		if (IF == NULL) {	/* use output filter */
38012111Sralph 			prog = PR;
38112111Sralph 			av[0] = "pr";
38212111Sralph 			av[1] = width;
38312111Sralph 			av[2] = length;
38412111Sralph 			av[3] = "-h";
38512111Sralph 			av[4] = *title ? title : " ";
38612111Sralph 			av[5] = 0;
38712111Sralph 			fo = ofd;
38812111Sralph 			goto start;
38912111Sralph 		}
39012111Sralph 		pipe(p);
39112111Sralph 		if ((prchild = dofork(DORETURN)) == 0) {	/* child */
39212111Sralph 			dup2(fi, 0);		/* file is stdin */
39312111Sralph 			dup2(p[1], 1);		/* pipe is stdout */
39412111Sralph 			for (n = 3; n < NOFILE; n++)
39512111Sralph 				(void) close(n);
39612111Sralph 			execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
39712111Sralph 			log("cannot execl %s", PR);
39812111Sralph 			exit(2);
39912111Sralph 		}
40012111Sralph 		(void) close(p[1]);		/* close output side */
40112111Sralph 		(void) close(fi);
40212111Sralph 		if (prchild < 0) {
40312111Sralph 			prchild = 0;
40412111Sralph 			(void) close(p[0]);
40512111Sralph 			return(-1);
40612111Sralph 		}
40712111Sralph 		fi = p[0];			/* use pipe for input */
40812111Sralph 	case 'f':	/* print plain text file */
40912111Sralph 		prog = IF;
41012111Sralph 		av[1] = width;
41112111Sralph 		av[2] = length;
41212581Sralph 		av[3] = indent;
41312581Sralph 		n = 4;
41412111Sralph 		break;
41512111Sralph 	case 'l':	/* like 'f' but pass control characters */
41612111Sralph 		prog = IF;
41712111Sralph 		av[1] = "-l";
41812111Sralph 		av[2] = width;
41912111Sralph 		av[3] = length;
42012581Sralph 		av[4] = indent;
42112581Sralph 		n = 5;
42212111Sralph 		break;
42312463Sralph 	case 'r':	/* print a fortran text file */
42412463Sralph 		prog = RF;
42512463Sralph 		av[1] = width;
42612463Sralph 		av[2] = length;
42712463Sralph 		n = 3;
42812463Sralph 		break;
42912111Sralph 	case 't':	/* print troff output */
43013233Sralph 	case 'n':	/* print ditroff output */
43112463Sralph 	case 'd':	/* print tex output */
43212111Sralph 		(void) unlink(".railmag");
43312463Sralph 		if ((fo = creat(".railmag", FILMOD)) < 0) {
43412111Sralph 			log("cannot create .railmag");
43512111Sralph 			(void) unlink(".railmag");
43612111Sralph 		} else {
43712111Sralph 			for (n = 0; n < 4; n++) {
43812111Sralph 				if (fonts[n][0] != '/')
43912111Sralph 					(void) write(fo, "/usr/lib/vfont/", 15);
44012111Sralph 				(void) write(fo, fonts[n], strlen(fonts[n]));
44112111Sralph 				(void) write(fo, "\n", 1);
44212111Sralph 			}
44312111Sralph 			(void) close(fo);
44412111Sralph 		}
44513233Sralph 		prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
44612463Sralph 		av[1] = pxwidth;
44712463Sralph 		av[2] = pxlength;
44812463Sralph 		n = 3;
44912111Sralph 		break;
45012111Sralph 	case 'c':	/* print cifplot output */
45112111Sralph 		prog = CF;
45212463Sralph 		av[1] = pxwidth;
45312463Sralph 		av[2] = pxlength;
45412463Sralph 		n = 3;
45512111Sralph 		break;
45612111Sralph 	case 'g':	/* print plot(1G) output */
45712111Sralph 		prog = GF;
45812463Sralph 		av[1] = pxwidth;
45912463Sralph 		av[2] = pxlength;
46012463Sralph 		n = 3;
46112111Sralph 		break;
46212111Sralph 	case 'v':	/* print raster output */
46312111Sralph 		prog = VF;
46412463Sralph 		av[1] = pxwidth;
46512463Sralph 		av[2] = pxlength;
46612463Sralph 		n = 3;
46712111Sralph 		break;
46812111Sralph 	default:
46912111Sralph 		(void) close(fi);
47012111Sralph 		log("illegal format character '%c'", format);
47112111Sralph 		return(-1);
47212111Sralph 	}
47312111Sralph 	if ((av[0] = rindex(prog, '/')) != NULL)
47412111Sralph 		av[0]++;
47512111Sralph 	else
47612111Sralph 		av[0] = prog;
47712111Sralph 	av[n++] = "-n";
47812111Sralph 	av[n++] = logname;
47912111Sralph 	av[n++] = "-h";
48012111Sralph 	av[n++] = host;
48112111Sralph 	av[n++] = AF;
48212111Sralph 	av[n] = 0;
48312111Sralph 	fo = pfd;
48412111Sralph 	if (ofilter > 0) {		/* stop output filter */
48512111Sralph 		write(ofd, "\031\1", 2);
48612111Sralph 		while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
48712111Sralph 			;
48812111Sralph 		if (status.w_stopval != WSTOPPED) {
48912111Sralph 			(void) close(fi);
49012111Sralph 			log("output filter died (%d)", status.w_retcode);
49112111Sralph 			return(1);
49212111Sralph 		}
49312111Sralph 		stopped++;
49412111Sralph 	}
49512111Sralph start:
49612111Sralph 	if ((child = dofork(DORETURN)) == 0) {	/* child */
49712111Sralph 		dup2(fi, 0);
49812111Sralph 		dup2(fo, 1);
49912111Sralph 		for (n = 3; n < NOFILE; n++)
50012111Sralph 			(void) close(n);
50112111Sralph 		execv(prog, av);
50212111Sralph 		log("cannot execl %s", prog);
50312111Sralph 		exit(2);
50412111Sralph 	}
50512111Sralph 	(void) close(fi);
50612111Sralph 	if (child < 0)
50712111Sralph 		status.w_retcode = 100;
50812111Sralph 	else
50912111Sralph 		while ((pid = wait(&status)) > 0 && pid != child)
51012111Sralph 			;
51112111Sralph 	child = 0;
51212111Sralph 	prchild = 0;
51312111Sralph 	if (stopped) {		/* restart output filter */
51412111Sralph 		if (kill(ofilter, SIGCONT) < 0) {
51512111Sralph 			log("cannot restart output filter");
51612111Sralph 			exit(1);
51712111Sralph 		}
51812111Sralph 	}
51912111Sralph 	tof = 0;
52012111Sralph 	if (!WIFEXITED(status) || status.w_retcode > 1) {
52112111Sralph 		log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode);
52212111Sralph 		return(-1);
52312111Sralph 	} else if (status.w_retcode == 1)
52412111Sralph 		return(1);
52512111Sralph 	tof = 1;
52612111Sralph 	return(0);
52712111Sralph }
52812111Sralph 
52912111Sralph /*
53012111Sralph  * Send the daemon control file (cf) and any data files.
53112111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
53212111Sralph  * 0 if all is well.
53312111Sralph  */
53412877Sralph static
53512111Sralph sendit(file)
53612111Sralph 	char *file;
53712111Sralph {
53812111Sralph 	register int linelen, err = 0;
53912111Sralph 	char last[132];
54012111Sralph 
54112111Sralph 	/*
54212111Sralph 	 * open control file
54312111Sralph 	 */
54412111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
54512111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
54612111Sralph 		return(0);
54712111Sralph 	}
54812111Sralph 	/*
54912111Sralph 	 *      read the control file for work to do
55012111Sralph 	 *
55112111Sralph 	 *      file format -- first character in the line is a command
55212111Sralph 	 *      rest of the line is the argument.
55312111Sralph 	 *      commands of interest are:
55412111Sralph 	 *
55512111Sralph 	 *            a-z -- "file name" name of file to print
55612111Sralph 	 *              U -- "unlink" name of file to remove
55712111Sralph 	 *                    (after we print it. (Pass 2 only)).
55812111Sralph 	 */
55912111Sralph 
56012111Sralph 	/*
56112111Sralph 	 * pass 1
56212111Sralph 	 */
56312111Sralph 	while (getline(cfp)) {
56412111Sralph 	again:
56512111Sralph 		if (line[0] >= 'a' && line[0] <= 'z') {
56612111Sralph 			strcpy(last, line);
56712111Sralph 			while (linelen = getline(cfp))
56812111Sralph 				if (strcmp(last, line))
56912111Sralph 					break;
57012111Sralph 			if ((err = sendfile('\3', last+1)) > 0) {
57112111Sralph 				(void) fclose(cfp);
57212111Sralph 				return(1);
57312111Sralph 			} else if (err)
57412111Sralph 				break;
57512111Sralph 			if (linelen)
57612111Sralph 				goto again;
57712111Sralph 			break;
57812111Sralph 		}
57912111Sralph 	}
58012111Sralph 	if (!err && sendfile('\2', file) > 0) {
58112111Sralph 		(void) fclose(cfp);
58212111Sralph 		return(1);
58312111Sralph 	}
58412111Sralph 	/*
58512111Sralph 	 * pass 2
58612111Sralph 	 */
58712111Sralph 	fseek(cfp, 0L, 0);
58812111Sralph 	while (getline(cfp))
58912111Sralph 		if (line[0] == 'U')
59012111Sralph 			(void) unlink(line+1);
59112111Sralph 	/*
59212111Sralph 	 * clean-up incase another control file exists
59312111Sralph 	 */
59412111Sralph 	(void) fclose(cfp);
59512111Sralph 	(void) unlink(file);
59612111Sralph 	return(0);
59712111Sralph }
59812111Sralph 
59912111Sralph /*
60012111Sralph  * Send a data file to the remote machine and spool it.
60112111Sralph  * Return positive if we should try resending.
60212111Sralph  */
60312877Sralph static
60412111Sralph sendfile(type, file)
60512111Sralph 	char type, *file;
60612111Sralph {
60712111Sralph 	register int f, i, amt;
60812111Sralph 	struct stat stb;
60912111Sralph 	char buf[BUFSIZ];
61012111Sralph 	int sizerr;
61112111Sralph 
61213148Ssam 	if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) {
61312111Sralph 		log("file (%s) open failure <errno = %d>", file, errno);
61412111Sralph 		return(-1);
61512111Sralph 	}
61612111Sralph 	(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
61712111Sralph 	amt = strlen(buf);
61812692Sralph 	if (write(pfd, buf, amt) != amt) {
61912692Sralph 		(void) close(f);
62012111Sralph 		return(1);
62112692Sralph 	}
62212692Sralph 	if (noresponse()) {
62312692Sralph 		(void) close(f);
62412111Sralph 		return(1);
62512692Sralph 	}
62612111Sralph 	sizerr = 0;
62712111Sralph 	for (i = 0; i < stb.st_size; i += BUFSIZ) {
62812111Sralph 		amt = BUFSIZ;
62912111Sralph 		if (i + amt > stb.st_size)
63012111Sralph 			amt = stb.st_size - i;
63112111Sralph 		if (sizerr == 0 && read(f, buf, amt) != amt)
63212111Sralph 			sizerr = 1;
63312692Sralph 		if (write(pfd, buf, amt) != amt) {
63412692Sralph 			(void) close(f);
63512111Sralph 			return(1);
63612692Sralph 		}
63712111Sralph 	}
63812111Sralph 	(void) close(f);
63912111Sralph 	if (sizerr) {
64012111Sralph 		log("%s: changed size", file);
64112111Sralph 		(void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
64212111Sralph 		return(-1);
64312111Sralph 	}
64412111Sralph 	if (write(pfd, "", 1) != 1)
64512111Sralph 		return(1);
64612111Sralph 	if (noresponse())
64712111Sralph 		return(1);
64812111Sralph 	return(0);
64912111Sralph }
65012111Sralph 
65112111Sralph /*
65212111Sralph  * Check to make sure there have been no errors and that both programs
65312111Sralph  * are in sync with eachother.
65412111Sralph  * Return non-zero if the connection was lost.
65512111Sralph  */
65612111Sralph static
65712111Sralph noresponse()
65812111Sralph {
65912111Sralph 	char resp;
66012111Sralph 
66112111Sralph 	if (read(pfd, &resp, 1) != 1 || resp != '\0') {
66212111Sralph 		log("lost connection or error in recvjob");
66312111Sralph 		return(1);
66412111Sralph 	}
66512111Sralph 	return(0);
66612111Sralph }
66712111Sralph 
66812111Sralph /*
66912111Sralph  * Banner printing stuff
67012111Sralph  */
67112877Sralph static
67212111Sralph banner(name1, name2)
67312111Sralph 	char *name1, *name2;
67412111Sralph {
67512111Sralph 	time_t tvec;
67612111Sralph 	extern char *ctime();
67712111Sralph 
67812111Sralph 	time(&tvec);
67912111Sralph 	if (!SF && !tof)
68012111Sralph 		(void) write(ofd, FF, strlen(FF));
68112111Sralph 	if (SB) {	/* short banner only */
68212111Sralph 		if (class[0]) {
68312111Sralph 			(void) write(ofd, class, strlen(class));
68412111Sralph 			(void) write(ofd, ":", 1);
68512111Sralph 		}
68612111Sralph 		(void) write(ofd, name1, strlen(name1));
68712111Sralph 		(void) write(ofd, "  Job: ", 7);
68812111Sralph 		(void) write(ofd, name2, strlen(name2));
68912111Sralph 		(void) write(ofd, "  Date: ", 8);
69012111Sralph 		(void) write(ofd, ctime(&tvec), 24);
69112111Sralph 		(void) write(ofd, "\n", 1);
69212111Sralph 	} else {	/* normal banner */
69312111Sralph 		(void) write(ofd, "\n\n\n", 3);
69412111Sralph 		scan_out(ofd, name1, '\0');
69512111Sralph 		(void) write(ofd, "\n\n", 2);
69612111Sralph 		scan_out(ofd, name2, '\0');
69712111Sralph 		if (class[0]) {
69812111Sralph 			(void) write(ofd,"\n\n\n",3);
69912111Sralph 			scan_out(ofd, class, '\0');
70012111Sralph 		}
70112111Sralph 		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
70212111Sralph 		(void) write(ofd, name2, strlen(name2));
70312111Sralph 		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
70412111Sralph 		(void) write(ofd, ctime(&tvec), 24);
70512111Sralph 		(void) write(ofd, "\n", 1);
70612111Sralph 	}
70712111Sralph 	if (!SF)
70812111Sralph 		(void) write(ofd, FF, strlen(FF));
70912111Sralph 	tof = 1;
71012111Sralph }
71112111Sralph 
71212877Sralph static char *
71312111Sralph scnline(key, p, c)
71412111Sralph 	register char key, *p;
71512111Sralph 	char c;
71612111Sralph {
71712111Sralph 	register scnwidth;
71812111Sralph 
71912111Sralph 	for (scnwidth = WIDTH; --scnwidth;) {
72012111Sralph 		key <<= 1;
72112111Sralph 		*p++ = key & 0200 ? c : BACKGND;
72212111Sralph 	}
72312111Sralph 	return (p);
72412111Sralph }
72512111Sralph 
72612111Sralph #define TRC(q)	(((q)-' ')&0177)
72712111Sralph 
72812877Sralph static
72912111Sralph scan_out(scfd, scsp, dlm)
73012111Sralph 	int scfd;
73112111Sralph 	char *scsp, dlm;
73212111Sralph {
73312111Sralph 	register char *strp;
73412111Sralph 	register nchrs, j;
73512111Sralph 	char outbuf[LINELEN+1], *sp, c, cc;
73612111Sralph 	int d, scnhgt;
73712111Sralph 	extern char scnkey[][HEIGHT];	/* in lpdchar.c */
73812111Sralph 
73912111Sralph 	for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
74012111Sralph 		strp = &outbuf[0];
74112111Sralph 		sp = scsp;
74212111Sralph 		for (nchrs = 0; ; ) {
74312111Sralph 			d = dropit(c = TRC(cc = *sp++));
74412111Sralph 			if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
74512111Sralph 				for (j = WIDTH; --j;)
74612111Sralph 					*strp++ = BACKGND;
74712111Sralph 			else
74812111Sralph 				strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
74912111Sralph 			if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
75012111Sralph 				break;
75112111Sralph 			*strp++ = BACKGND;
75212111Sralph 			*strp++ = BACKGND;
75312111Sralph 		}
75412111Sralph 		while (*--strp == BACKGND && strp >= outbuf)
75512111Sralph 			;
75612111Sralph 		strp++;
75712111Sralph 		*strp++ = '\n';
75812111Sralph 		(void) write(scfd, outbuf, strp-outbuf);
75912111Sralph 	}
76012111Sralph }
76112111Sralph 
76212877Sralph static
76312111Sralph dropit(c)
76412111Sralph 	char c;
76512111Sralph {
76612111Sralph 	switch(c) {
76712111Sralph 
76812111Sralph 	case TRC('_'):
76912111Sralph 	case TRC(';'):
77012111Sralph 	case TRC(','):
77112111Sralph 	case TRC('g'):
77212111Sralph 	case TRC('j'):
77312111Sralph 	case TRC('p'):
77412111Sralph 	case TRC('q'):
77512111Sralph 	case TRC('y'):
77612111Sralph 		return (DROP);
77712111Sralph 
77812111Sralph 	default:
77912111Sralph 		return (0);
78012111Sralph 	}
78112111Sralph }
78212111Sralph 
78312111Sralph /*
78412111Sralph  * sendmail ---
78512111Sralph  *   tell people about job completion
78612111Sralph  */
78712877Sralph static
78812111Sralph sendmail(bombed)
78912111Sralph 	int bombed;
79012111Sralph {
79112111Sralph 	static int p[2];
79212111Sralph 	register int i;
79312111Sralph 	int stat;
79412111Sralph 	register char *cp;
79512111Sralph 	char buf[100];
79612111Sralph 
79712111Sralph 	pipe(p);
79812111Sralph 	if ((stat = dofork(DORETURN)) == 0) {		/* child */
79912111Sralph 		dup2(p[0], 0);
80012111Sralph 		for (i = 3; i < NOFILE; i++)
80112111Sralph 			(void) close(i);
80212111Sralph 		if ((cp = rindex(MAIL, '/')) != NULL)
80312111Sralph 			cp++;
80412111Sralph 		else
80512111Sralph 			cp = MAIL;
80612111Sralph 		sprintf(buf, "%s@%s", line+1, host);
80712111Sralph 		execl(MAIL, cp, buf, 0);
80812111Sralph 		exit(0);
80912111Sralph 	} else if (stat > 0) {				/* parent */
81012111Sralph 		dup2(p[1], 1);
81112111Sralph 		printf("To: %s\n", line+1);
81212111Sralph 		printf("Subject: printer job\n\n");
81312111Sralph 		printf("Your printer job ");
81412111Sralph 		if (*jobname)
81512111Sralph 			printf("(%s) ", jobname);
81612463Sralph 		switch (bombed) {
81712463Sralph 		case 0:
81812463Sralph 			printf("\ncompleted successfully\n");
81912463Sralph 			break;
82012463Sralph 		default:
82112463Sralph 		case 1:
82212463Sralph 			printf("\ncould not be printed\n");
82312463Sralph 			break;
82412463Sralph 		case 2:
82512463Sralph 			printf("\ncould not be printed without an account on %s\n", host);
82612463Sralph 			break;
82712463Sralph 		}
82812111Sralph 		fflush(stdout);
82912111Sralph 		(void) close(1);
83012111Sralph 	}
83112111Sralph 	(void) close(p[0]);
83212111Sralph 	(void) close(p[1]);
83312111Sralph 	wait(&stat);
83412111Sralph }
83512111Sralph 
83612111Sralph /*
83712111Sralph  * dofork - fork with retries on failure
83812111Sralph  */
83912877Sralph static
84012111Sralph dofork(action)
84112111Sralph 	int action;
84212111Sralph {
84312111Sralph 	register int i, pid;
84412111Sralph 
84512111Sralph 	for (i = 0; i < 20; i++) {
84612463Sralph 		if ((pid = fork()) < 0) {
84712111Sralph 			sleep((unsigned)(i*i));
84812463Sralph 			continue;
84912463Sralph 		}
85012463Sralph 		/*
85112463Sralph 		 * Child should run as daemon instead of root
85212463Sralph 		 */
85312463Sralph 		if (pid == 0)
85412463Sralph 			setuid(DU);
85512463Sralph 		return(pid);
85612111Sralph 	}
85712111Sralph 	log("can't fork");
85812111Sralph 
85912111Sralph 	switch (action) {
86012111Sralph 	case DORETURN:
86112111Sralph 		return (-1);
86212111Sralph 	default:
86312111Sralph 		log("bad action (%d) to dofork", action);
86412111Sralph 		/*FALL THRU*/
86512111Sralph 	case DOABORT:
86612111Sralph 		exit(1);
86712111Sralph 	}
86812111Sralph 	/*NOTREACHED*/
86912111Sralph }
87012111Sralph 
87112111Sralph /*
87212111Sralph  * Cleanup child processes when a SIGINT is caught.
87312111Sralph  */
87412877Sralph static
87512111Sralph onintr()
87612111Sralph {
87712111Sralph 	kill(0, SIGINT);
87812111Sralph 	if (ofilter > 0)
87912111Sralph 		kill(ofilter, SIGCONT);
88012111Sralph 	while (wait(0) > 0)
88112111Sralph 		;
88212111Sralph 	exit(0);
88312111Sralph }
88412111Sralph 
88512877Sralph static
88612111Sralph init()
88712111Sralph {
88812111Sralph 	int status;
88912111Sralph 
89013169Sralph 	if ((status = pgetent(line, printer)) < 0)
89113169Sralph 		fatal("can't open printer description file");
89213169Sralph 	else if (status == 0)
89313169Sralph 		fatal("unknown printer");
89412111Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
89512111Sralph 		LP = DEFDEVLP;
89612111Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
89712463Sralph 		RP = DEFLP;
89812111Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
89912111Sralph 		LO = DEFLOCK;
90012111Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
90112111Sralph 		ST = DEFSTAT;
90212111Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
90312111Sralph 		LF = DEFLOGF;
90412111Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
90512111Sralph 		SD = DEFSPOOL;
90612111Sralph 	if ((DU = pgetnum("du")) < 0)
90712111Sralph 		DU = DEFUID;
90812111Sralph 	if ((FF = pgetstr("ff", &bp)) == NULL)
90912111Sralph 		FF = DEFFF;
91012111Sralph 	if ((PW = pgetnum("pw")) < 0)
91112111Sralph 		PW = DEFWIDTH;
91212111Sralph 	sprintf(&width[2], "%d", PW);
91312111Sralph 	if ((PL = pgetnum("pl")) < 0)
91412111Sralph 		PL = DEFLENGTH;
91512111Sralph 	sprintf(&length[2], "%d", PL);
91612463Sralph 	if ((PX = pgetnum("px")) < 0)
91712463Sralph 		PX = 0;
91812463Sralph 	sprintf(&pxwidth[2], "%d", PX);
91912463Sralph 	if ((PY = pgetnum("py")) < 0)
92012463Sralph 		PY = 0;
92112463Sralph 	sprintf(&pxlength[2], "%d", PY);
92212111Sralph 	RM = pgetstr("rm", &bp);
92312111Sralph 	AF = pgetstr("af", &bp);
92412111Sralph 	OF = pgetstr("of", &bp);
92512111Sralph 	IF = pgetstr("if", &bp);
92612463Sralph 	RF = pgetstr("rf", &bp);
92712111Sralph 	TF = pgetstr("tf", &bp);
92813233Sralph 	NF = pgetstr("nf", &bp);
92912111Sralph 	DF = pgetstr("df", &bp);
93012111Sralph 	GF = pgetstr("gf", &bp);
93112111Sralph 	VF = pgetstr("vf", &bp);
93212111Sralph 	CF = pgetstr("cf", &bp);
93312111Sralph 	TR = pgetstr("tr", &bp);
93412463Sralph 	RS = pgetflag("rs");
93512111Sralph 	SF = pgetflag("sf");
93612111Sralph 	SH = pgetflag("sh");
93712111Sralph 	SB = pgetflag("sb");
93812111Sralph 	RW = pgetflag("rw");
93912111Sralph 	BR = pgetnum("br");
94012111Sralph 	if ((FC = pgetnum("fc")) < 0)
94112111Sralph 		FC = 0;
94212111Sralph 	if ((FS = pgetnum("fs")) < 0)
94312111Sralph 		FS = 0;
94412111Sralph 	if ((XC = pgetnum("xc")) < 0)
94512111Sralph 		XC = 0;
94612111Sralph 	if ((XS = pgetnum("xs")) < 0)
94712111Sralph 		XS = 0;
94812581Sralph 	tof = !pgetflag("fo");
94912111Sralph }
95012111Sralph 
95112463Sralph /*
95212463Sralph  * Acquire line printer or remote connection.
95312463Sralph  */
95412877Sralph static
95512463Sralph openpr()
95612463Sralph {
95712463Sralph 	register int i, n;
95812463Sralph 
95912463Sralph 	if (*LP) {
96012463Sralph 		for (i = 1; ; i = i < 32 ? i << 1 : i) {
96113148Ssam 			pfd = open(LP, RW ? O_RDWR : O_WRONLY);
96212463Sralph 			if (pfd >= 0)
96312463Sralph 				break;
96412463Sralph 			if (errno == ENOENT) {
96512463Sralph 				log("cannot open %s", LP);
96612463Sralph 				exit(1);
96712463Sralph 			}
96812463Sralph 			if (i == 1)
96912463Sralph 				status("waiting for %s to become ready (offline ?)", printer);
97012463Sralph 			sleep(i);
97112463Sralph 		}
97212463Sralph 		if (isatty(pfd))
97312463Sralph 			setty();
97412463Sralph 		status("%s is ready and printing", printer);
97512463Sralph 	} else if (RM != NULL) {
97612463Sralph 		for (i = 1; ; i = i < 512 ? i << 1 : i) {
97712528Sralph 			pfd = getport(RM);
97812463Sralph 			if (pfd >= 0) {
97912463Sralph 				(void) sprintf(line, "\2%s\n", RP);
98012463Sralph 				n = strlen(line);
98112463Sralph 				if (write(pfd, line, n) != n)
98212463Sralph 					break;
98312463Sralph 				if (noresponse())
98412463Sralph 					(void) close(pfd);
98512463Sralph 				else
98612463Sralph 					break;
98712463Sralph 			}
98812463Sralph 			if (i == 1)
98912463Sralph 				status("waiting for %s to come up", RM);
99012463Sralph 			sleep(i);
99112463Sralph 		}
99212463Sralph 		status("sending to %s", RM);
99312463Sralph 		remote = 1;
99412463Sralph 	} else {
99512463Sralph 		log("no line printer device or remote machine name");
99612463Sralph 		exit(1);
99712463Sralph 	}
99812463Sralph 	/*
99912463Sralph 	 * Start up an output filter, if needed.
100012463Sralph 	 */
100112463Sralph 	if (OF) {
100212463Sralph 		int p[2];
100312463Sralph 		char *cp;
100412463Sralph 
100512463Sralph 		pipe(p);
100612463Sralph 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
100712463Sralph 			dup2(p[0], 0);		/* pipe is std in */
100812463Sralph 			dup2(pfd, 1);		/* printer is std out */
100912463Sralph 			for (i = 3; i < NOFILE; i++)
101012463Sralph 				(void) close(i);
101112463Sralph 			if ((cp = rindex(OF, '/')) == NULL)
101212463Sralph 				cp = OF;
101312463Sralph 			else
101412463Sralph 				cp++;
101512463Sralph 			execl(OF, cp, width, length, 0);
101612463Sralph 			log("can't execl output filter %s", OF);
101712463Sralph 			exit(1);
101812463Sralph 		}
101912463Sralph 		(void) close(p[0]);		/* close input side */
102012463Sralph 		ofd = p[1];			/* use pipe for output */
102112463Sralph 	} else {
102212463Sralph 		ofd = pfd;
102312463Sralph 		ofilter = 0;
102412463Sralph 	}
102512463Sralph }
102612463Sralph 
102712111Sralph struct bauds {
102812111Sralph 	int	baud;
102912111Sralph 	int	speed;
103012111Sralph } bauds[] = {
103112111Sralph 	50,	B50,
103212111Sralph 	75,	B75,
103312111Sralph 	110,	B110,
103412111Sralph 	134,	B134,
103512111Sralph 	150,	B150,
103612111Sralph 	200,	B200,
103712111Sralph 	300,	B300,
103812111Sralph 	600,	B600,
103912111Sralph 	1200,	B1200,
104012111Sralph 	1800,	B1800,
104112111Sralph 	2400,	B2400,
104212111Sralph 	4800,	B4800,
104312111Sralph 	9600,	B9600,
104412111Sralph 	19200,	EXTA,
104512111Sralph 	38400,	EXTB,
104612111Sralph 	0,	0
104712111Sralph };
104812111Sralph 
104912111Sralph /*
105012111Sralph  * setup tty lines.
105112111Sralph  */
105212877Sralph static
105312111Sralph setty()
105412111Sralph {
105512111Sralph 	struct sgttyb ttybuf;
105612111Sralph 	register struct bauds *bp;
105712111Sralph 
105812111Sralph 	if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
105912111Sralph 		log("cannot set exclusive-use");
106012111Sralph 		exit(1);
106112111Sralph 	}
106212111Sralph 	if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
106312111Sralph 		log("cannot get tty parameters");
106412111Sralph 		exit(1);
106512111Sralph 	}
106612111Sralph 	if (BR > 0) {
106712111Sralph 		for (bp = bauds; bp->baud; bp++)
106812111Sralph 			if (BR == bp->baud)
106912111Sralph 				break;
107012111Sralph 		if (!bp->baud) {
107112111Sralph 			log("illegal baud rate %d", BR);
107212111Sralph 			exit(1);
107312111Sralph 		}
107412111Sralph 		ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
107512111Sralph 	}
107613169Sralph 	ttybuf.sg_flags &= ~FC;
107713169Sralph 	ttybuf.sg_flags |= FS;
107812111Sralph 	if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
107912111Sralph 		log("cannot set tty parameters");
108012111Sralph 		exit(1);
108112111Sralph 	}
108212111Sralph 	if (XC) {
108312111Sralph 		if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
108412111Sralph 			log("cannot set local tty parameters");
108512111Sralph 			exit(1);
108612111Sralph 		}
108712111Sralph 	}
108812111Sralph 	if (XS) {
108912111Sralph 		if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
109012111Sralph 			log("cannot set local tty parameters");
109112111Sralph 			exit(1);
109212111Sralph 		}
109312111Sralph 	}
109412111Sralph }
109512463Sralph 
109612463Sralph /*VARARGS1*/
109712463Sralph static
109812463Sralph status(msg, a1, a2, a3)
109912463Sralph 	char *msg;
110012463Sralph {
110112463Sralph 	register int fd;
110212463Sralph 	char buf[BUFSIZ];
110312463Sralph 
110412463Sralph 	umask(0);
110513148Ssam 	fd = open(ST, O_WRONLY|O_CREAT, 0664);
110613148Ssam 	if (fd < 0 || flock(fd, LOCK_EX) < 0)
110712463Sralph 		fatal("cannot create status file");
110813148Ssam 	ftruncate(fd, 0);
110912463Sralph 	sprintf(buf, msg, a1, a2, a3);
111012463Sralph 	strcat(buf, "\n");
111112463Sralph 	(void) write(fd, buf, strlen(buf));
111212463Sralph 	(void) close(fd);
111312463Sralph }
1114