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