xref: /csrg-svn/usr.sbin/lpr/lpd/printjob.c (revision 13954)
1*13954Ssam #ifndef lint
2*13954Ssam static char sccsid[] = "@(#)printjob.c	4.11 (Berkeley) 07/17/83";
3*13954Ssam #endif
4*13954Ssam 
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 
1412877Sralph #define DORETURN	0		/* absorb fork error */
1512877Sralph #define DOABORT		1		/* abort if dofork fails */
1612111Sralph 
1712877Sralph static char	title[80];		/* ``pr'' title */
1812877Sralph static FILE	*cfp;			/* control file */
1912877Sralph static int	pfd;			/* printer file descriptor */
2012877Sralph static int	ofd;			/* output filter file descriptor */
2112877Sralph static int	lfd;			/* lock file descriptor */
2212877Sralph static int	pid;			/* pid of lpd process */
2312877Sralph static int	prchild;		/* id of pr process */
2412877Sralph static int	child;			/* id of any filters */
2512877Sralph static int	ofilter;		/* id of output filter, if any */
2612877Sralph static int	tof;			/* true if at top of form */
2712877Sralph static int	remote;			/* true if sending files to remote */
2812111Sralph 
2912877Sralph static char	logname[32];		/* user's login name */
3012877Sralph static char	jobname[32];		/* job or file name */
3112877Sralph static char	class[32];		/* classification field */
3212877Sralph static char	width[10] = "-w";	/* page width in characters */
3312877Sralph static char	length[10] = "-l";	/* page length in lines */
3412877Sralph static char	pxwidth[10] = "-x";	/* page width in pixels */
3512877Sralph static char	pxlength[10] = "-y";	/* page length in pixels */
3612877Sralph static char	indent[10] = "-i0";	/* indentation size in characters */
3712111Sralph 
3812111Sralph printjob()
3912111Sralph {
4012111Sralph 	struct stat stb;
4112111Sralph 	register struct queue *q, **qp;
4212111Sralph 	struct queue **queue;
4312111Sralph 	register int i, nitems;
4412111Sralph 	long pidoff;
4512111Sralph 	extern int onintr();
4612111Sralph 
4712111Sralph 	init();					/* set up capabilities */
4813442Sralph 	(void) write(1, "", 1);			/* ack that daemon is started */
4912877Sralph 	(void) close(1);			/* set up log file */
5012877Sralph 	(void) close(2);
5113148Ssam 	if (open(LF, O_WRONLY|O_APPEND) < 0)
5213148Ssam 		(void) open("/dev/null", O_WRONLY);
5312877Sralph 	dup(1);
5412463Sralph 	pid = getpid();				/* for use with lprm */
5512111Sralph 	setpgrp(0, pid);
5613148Ssam 	signal(SIGINT, onintr);
5712111Sralph 
5812111Sralph 	/*
5912111Sralph 	 * uses short form file names
6012111Sralph 	 */
6112111Sralph 	if (chdir(SD) < 0) {
6212111Sralph 		log("cannot chdir to %s", SD);
6312111Sralph 		exit(1);
6412111Sralph 	}
6512463Sralph 	if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
6612463Sralph 		exit(0);		/* printing disabled */
6713169Sralph 	lfd = open(LO, O_WRONLY|O_CREAT|O_TRUNC, 0644);
6813169Sralph 	if (lfd < 0) {
6913169Sralph 		log("cannot create %s", LO);
7013169Sralph 		exit(1);
7113169Sralph 	}
7213169Sralph 	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
7312111Sralph 		if (errno == EWOULDBLOCK)	/* active deamon present */
7412111Sralph 			exit(0);
7513169Sralph 		log("cannot lock %s", LO);
7612111Sralph 		exit(1);
7712111Sralph 	}
7813148Ssam 	ftruncate(lfd, 0);
7912111Sralph 	/*
8012111Sralph 	 * write process id for others to know
8112111Sralph 	 */
8212111Sralph 	sprintf(line, "%u\n", pid);
8312111Sralph 	pidoff = i = strlen(line);
8412463Sralph 	if (write(lfd, line, i) != i) {
8512111Sralph 		log("cannot write daemon pid");
8612111Sralph 		exit(1);
8712111Sralph 	}
8812111Sralph 	/*
8912111Sralph 	 * search the spool directory for work and sort by queue order.
9012111Sralph 	 */
9112111Sralph 	if ((nitems = getq(&queue)) < 0) {
9212111Sralph 		log("can't scan spool directory %s", SD);
9312111Sralph 		exit(1);
9412111Sralph 	}
9512463Sralph 	if (nitems == 0)		/* no work to do */
9612111Sralph 		exit(0);
9713169Sralph 	if (stb.st_mode & 01) {		/* reset queue flag */
9813169Sralph 		if (fchmod(lfd, stb.st_mode & 0776) < 0)
9913169Sralph 			log("cannot chmod %s", LO);
10013169Sralph 	}
10112463Sralph 	openpr();			/* open printer or remote */
10212463Sralph again:
10312111Sralph 	/*
10412111Sralph 	 * we found something to do now do it --
10512111Sralph 	 *    write the name of the current control file into the lock file
10612111Sralph 	 *    so the spool queue program can tell what we're working on
10712111Sralph 	 */
10812111Sralph 	for (qp = queue; nitems--; free((char *) q)) {
10912111Sralph 		q = *qp++;
11012111Sralph 		if (stat(q->q_name, &stb) < 0)
11112111Sralph 			continue;
11212463Sralph 	restart:
11312111Sralph 		(void) lseek(lfd, pidoff, 0);
11412111Sralph 		(void) sprintf(line, "%s\n", q->q_name);
11512111Sralph 		i = strlen(line);
11612111Sralph 		if (write(lfd, line, i) != i)
11712111Sralph 			log("can't write (%d) control file name", errno);
11812111Sralph 		if (!remote)
11912111Sralph 			i = printit(q->q_name);
12012111Sralph 		else
12112111Sralph 			i = sendit(q->q_name);
12212463Sralph 		/*
12313169Sralph 		 * Check to see if we are supposed to stop printing or
12413169Sralph 		 * if we are to rebuild the queue.
12512463Sralph 		 */
12613169Sralph 		if (fstat(lfd, &stb) == 0) {
12713169Sralph 			if (stb.st_mode & 0100)
12813169Sralph 				goto done;
12913169Sralph 			if (stb.st_mode & 01) {
13013169Sralph 				for (free((char *) q); nitems--; free((char *) q))
13113169Sralph 					q = *qp++;
13213169Sralph 				if (fchmod(lfd, stb.st_mode & 0776) < 0)
13313169Sralph 					log("cannot chmod %s", LO);
13413169Sralph 				break;
13513169Sralph 			}
13613169Sralph 		}
13712463Sralph 		/*
13812463Sralph 		 * Check to see if we should try reprinting the job.
13912463Sralph 		 */
14012463Sralph 		if (i > 0) {
14112111Sralph 			log("restarting");
14212111Sralph 			if (ofilter > 0) {
14312111Sralph 				kill(ofilter, SIGCONT);	/* to be sure */
14412111Sralph 				(void) close(ofd);
14512111Sralph 				while ((i = wait(0)) > 0 && i != ofilter)
14612111Sralph 					;
14712111Sralph 				ofilter = 0;
14812111Sralph 			}
14912463Sralph 			(void) close(pfd);	/* close printer */
15012463Sralph 			(void) lseek(lfd, pidoff, 0);
15112463Sralph 			if (write(lfd, "\n", 1) != 1)
15212463Sralph 				log("can't write (%d) control file name", errno);
15312463Sralph 			openpr();		/* try to reopen printer */
15412111Sralph 			goto restart;
15512111Sralph 		}
15612111Sralph 	}
15712111Sralph 	free((char *) queue);
15812463Sralph 	/*
15912463Sralph 	 * search the spool directory for more work.
16012463Sralph 	 */
16112463Sralph 	if ((nitems = getq(&queue)) < 0) {
16212463Sralph 		log("can't scan spool directory %s", SD);
16312463Sralph 		exit(1);
16412463Sralph 	}
16512463Sralph 	if (nitems == 0) {		/* no more work to do */
16612463Sralph 	done:
16712463Sralph 		if (!SF && !tof)
16812463Sralph 			(void) write(ofd, FF, strlen(FF));
16912463Sralph 		if (TR != NULL)		/* output trailer */
17012463Sralph 			(void) write(ofd, TR, strlen(TR));
17112463Sralph 		exit(0);
17212463Sralph 	}
17312111Sralph 	goto again;
17412111Sralph }
17512111Sralph 
17612111Sralph char	fonts[4][50];	/* fonts for troff */
17712111Sralph 
17812111Sralph static char ifonts[4][18] = {
17912111Sralph 	"/usr/lib/vfont/R",
18012111Sralph 	"/usr/lib/vfont/I",
18112111Sralph 	"/usr/lib/vfont/B",
18212111Sralph 	"/usr/lib/vfont/S"
18312111Sralph };
18412111Sralph 
18512111Sralph /*
18612111Sralph  * The remaining part is the reading of the control file (cf)
18712111Sralph  * and performing the various actions.
18812111Sralph  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
18912111Sralph  * -1 if a non-recoverable error occured.
19012111Sralph  */
19112877Sralph static
19212111Sralph printit(file)
19312111Sralph 	char *file;
19412111Sralph {
19512111Sralph 	register int i;
19612111Sralph 	int bombed = 0;
19712111Sralph 
19812111Sralph 	/*
19912111Sralph 	 * open control file
20012111Sralph 	 */
20112111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
20212111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
20312111Sralph 		return(0);
20412111Sralph 	}
20512111Sralph 	/*
20612111Sralph 	 * Reset troff fonts.
20712111Sralph 	 */
20812111Sralph 	for (i = 0; i < 4; i++)
20912111Sralph 		strcpy(fonts[i], ifonts[i]);
21012111Sralph 
21112111Sralph 	/*
21212111Sralph 	 *      read the control file for work to do
21312111Sralph 	 *
21412111Sralph 	 *      file format -- first character in the line is a command
21512111Sralph 	 *      rest of the line is the argument.
21612111Sralph 	 *      valid commands are:
21712111Sralph 	 *
21812111Sralph 	 *		J -- "job name" on banner page
21912111Sralph 	 *		C -- "class name" on banner page
22012111Sralph 	 *              L -- "literal" user's name to print on banner
22112111Sralph 	 *		T -- "title" for pr
22212111Sralph 	 *		H -- "host name" of machine where lpr was done
22312111Sralph 	 *              P -- "person" user's login name
22412581Sralph 	 *              I -- "indent" amount to indent output
22512111Sralph 	 *              f -- "file name" name of text file to print
22612111Sralph 	 *		l -- "file name" text file with control chars
22712111Sralph 	 *		p -- "file name" text file to print with pr(1)
22812111Sralph 	 *		t -- "file name" troff(1) file to print
22913233Sralph 	 *		n -- "file name" ditroff(1) file to print
23012111Sralph 	 *		d -- "file name" dvi file to print
23112111Sralph 	 *		g -- "file name" plot(1G) file to print
23212111Sralph 	 *		v -- "file name" plain raster file to print
23312111Sralph 	 *		c -- "file name" cifplot file to print
23412111Sralph 	 *		1 -- "R font file" for troff
23512111Sralph 	 *		2 -- "I font file" for troff
23612111Sralph 	 *		3 -- "B font file" for troff
23712111Sralph 	 *		4 -- "S font file" for troff
23812111Sralph 	 *		N -- "name" of file (used by lpq)
23912111Sralph 	 *              U -- "unlink" name of file to remove
24012111Sralph 	 *                    (after we print it. (Pass 2 only)).
24112111Sralph 	 *		M -- "mail" to user when done printing
24212111Sralph 	 *
24312111Sralph 	 *      getline reads a line and expands tabs to blanks
24412111Sralph 	 */
24512111Sralph 
24612111Sralph 	/* pass 1 */
24712111Sralph 
24812111Sralph 	while (getline(cfp))
24912111Sralph 		switch (line[0]) {
25012111Sralph 		case 'H':
25112111Sralph 			strcpy(host, line+1);
25212111Sralph 			if (class[0] == '\0')
25312111Sralph 				strcpy(class, line+1);
25412111Sralph 			continue;
25512111Sralph 
25612111Sralph 		case 'P':
25712111Sralph 			strcpy(logname, line+1);
25812463Sralph 			if (RS) {			/* restricted */
25912463Sralph 				if (getpwnam(logname) == (struct passwd *)0) {
26012463Sralph 					bombed = 2;
26112463Sralph 					sendmail(bombed);
26212463Sralph 					goto pass2;
26312463Sralph 				}
26412463Sralph 			}
26512111Sralph 			continue;
26612111Sralph 
26712111Sralph 		case 'J':
26812111Sralph 			if (line[1] != '\0')
26912111Sralph 				strcpy(jobname, line+1);
27012111Sralph 			else
27112111Sralph 				strcpy(jobname, " ");
27212111Sralph 			continue;
27312111Sralph 
27412111Sralph 		case 'C':
27512111Sralph 			if (line[1] != '\0')
27612111Sralph 				strcpy(class, line+1);
27712111Sralph 			else if (class[0] == '\0')
27812111Sralph 				gethostname(class, sizeof (class));
27912111Sralph 			continue;
28012111Sralph 
28112111Sralph 		case 'T':	/* header title for pr */
28212111Sralph 			strcpy(title, line+1);
28312111Sralph 			continue;
28412111Sralph 
28512111Sralph 		case 'L':	/* identification line */
28612111Sralph 			if (!SH)
28712111Sralph 				banner(line+1, jobname);
28812111Sralph 			continue;
28912111Sralph 
29012111Sralph 		case '1':	/* troff fonts */
29112111Sralph 		case '2':
29212111Sralph 		case '3':
29312111Sralph 		case '4':
29412111Sralph 			if (line[1] != '\0')
29512111Sralph 				strcpy(fonts[line[0]-'1'], line+1);
29612111Sralph 			continue;
29712111Sralph 
29812111Sralph 		case 'W':	/* page width */
29912111Sralph 			strcpy(width+2, line+1);
30012111Sralph 			continue;
30112111Sralph 
30212581Sralph 		case 'I':	/* indent amount */
30312581Sralph 			strcpy(indent+2, line+1);
30412581Sralph 			continue;
30512581Sralph 
30612111Sralph 		default:	/* some file to print */
30712111Sralph 			if ((i = print(line[0], line+1)) > 0) {
30812111Sralph 				(void) fclose(cfp);
30912111Sralph 				return(1);
31012111Sralph 			} else if (i < 0)
31112111Sralph 				bombed = 1;
31212111Sralph 			title[0] = '\0';
31312111Sralph 			continue;
31412111Sralph 
31512111Sralph 		case 'N':
31612111Sralph 		case 'U':
31712111Sralph 		case 'M':
31812111Sralph 			continue;
31912111Sralph 		}
32012111Sralph 
32112111Sralph 	/* pass 2 */
32212111Sralph 
32312463Sralph pass2:
32412111Sralph 	fseek(cfp, 0L, 0);
32512111Sralph 	while (getline(cfp))
32612111Sralph 		switch (line[0]) {
32712111Sralph 		case 'M':
32812463Sralph 			if (bombed != 2)		/* already sent if 2 */
32912463Sralph 				sendmail(bombed);
33012111Sralph 			continue;
33112111Sralph 
33212111Sralph 		case 'U':
33312111Sralph 			(void) unlink(line+1);
33412111Sralph 		}
33512111Sralph 	/*
33612111Sralph 	 * clean-up incase another control file exists
33712111Sralph 	 */
33812111Sralph 	(void) fclose(cfp);
33912111Sralph 	(void) unlink(file);
34012111Sralph 	return(0);
34112111Sralph }
34212111Sralph 
34312111Sralph /*
34412111Sralph  * Print a file.
34513233Sralph  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
34612111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
34712111Sralph  * 0 if all is well.
34812111Sralph  * Note: all filters take stdin as the file, stdout as the printer,
34912111Sralph  * stderr as the log file, and must not ignore SIGINT.
35012111Sralph  */
35112877Sralph static
35212111Sralph print(format, file)
35312111Sralph 	int format;
35412111Sralph 	char *file;
35512111Sralph {
35612111Sralph 	register int n, fi, fo;
35712111Sralph 	register char *prog;
35812111Sralph 	char *av[15], buf[BUFSIZ];
35912111Sralph 	int pid, p[2], stopped = 0;
36012111Sralph 	union wait status;
36112111Sralph 
36213148Ssam 	if ((fi = open(file, O_RDONLY)) < 0) {
36312111Sralph 		log("%s: open failure <errno = %d>", file, errno);
36412111Sralph 		return(-1);
36512111Sralph 	}
36612111Sralph 	if (!SF && !tof) {		/* start on a fresh page */
36712111Sralph 		(void) write(ofd, FF, strlen(FF));
36812111Sralph 		tof = 1;
36912111Sralph 	}
37012111Sralph 	if (IF == NULL && (format == 'f' || format == 'l')) {
37112111Sralph 		tof = 0;
37212111Sralph 		while ((n = read(fi, buf, BUFSIZ)) > 0)
37312111Sralph 			if (write(ofd, buf, n) != n) {
37412111Sralph 				(void) close(fi);
37512111Sralph 				return(1);
37612111Sralph 			}
37712111Sralph 		(void) close(fi);
37812111Sralph 		return(0);
37912111Sralph 	}
38012111Sralph 	switch (format) {
38112111Sralph 	case 'p':	/* print file using 'pr' */
38212111Sralph 		if (IF == NULL) {	/* use output filter */
38312111Sralph 			prog = PR;
38412111Sralph 			av[0] = "pr";
38512111Sralph 			av[1] = width;
38612111Sralph 			av[2] = length;
38712111Sralph 			av[3] = "-h";
38812111Sralph 			av[4] = *title ? title : " ";
38912111Sralph 			av[5] = 0;
39012111Sralph 			fo = ofd;
39112111Sralph 			goto start;
39212111Sralph 		}
39312111Sralph 		pipe(p);
39412111Sralph 		if ((prchild = dofork(DORETURN)) == 0) {	/* child */
39512111Sralph 			dup2(fi, 0);		/* file is stdin */
39612111Sralph 			dup2(p[1], 1);		/* pipe is stdout */
39712111Sralph 			for (n = 3; n < NOFILE; n++)
39812111Sralph 				(void) close(n);
39912111Sralph 			execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
40012111Sralph 			log("cannot execl %s", PR);
40112111Sralph 			exit(2);
40212111Sralph 		}
40312111Sralph 		(void) close(p[1]);		/* close output side */
40412111Sralph 		(void) close(fi);
40512111Sralph 		if (prchild < 0) {
40612111Sralph 			prchild = 0;
40712111Sralph 			(void) close(p[0]);
40812111Sralph 			return(-1);
40912111Sralph 		}
41012111Sralph 		fi = p[0];			/* use pipe for input */
41112111Sralph 	case 'f':	/* print plain text file */
41212111Sralph 		prog = IF;
41312111Sralph 		av[1] = width;
41412111Sralph 		av[2] = length;
41512581Sralph 		av[3] = indent;
41612581Sralph 		n = 4;
41712111Sralph 		break;
41812111Sralph 	case 'l':	/* like 'f' but pass control characters */
41912111Sralph 		prog = IF;
42012111Sralph 		av[1] = "-l";
42112111Sralph 		av[2] = width;
42212111Sralph 		av[3] = length;
42312581Sralph 		av[4] = indent;
42412581Sralph 		n = 5;
42512111Sralph 		break;
42612463Sralph 	case 'r':	/* print a fortran text file */
42712463Sralph 		prog = RF;
42812463Sralph 		av[1] = width;
42912463Sralph 		av[2] = length;
43012463Sralph 		n = 3;
43112463Sralph 		break;
43212111Sralph 	case 't':	/* print troff output */
43313233Sralph 	case 'n':	/* print ditroff output */
43412463Sralph 	case 'd':	/* print tex output */
43512111Sralph 		(void) unlink(".railmag");
43612463Sralph 		if ((fo = creat(".railmag", FILMOD)) < 0) {
43712111Sralph 			log("cannot create .railmag");
43812111Sralph 			(void) unlink(".railmag");
43912111Sralph 		} else {
44012111Sralph 			for (n = 0; n < 4; n++) {
44112111Sralph 				if (fonts[n][0] != '/')
44212111Sralph 					(void) write(fo, "/usr/lib/vfont/", 15);
44312111Sralph 				(void) write(fo, fonts[n], strlen(fonts[n]));
44412111Sralph 				(void) write(fo, "\n", 1);
44512111Sralph 			}
44612111Sralph 			(void) close(fo);
44712111Sralph 		}
44813233Sralph 		prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
44912463Sralph 		av[1] = pxwidth;
45012463Sralph 		av[2] = pxlength;
45112463Sralph 		n = 3;
45212111Sralph 		break;
45312111Sralph 	case 'c':	/* print cifplot output */
45412111Sralph 		prog = CF;
45512463Sralph 		av[1] = pxwidth;
45612463Sralph 		av[2] = pxlength;
45712463Sralph 		n = 3;
45812111Sralph 		break;
45912111Sralph 	case 'g':	/* print plot(1G) output */
46012111Sralph 		prog = GF;
46112463Sralph 		av[1] = pxwidth;
46212463Sralph 		av[2] = pxlength;
46312463Sralph 		n = 3;
46412111Sralph 		break;
46512111Sralph 	case 'v':	/* print raster output */
46612111Sralph 		prog = VF;
46712463Sralph 		av[1] = pxwidth;
46812463Sralph 		av[2] = pxlength;
46912463Sralph 		n = 3;
47012111Sralph 		break;
47112111Sralph 	default:
47212111Sralph 		(void) close(fi);
47312111Sralph 		log("illegal format character '%c'", format);
47412111Sralph 		return(-1);
47512111Sralph 	}
47612111Sralph 	if ((av[0] = rindex(prog, '/')) != NULL)
47712111Sralph 		av[0]++;
47812111Sralph 	else
47912111Sralph 		av[0] = prog;
48012111Sralph 	av[n++] = "-n";
48112111Sralph 	av[n++] = logname;
48212111Sralph 	av[n++] = "-h";
48312111Sralph 	av[n++] = host;
48412111Sralph 	av[n++] = AF;
48512111Sralph 	av[n] = 0;
48612111Sralph 	fo = pfd;
48712111Sralph 	if (ofilter > 0) {		/* stop output filter */
48812111Sralph 		write(ofd, "\031\1", 2);
48912111Sralph 		while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
49012111Sralph 			;
49112111Sralph 		if (status.w_stopval != WSTOPPED) {
49212111Sralph 			(void) close(fi);
49312111Sralph 			log("output filter died (%d)", status.w_retcode);
49412111Sralph 			return(1);
49512111Sralph 		}
49612111Sralph 		stopped++;
49712111Sralph 	}
49812111Sralph start:
49912111Sralph 	if ((child = dofork(DORETURN)) == 0) {	/* child */
50012111Sralph 		dup2(fi, 0);
50112111Sralph 		dup2(fo, 1);
50212111Sralph 		for (n = 3; n < NOFILE; n++)
50312111Sralph 			(void) close(n);
50412111Sralph 		execv(prog, av);
50512111Sralph 		log("cannot execl %s", prog);
50612111Sralph 		exit(2);
50712111Sralph 	}
50812111Sralph 	(void) close(fi);
50912111Sralph 	if (child < 0)
51012111Sralph 		status.w_retcode = 100;
51112111Sralph 	else
51212111Sralph 		while ((pid = wait(&status)) > 0 && pid != child)
51312111Sralph 			;
51412111Sralph 	child = 0;
51512111Sralph 	prchild = 0;
51612111Sralph 	if (stopped) {		/* restart output filter */
51712111Sralph 		if (kill(ofilter, SIGCONT) < 0) {
51812111Sralph 			log("cannot restart output filter");
51912111Sralph 			exit(1);
52012111Sralph 		}
52112111Sralph 	}
52212111Sralph 	tof = 0;
52312111Sralph 	if (!WIFEXITED(status) || status.w_retcode > 1) {
52412111Sralph 		log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode);
52512111Sralph 		return(-1);
52612111Sralph 	} else if (status.w_retcode == 1)
52712111Sralph 		return(1);
52812111Sralph 	tof = 1;
52912111Sralph 	return(0);
53012111Sralph }
53112111Sralph 
53212111Sralph /*
53312111Sralph  * Send the daemon control file (cf) and any data files.
53412111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
53512111Sralph  * 0 if all is well.
53612111Sralph  */
53712877Sralph static
53812111Sralph sendit(file)
53912111Sralph 	char *file;
54012111Sralph {
54112111Sralph 	register int linelen, err = 0;
54212111Sralph 	char last[132];
54312111Sralph 
54412111Sralph 	/*
54512111Sralph 	 * open control file
54612111Sralph 	 */
54712111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
54812111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
54912111Sralph 		return(0);
55012111Sralph 	}
55112111Sralph 	/*
55212111Sralph 	 *      read the control file for work to do
55312111Sralph 	 *
55412111Sralph 	 *      file format -- first character in the line is a command
55512111Sralph 	 *      rest of the line is the argument.
55612111Sralph 	 *      commands of interest are:
55712111Sralph 	 *
55812111Sralph 	 *            a-z -- "file name" name of file to print
55912111Sralph 	 *              U -- "unlink" name of file to remove
56012111Sralph 	 *                    (after we print it. (Pass 2 only)).
56112111Sralph 	 */
56212111Sralph 
56312111Sralph 	/*
56412111Sralph 	 * pass 1
56512111Sralph 	 */
56612111Sralph 	while (getline(cfp)) {
56712111Sralph 	again:
56812111Sralph 		if (line[0] >= 'a' && line[0] <= 'z') {
56912111Sralph 			strcpy(last, line);
57012111Sralph 			while (linelen = getline(cfp))
57112111Sralph 				if (strcmp(last, line))
57212111Sralph 					break;
57312111Sralph 			if ((err = sendfile('\3', last+1)) > 0) {
57412111Sralph 				(void) fclose(cfp);
57512111Sralph 				return(1);
57612111Sralph 			} else if (err)
57712111Sralph 				break;
57812111Sralph 			if (linelen)
57912111Sralph 				goto again;
58012111Sralph 			break;
58112111Sralph 		}
58212111Sralph 	}
58312111Sralph 	if (!err && sendfile('\2', file) > 0) {
58412111Sralph 		(void) fclose(cfp);
58512111Sralph 		return(1);
58612111Sralph 	}
58712111Sralph 	/*
58812111Sralph 	 * pass 2
58912111Sralph 	 */
59012111Sralph 	fseek(cfp, 0L, 0);
59112111Sralph 	while (getline(cfp))
59212111Sralph 		if (line[0] == 'U')
59312111Sralph 			(void) unlink(line+1);
59412111Sralph 	/*
59512111Sralph 	 * clean-up incase another control file exists
59612111Sralph 	 */
59712111Sralph 	(void) fclose(cfp);
59812111Sralph 	(void) unlink(file);
59912111Sralph 	return(0);
60012111Sralph }
60112111Sralph 
60212111Sralph /*
60312111Sralph  * Send a data file to the remote machine and spool it.
60412111Sralph  * Return positive if we should try resending.
60512111Sralph  */
60612877Sralph static
60712111Sralph sendfile(type, file)
60812111Sralph 	char type, *file;
60912111Sralph {
61012111Sralph 	register int f, i, amt;
61112111Sralph 	struct stat stb;
61212111Sralph 	char buf[BUFSIZ];
61312111Sralph 	int sizerr;
61412111Sralph 
61513148Ssam 	if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) {
61612111Sralph 		log("file (%s) open failure <errno = %d>", file, errno);
61712111Sralph 		return(-1);
61812111Sralph 	}
61912111Sralph 	(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
62012111Sralph 	amt = strlen(buf);
62112692Sralph 	if (write(pfd, buf, amt) != amt) {
62212692Sralph 		(void) close(f);
62312111Sralph 		return(1);
62412692Sralph 	}
62512692Sralph 	if (noresponse()) {
62612692Sralph 		(void) close(f);
62712111Sralph 		return(1);
62812692Sralph 	}
62912111Sralph 	sizerr = 0;
63012111Sralph 	for (i = 0; i < stb.st_size; i += BUFSIZ) {
63112111Sralph 		amt = BUFSIZ;
63212111Sralph 		if (i + amt > stb.st_size)
63312111Sralph 			amt = stb.st_size - i;
63412111Sralph 		if (sizerr == 0 && read(f, buf, amt) != amt)
63512111Sralph 			sizerr = 1;
63612692Sralph 		if (write(pfd, buf, amt) != amt) {
63712692Sralph 			(void) close(f);
63812111Sralph 			return(1);
63912692Sralph 		}
64012111Sralph 	}
64112111Sralph 	(void) close(f);
64212111Sralph 	if (sizerr) {
64312111Sralph 		log("%s: changed size", file);
64412111Sralph 		(void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
64512111Sralph 		return(-1);
64612111Sralph 	}
64712111Sralph 	if (write(pfd, "", 1) != 1)
64812111Sralph 		return(1);
64912111Sralph 	if (noresponse())
65012111Sralph 		return(1);
65112111Sralph 	return(0);
65212111Sralph }
65312111Sralph 
65412111Sralph /*
65512111Sralph  * Check to make sure there have been no errors and that both programs
65612111Sralph  * are in sync with eachother.
65712111Sralph  * Return non-zero if the connection was lost.
65812111Sralph  */
65912111Sralph static
66012111Sralph noresponse()
66112111Sralph {
66212111Sralph 	char resp;
66312111Sralph 
66412111Sralph 	if (read(pfd, &resp, 1) != 1 || resp != '\0') {
66512111Sralph 		log("lost connection or error in recvjob");
66612111Sralph 		return(1);
66712111Sralph 	}
66812111Sralph 	return(0);
66912111Sralph }
67012111Sralph 
67112111Sralph /*
67212111Sralph  * Banner printing stuff
67312111Sralph  */
67412877Sralph static
67512111Sralph banner(name1, name2)
67612111Sralph 	char *name1, *name2;
67712111Sralph {
67812111Sralph 	time_t tvec;
67912111Sralph 	extern char *ctime();
68012111Sralph 
68112111Sralph 	time(&tvec);
68212111Sralph 	if (!SF && !tof)
68312111Sralph 		(void) write(ofd, FF, strlen(FF));
68412111Sralph 	if (SB) {	/* short banner only */
68512111Sralph 		if (class[0]) {
68612111Sralph 			(void) write(ofd, class, strlen(class));
68712111Sralph 			(void) write(ofd, ":", 1);
68812111Sralph 		}
68912111Sralph 		(void) write(ofd, name1, strlen(name1));
69012111Sralph 		(void) write(ofd, "  Job: ", 7);
69112111Sralph 		(void) write(ofd, name2, strlen(name2));
69212111Sralph 		(void) write(ofd, "  Date: ", 8);
69312111Sralph 		(void) write(ofd, ctime(&tvec), 24);
69412111Sralph 		(void) write(ofd, "\n", 1);
69512111Sralph 	} else {	/* normal banner */
69612111Sralph 		(void) write(ofd, "\n\n\n", 3);
69712111Sralph 		scan_out(ofd, name1, '\0');
69812111Sralph 		(void) write(ofd, "\n\n", 2);
69912111Sralph 		scan_out(ofd, name2, '\0');
70012111Sralph 		if (class[0]) {
70112111Sralph 			(void) write(ofd,"\n\n\n",3);
70212111Sralph 			scan_out(ofd, class, '\0');
70312111Sralph 		}
70412111Sralph 		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
70512111Sralph 		(void) write(ofd, name2, strlen(name2));
70612111Sralph 		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
70712111Sralph 		(void) write(ofd, ctime(&tvec), 24);
70812111Sralph 		(void) write(ofd, "\n", 1);
70912111Sralph 	}
71012111Sralph 	if (!SF)
71112111Sralph 		(void) write(ofd, FF, strlen(FF));
71212111Sralph 	tof = 1;
71312111Sralph }
71412111Sralph 
71512877Sralph static char *
71612111Sralph scnline(key, p, c)
71712111Sralph 	register char key, *p;
71812111Sralph 	char c;
71912111Sralph {
72012111Sralph 	register scnwidth;
72112111Sralph 
72212111Sralph 	for (scnwidth = WIDTH; --scnwidth;) {
72312111Sralph 		key <<= 1;
72412111Sralph 		*p++ = key & 0200 ? c : BACKGND;
72512111Sralph 	}
72612111Sralph 	return (p);
72712111Sralph }
72812111Sralph 
72912111Sralph #define TRC(q)	(((q)-' ')&0177)
73012111Sralph 
73112877Sralph static
73212111Sralph scan_out(scfd, scsp, dlm)
73312111Sralph 	int scfd;
73412111Sralph 	char *scsp, dlm;
73512111Sralph {
73612111Sralph 	register char *strp;
73712111Sralph 	register nchrs, j;
73812111Sralph 	char outbuf[LINELEN+1], *sp, c, cc;
73912111Sralph 	int d, scnhgt;
74012111Sralph 	extern char scnkey[][HEIGHT];	/* in lpdchar.c */
74112111Sralph 
74212111Sralph 	for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
74312111Sralph 		strp = &outbuf[0];
74412111Sralph 		sp = scsp;
74512111Sralph 		for (nchrs = 0; ; ) {
74612111Sralph 			d = dropit(c = TRC(cc = *sp++));
74712111Sralph 			if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
74812111Sralph 				for (j = WIDTH; --j;)
74912111Sralph 					*strp++ = BACKGND;
75012111Sralph 			else
75112111Sralph 				strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
75212111Sralph 			if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
75312111Sralph 				break;
75412111Sralph 			*strp++ = BACKGND;
75512111Sralph 			*strp++ = BACKGND;
75612111Sralph 		}
75712111Sralph 		while (*--strp == BACKGND && strp >= outbuf)
75812111Sralph 			;
75912111Sralph 		strp++;
76012111Sralph 		*strp++ = '\n';
76112111Sralph 		(void) write(scfd, outbuf, strp-outbuf);
76212111Sralph 	}
76312111Sralph }
76412111Sralph 
76512877Sralph static
76612111Sralph dropit(c)
76712111Sralph 	char c;
76812111Sralph {
76912111Sralph 	switch(c) {
77012111Sralph 
77112111Sralph 	case TRC('_'):
77212111Sralph 	case TRC(';'):
77312111Sralph 	case TRC(','):
77412111Sralph 	case TRC('g'):
77512111Sralph 	case TRC('j'):
77612111Sralph 	case TRC('p'):
77712111Sralph 	case TRC('q'):
77812111Sralph 	case TRC('y'):
77912111Sralph 		return (DROP);
78012111Sralph 
78112111Sralph 	default:
78212111Sralph 		return (0);
78312111Sralph 	}
78412111Sralph }
78512111Sralph 
78612111Sralph /*
78712111Sralph  * sendmail ---
78812111Sralph  *   tell people about job completion
78912111Sralph  */
79012877Sralph static
79112111Sralph sendmail(bombed)
79212111Sralph 	int bombed;
79312111Sralph {
79412111Sralph 	static int p[2];
79512111Sralph 	register int i;
79612111Sralph 	int stat;
79712111Sralph 	register char *cp;
79812111Sralph 	char buf[100];
79912111Sralph 
80012111Sralph 	pipe(p);
80112111Sralph 	if ((stat = dofork(DORETURN)) == 0) {		/* child */
80212111Sralph 		dup2(p[0], 0);
80312111Sralph 		for (i = 3; i < NOFILE; i++)
80412111Sralph 			(void) close(i);
80512111Sralph 		if ((cp = rindex(MAIL, '/')) != NULL)
80612111Sralph 			cp++;
80712111Sralph 		else
80812111Sralph 			cp = MAIL;
80912111Sralph 		sprintf(buf, "%s@%s", line+1, host);
81012111Sralph 		execl(MAIL, cp, buf, 0);
81112111Sralph 		exit(0);
81212111Sralph 	} else if (stat > 0) {				/* parent */
81312111Sralph 		dup2(p[1], 1);
81412111Sralph 		printf("To: %s\n", line+1);
81512111Sralph 		printf("Subject: printer job\n\n");
81612111Sralph 		printf("Your printer job ");
81712111Sralph 		if (*jobname)
81812111Sralph 			printf("(%s) ", jobname);
81912463Sralph 		switch (bombed) {
82012463Sralph 		case 0:
82112463Sralph 			printf("\ncompleted successfully\n");
82212463Sralph 			break;
82312463Sralph 		default:
82412463Sralph 		case 1:
82512463Sralph 			printf("\ncould not be printed\n");
82612463Sralph 			break;
82712463Sralph 		case 2:
82812463Sralph 			printf("\ncould not be printed without an account on %s\n", host);
82912463Sralph 			break;
83012463Sralph 		}
83112111Sralph 		fflush(stdout);
83212111Sralph 		(void) close(1);
83312111Sralph 	}
83412111Sralph 	(void) close(p[0]);
83512111Sralph 	(void) close(p[1]);
83612111Sralph 	wait(&stat);
83712111Sralph }
83812111Sralph 
83912111Sralph /*
84012111Sralph  * dofork - fork with retries on failure
84112111Sralph  */
84212877Sralph static
84312111Sralph dofork(action)
84412111Sralph 	int action;
84512111Sralph {
84612111Sralph 	register int i, pid;
84712111Sralph 
84812111Sralph 	for (i = 0; i < 20; i++) {
84912463Sralph 		if ((pid = fork()) < 0) {
85012111Sralph 			sleep((unsigned)(i*i));
85112463Sralph 			continue;
85212463Sralph 		}
85312463Sralph 		/*
85412463Sralph 		 * Child should run as daemon instead of root
85512463Sralph 		 */
85612463Sralph 		if (pid == 0)
85712463Sralph 			setuid(DU);
85812463Sralph 		return(pid);
85912111Sralph 	}
86012111Sralph 	log("can't fork");
86112111Sralph 
86212111Sralph 	switch (action) {
86312111Sralph 	case DORETURN:
86412111Sralph 		return (-1);
86512111Sralph 	default:
86612111Sralph 		log("bad action (%d) to dofork", action);
86712111Sralph 		/*FALL THRU*/
86812111Sralph 	case DOABORT:
86912111Sralph 		exit(1);
87012111Sralph 	}
87112111Sralph 	/*NOTREACHED*/
87212111Sralph }
87312111Sralph 
87412111Sralph /*
87512111Sralph  * Cleanup child processes when a SIGINT is caught.
87612111Sralph  */
87712877Sralph static
87812111Sralph onintr()
87912111Sralph {
88012111Sralph 	kill(0, SIGINT);
88112111Sralph 	if (ofilter > 0)
88212111Sralph 		kill(ofilter, SIGCONT);
88312111Sralph 	while (wait(0) > 0)
88412111Sralph 		;
88512111Sralph 	exit(0);
88612111Sralph }
88712111Sralph 
88812877Sralph static
88912111Sralph init()
89012111Sralph {
89112111Sralph 	int status;
89212111Sralph 
89313169Sralph 	if ((status = pgetent(line, printer)) < 0)
89413169Sralph 		fatal("can't open printer description file");
89513169Sralph 	else if (status == 0)
89613169Sralph 		fatal("unknown printer");
89712111Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
89812111Sralph 		LP = DEFDEVLP;
89912111Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
90012463Sralph 		RP = DEFLP;
90112111Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
90212111Sralph 		LO = DEFLOCK;
90312111Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
90412111Sralph 		ST = DEFSTAT;
90512111Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
90612111Sralph 		LF = DEFLOGF;
90712111Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
90812111Sralph 		SD = DEFSPOOL;
90912111Sralph 	if ((DU = pgetnum("du")) < 0)
91012111Sralph 		DU = DEFUID;
91112111Sralph 	if ((FF = pgetstr("ff", &bp)) == NULL)
91212111Sralph 		FF = DEFFF;
91312111Sralph 	if ((PW = pgetnum("pw")) < 0)
91412111Sralph 		PW = DEFWIDTH;
91512111Sralph 	sprintf(&width[2], "%d", PW);
91612111Sralph 	if ((PL = pgetnum("pl")) < 0)
91712111Sralph 		PL = DEFLENGTH;
91812111Sralph 	sprintf(&length[2], "%d", PL);
91912463Sralph 	if ((PX = pgetnum("px")) < 0)
92012463Sralph 		PX = 0;
92112463Sralph 	sprintf(&pxwidth[2], "%d", PX);
92212463Sralph 	if ((PY = pgetnum("py")) < 0)
92312463Sralph 		PY = 0;
92412463Sralph 	sprintf(&pxlength[2], "%d", PY);
92512111Sralph 	RM = pgetstr("rm", &bp);
92612111Sralph 	AF = pgetstr("af", &bp);
92712111Sralph 	OF = pgetstr("of", &bp);
92812111Sralph 	IF = pgetstr("if", &bp);
92912463Sralph 	RF = pgetstr("rf", &bp);
93012111Sralph 	TF = pgetstr("tf", &bp);
93113233Sralph 	NF = pgetstr("nf", &bp);
93212111Sralph 	DF = pgetstr("df", &bp);
93312111Sralph 	GF = pgetstr("gf", &bp);
93412111Sralph 	VF = pgetstr("vf", &bp);
93512111Sralph 	CF = pgetstr("cf", &bp);
93612111Sralph 	TR = pgetstr("tr", &bp);
93712463Sralph 	RS = pgetflag("rs");
93812111Sralph 	SF = pgetflag("sf");
93912111Sralph 	SH = pgetflag("sh");
94012111Sralph 	SB = pgetflag("sb");
94112111Sralph 	RW = pgetflag("rw");
94212111Sralph 	BR = pgetnum("br");
94312111Sralph 	if ((FC = pgetnum("fc")) < 0)
94412111Sralph 		FC = 0;
94512111Sralph 	if ((FS = pgetnum("fs")) < 0)
94612111Sralph 		FS = 0;
94712111Sralph 	if ((XC = pgetnum("xc")) < 0)
94812111Sralph 		XC = 0;
94912111Sralph 	if ((XS = pgetnum("xs")) < 0)
95012111Sralph 		XS = 0;
95112581Sralph 	tof = !pgetflag("fo");
95212111Sralph }
95312111Sralph 
95412463Sralph /*
95512463Sralph  * Acquire line printer or remote connection.
95612463Sralph  */
95712877Sralph static
95812463Sralph openpr()
95912463Sralph {
96012463Sralph 	register int i, n;
96112463Sralph 
96212463Sralph 	if (*LP) {
96312463Sralph 		for (i = 1; ; i = i < 32 ? i << 1 : i) {
96413148Ssam 			pfd = open(LP, RW ? O_RDWR : O_WRONLY);
96512463Sralph 			if (pfd >= 0)
96612463Sralph 				break;
96712463Sralph 			if (errno == ENOENT) {
96812463Sralph 				log("cannot open %s", LP);
96912463Sralph 				exit(1);
97012463Sralph 			}
97112463Sralph 			if (i == 1)
97212463Sralph 				status("waiting for %s to become ready (offline ?)", printer);
97312463Sralph 			sleep(i);
97412463Sralph 		}
97512463Sralph 		if (isatty(pfd))
97612463Sralph 			setty();
97712463Sralph 		status("%s is ready and printing", printer);
97812463Sralph 	} else if (RM != NULL) {
97912463Sralph 		for (i = 1; ; i = i < 512 ? i << 1 : i) {
98012528Sralph 			pfd = getport(RM);
98112463Sralph 			if (pfd >= 0) {
98212463Sralph 				(void) sprintf(line, "\2%s\n", RP);
98312463Sralph 				n = strlen(line);
98412463Sralph 				if (write(pfd, line, n) != n)
98512463Sralph 					break;
98612463Sralph 				if (noresponse())
98712463Sralph 					(void) close(pfd);
98812463Sralph 				else
98912463Sralph 					break;
99012463Sralph 			}
99112463Sralph 			if (i == 1)
99212463Sralph 				status("waiting for %s to come up", RM);
99312463Sralph 			sleep(i);
99412463Sralph 		}
99512463Sralph 		status("sending to %s", RM);
99612463Sralph 		remote = 1;
99712463Sralph 	} else {
99812463Sralph 		log("no line printer device or remote machine name");
99912463Sralph 		exit(1);
100012463Sralph 	}
100112463Sralph 	/*
100212463Sralph 	 * Start up an output filter, if needed.
100312463Sralph 	 */
100412463Sralph 	if (OF) {
100512463Sralph 		int p[2];
100612463Sralph 		char *cp;
100712463Sralph 
100812463Sralph 		pipe(p);
100912463Sralph 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
101012463Sralph 			dup2(p[0], 0);		/* pipe is std in */
101112463Sralph 			dup2(pfd, 1);		/* printer is std out */
101212463Sralph 			for (i = 3; i < NOFILE; i++)
101312463Sralph 				(void) close(i);
101412463Sralph 			if ((cp = rindex(OF, '/')) == NULL)
101512463Sralph 				cp = OF;
101612463Sralph 			else
101712463Sralph 				cp++;
101812463Sralph 			execl(OF, cp, width, length, 0);
101912463Sralph 			log("can't execl output filter %s", OF);
102012463Sralph 			exit(1);
102112463Sralph 		}
102212463Sralph 		(void) close(p[0]);		/* close input side */
102312463Sralph 		ofd = p[1];			/* use pipe for output */
102412463Sralph 	} else {
102512463Sralph 		ofd = pfd;
102612463Sralph 		ofilter = 0;
102712463Sralph 	}
102812463Sralph }
102912463Sralph 
103012111Sralph struct bauds {
103112111Sralph 	int	baud;
103212111Sralph 	int	speed;
103312111Sralph } bauds[] = {
103412111Sralph 	50,	B50,
103512111Sralph 	75,	B75,
103612111Sralph 	110,	B110,
103712111Sralph 	134,	B134,
103812111Sralph 	150,	B150,
103912111Sralph 	200,	B200,
104012111Sralph 	300,	B300,
104112111Sralph 	600,	B600,
104212111Sralph 	1200,	B1200,
104312111Sralph 	1800,	B1800,
104412111Sralph 	2400,	B2400,
104512111Sralph 	4800,	B4800,
104612111Sralph 	9600,	B9600,
104712111Sralph 	19200,	EXTA,
104812111Sralph 	38400,	EXTB,
104912111Sralph 	0,	0
105012111Sralph };
105112111Sralph 
105212111Sralph /*
105312111Sralph  * setup tty lines.
105412111Sralph  */
105512877Sralph static
105612111Sralph setty()
105712111Sralph {
105812111Sralph 	struct sgttyb ttybuf;
105912111Sralph 	register struct bauds *bp;
106012111Sralph 
106112111Sralph 	if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
106212111Sralph 		log("cannot set exclusive-use");
106312111Sralph 		exit(1);
106412111Sralph 	}
106512111Sralph 	if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
106612111Sralph 		log("cannot get tty parameters");
106712111Sralph 		exit(1);
106812111Sralph 	}
106912111Sralph 	if (BR > 0) {
107012111Sralph 		for (bp = bauds; bp->baud; bp++)
107112111Sralph 			if (BR == bp->baud)
107212111Sralph 				break;
107312111Sralph 		if (!bp->baud) {
107412111Sralph 			log("illegal baud rate %d", BR);
107512111Sralph 			exit(1);
107612111Sralph 		}
107712111Sralph 		ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
107812111Sralph 	}
107913169Sralph 	ttybuf.sg_flags &= ~FC;
108013169Sralph 	ttybuf.sg_flags |= FS;
108112111Sralph 	if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
108212111Sralph 		log("cannot set tty parameters");
108312111Sralph 		exit(1);
108412111Sralph 	}
108512111Sralph 	if (XC) {
108612111Sralph 		if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
108712111Sralph 			log("cannot set local tty parameters");
108812111Sralph 			exit(1);
108912111Sralph 		}
109012111Sralph 	}
109112111Sralph 	if (XS) {
109212111Sralph 		if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
109312111Sralph 			log("cannot set local tty parameters");
109412111Sralph 			exit(1);
109512111Sralph 		}
109612111Sralph 	}
109712111Sralph }
109812463Sralph 
109912463Sralph /*VARARGS1*/
110012463Sralph static
110112463Sralph status(msg, a1, a2, a3)
110212463Sralph 	char *msg;
110312463Sralph {
110412463Sralph 	register int fd;
110512463Sralph 	char buf[BUFSIZ];
110612463Sralph 
110712463Sralph 	umask(0);
110813148Ssam 	fd = open(ST, O_WRONLY|O_CREAT, 0664);
110913148Ssam 	if (fd < 0 || flock(fd, LOCK_EX) < 0)
111012463Sralph 		fatal("cannot create status file");
111113148Ssam 	ftruncate(fd, 0);
111212463Sralph 	sprintf(buf, msg, a1, a2, a3);
111312463Sralph 	strcat(buf, "\n");
111412463Sralph 	(void) write(fd, buf, strlen(buf));
111512463Sralph 	(void) close(fd);
111612463Sralph }
1117