xref: /csrg-svn/usr.sbin/lpr/lpd/printjob.c (revision 14325)
113954Ssam #ifndef lint
2*14325Sralph static char sccsid[] = "@(#)printjob.c	4.13 (Berkeley) 08/02/83";
313954Ssam #endif
413954Ssam 
512111Sralph /*
612111Sralph  * printjob -- print jobs in the queue.
712111Sralph  *
812111Sralph  *	NOTE: the lock file is used to pass information to lpq and lprm.
912111Sralph  *	it does not need to be removed because file locks are dynamic.
1012111Sralph  */
1112111Sralph 
1212111Sralph #include "lp.h"
1312111Sralph 
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 */
2714150Sralph static int	count;			/* Number of files actually printed */
2812877Sralph static int	remote;			/* true if sending files to remote */
2912111Sralph 
3014150Sralph static char	fromhost[32];		/* user's host machine */
3112877Sralph static char	logname[32];		/* user's login name */
3212877Sralph static char	jobname[32];		/* job or file name */
3312877Sralph static char	class[32];		/* classification field */
3412877Sralph static char	width[10] = "-w";	/* page width in characters */
3512877Sralph static char	length[10] = "-l";	/* page length in lines */
3612877Sralph static char	pxwidth[10] = "-x";	/* page width in pixels */
3712877Sralph static char	pxlength[10] = "-y";	/* page length in pixels */
3812877Sralph static char	indent[10] = "-i0";	/* indentation size in characters */
3912111Sralph 
4012111Sralph printjob()
4112111Sralph {
4212111Sralph 	struct stat stb;
4312111Sralph 	register struct queue *q, **qp;
4412111Sralph 	struct queue **queue;
4512111Sralph 	register int i, nitems;
4612111Sralph 	long pidoff;
4712111Sralph 	extern int onintr();
4812111Sralph 
4912111Sralph 	init();					/* set up capabilities */
5013442Sralph 	(void) write(1, "", 1);			/* ack that daemon is started */
5112877Sralph 	(void) close(1);			/* set up log file */
5212877Sralph 	(void) close(2);
5313148Ssam 	if (open(LF, O_WRONLY|O_APPEND) < 0)
5413148Ssam 		(void) open("/dev/null", O_WRONLY);
5512877Sralph 	dup(1);
5612463Sralph 	pid = getpid();				/* for use with lprm */
5712111Sralph 	setpgrp(0, pid);
5813148Ssam 	signal(SIGINT, onintr);
5912111Sralph 
6012111Sralph 	/*
6112111Sralph 	 * uses short form file names
6212111Sralph 	 */
6312111Sralph 	if (chdir(SD) < 0) {
6412111Sralph 		log("cannot chdir to %s", SD);
6512111Sralph 		exit(1);
6612111Sralph 	}
6712463Sralph 	if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
6812463Sralph 		exit(0);		/* printing disabled */
6914150Sralph 	lfd = open(LO, O_WRONLY|O_CREAT, 0644);
7013169Sralph 	if (lfd < 0) {
7113169Sralph 		log("cannot create %s", LO);
7213169Sralph 		exit(1);
7313169Sralph 	}
7413169Sralph 	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
7512111Sralph 		if (errno == EWOULDBLOCK)	/* active deamon present */
7612111Sralph 			exit(0);
7713169Sralph 		log("cannot lock %s", LO);
7812111Sralph 		exit(1);
7912111Sralph 	}
8013148Ssam 	ftruncate(lfd, 0);
8112111Sralph 	/*
8212111Sralph 	 * write process id for others to know
8312111Sralph 	 */
8412111Sralph 	sprintf(line, "%u\n", pid);
8512111Sralph 	pidoff = i = strlen(line);
8612463Sralph 	if (write(lfd, line, i) != i) {
8712111Sralph 		log("cannot write daemon pid");
8812111Sralph 		exit(1);
8912111Sralph 	}
9012111Sralph 	/*
9112111Sralph 	 * search the spool directory for work and sort by queue order.
9212111Sralph 	 */
9312111Sralph 	if ((nitems = getq(&queue)) < 0) {
9412111Sralph 		log("can't scan spool directory %s", SD);
9512111Sralph 		exit(1);
9612111Sralph 	}
9712463Sralph 	if (nitems == 0)		/* no work to do */
9812111Sralph 		exit(0);
9913169Sralph 	if (stb.st_mode & 01) {		/* reset queue flag */
10013169Sralph 		if (fchmod(lfd, stb.st_mode & 0776) < 0)
10113169Sralph 			log("cannot chmod %s", LO);
10213169Sralph 	}
10312463Sralph 	openpr();			/* open printer or remote */
10412463Sralph again:
10512111Sralph 	/*
10612111Sralph 	 * we found something to do now do it --
10712111Sralph 	 *    write the name of the current control file into the lock file
10812111Sralph 	 *    so the spool queue program can tell what we're working on
10912111Sralph 	 */
11012111Sralph 	for (qp = queue; nitems--; free((char *) q)) {
11112111Sralph 		q = *qp++;
11212111Sralph 		if (stat(q->q_name, &stb) < 0)
11312111Sralph 			continue;
11412463Sralph 	restart:
11512111Sralph 		(void) lseek(lfd, pidoff, 0);
11612111Sralph 		(void) sprintf(line, "%s\n", q->q_name);
11712111Sralph 		i = strlen(line);
11812111Sralph 		if (write(lfd, line, i) != i)
11912111Sralph 			log("can't write (%d) control file name", errno);
12012111Sralph 		if (!remote)
12112111Sralph 			i = printit(q->q_name);
12212111Sralph 		else
12312111Sralph 			i = sendit(q->q_name);
12412463Sralph 		/*
12513169Sralph 		 * Check to see if we are supposed to stop printing or
12613169Sralph 		 * if we are to rebuild the queue.
12712463Sralph 		 */
12813169Sralph 		if (fstat(lfd, &stb) == 0) {
12913169Sralph 			if (stb.st_mode & 0100)
13013169Sralph 				goto done;
13113169Sralph 			if (stb.st_mode & 01) {
13213169Sralph 				for (free((char *) q); nitems--; free((char *) q))
13313169Sralph 					q = *qp++;
13413169Sralph 				if (fchmod(lfd, stb.st_mode & 0776) < 0)
13513169Sralph 					log("cannot chmod %s", LO);
13613169Sralph 				break;
13713169Sralph 			}
13813169Sralph 		}
13914150Sralph 		if (i == 0)		/* file ok and printed */
14014150Sralph 			count++;
14114150Sralph 		else if (i > 0) {	/* try reprinting the job */
14212111Sralph 			log("restarting");
14312111Sralph 			if (ofilter > 0) {
14412111Sralph 				kill(ofilter, SIGCONT);	/* to be sure */
14512111Sralph 				(void) close(ofd);
14612111Sralph 				while ((i = wait(0)) > 0 && i != ofilter)
14712111Sralph 					;
14812111Sralph 				ofilter = 0;
14912111Sralph 			}
15012463Sralph 			(void) close(pfd);	/* close printer */
15112463Sralph 			(void) lseek(lfd, pidoff, 0);
15212463Sralph 			if (write(lfd, "\n", 1) != 1)
15312463Sralph 				log("can't write (%d) control file name", errno);
15412463Sralph 			openpr();		/* try to reopen printer */
15512111Sralph 			goto restart;
15612111Sralph 		}
15712111Sralph 	}
15812111Sralph 	free((char *) queue);
15912463Sralph 	/*
16012463Sralph 	 * search the spool directory for more work.
16112463Sralph 	 */
16212463Sralph 	if ((nitems = getq(&queue)) < 0) {
16312463Sralph 		log("can't scan spool directory %s", SD);
16412463Sralph 		exit(1);
16512463Sralph 	}
16612463Sralph 	if (nitems == 0) {		/* no more work to do */
16712463Sralph 	done:
16814150Sralph 		if (count > 0) {	/* Files actually printed */
16914150Sralph 			if (!SF && !tof)
17014150Sralph 				(void) write(ofd, FF, strlen(FF));
17114150Sralph 			if (TR != NULL)		/* output trailer */
17214150Sralph 				(void) write(ofd, TR, strlen(TR));
17314150Sralph 		}
17412463Sralph 		exit(0);
17512463Sralph 	}
17612111Sralph 	goto again;
17712111Sralph }
17812111Sralph 
17912111Sralph char	fonts[4][50];	/* fonts for troff */
18012111Sralph 
18112111Sralph static char ifonts[4][18] = {
18212111Sralph 	"/usr/lib/vfont/R",
18312111Sralph 	"/usr/lib/vfont/I",
18412111Sralph 	"/usr/lib/vfont/B",
18512111Sralph 	"/usr/lib/vfont/S"
18612111Sralph };
18712111Sralph 
18812111Sralph /*
18912111Sralph  * The remaining part is the reading of the control file (cf)
19012111Sralph  * and performing the various actions.
19112111Sralph  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
19212111Sralph  * -1 if a non-recoverable error occured.
19312111Sralph  */
19412877Sralph static
19512111Sralph printit(file)
19612111Sralph 	char *file;
19712111Sralph {
19812111Sralph 	register int i;
19912111Sralph 	int bombed = 0;
20012111Sralph 
20112111Sralph 	/*
20212111Sralph 	 * open control file
20312111Sralph 	 */
20412111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
20512111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
20612111Sralph 		return(0);
20712111Sralph 	}
20812111Sralph 	/*
20912111Sralph 	 * Reset troff fonts.
21012111Sralph 	 */
21112111Sralph 	for (i = 0; i < 4; i++)
21212111Sralph 		strcpy(fonts[i], ifonts[i]);
21312111Sralph 
21412111Sralph 	/*
21512111Sralph 	 *      read the control file for work to do
21612111Sralph 	 *
21712111Sralph 	 *      file format -- first character in the line is a command
21812111Sralph 	 *      rest of the line is the argument.
21912111Sralph 	 *      valid commands are:
22012111Sralph 	 *
22112111Sralph 	 *		J -- "job name" on banner page
22212111Sralph 	 *		C -- "class name" on banner page
22312111Sralph 	 *              L -- "literal" user's name to print on banner
22412111Sralph 	 *		T -- "title" for pr
22512111Sralph 	 *		H -- "host name" of machine where lpr was done
22612111Sralph 	 *              P -- "person" user's login name
22712581Sralph 	 *              I -- "indent" amount to indent output
22812111Sralph 	 *              f -- "file name" name of text file to print
22912111Sralph 	 *		l -- "file name" text file with control chars
23012111Sralph 	 *		p -- "file name" text file to print with pr(1)
23112111Sralph 	 *		t -- "file name" troff(1) file to print
23213233Sralph 	 *		n -- "file name" ditroff(1) file to print
23312111Sralph 	 *		d -- "file name" dvi file to print
23412111Sralph 	 *		g -- "file name" plot(1G) file to print
23512111Sralph 	 *		v -- "file name" plain raster file to print
23612111Sralph 	 *		c -- "file name" cifplot file to print
23712111Sralph 	 *		1 -- "R font file" for troff
23812111Sralph 	 *		2 -- "I font file" for troff
23912111Sralph 	 *		3 -- "B font file" for troff
24012111Sralph 	 *		4 -- "S font file" for troff
24112111Sralph 	 *		N -- "name" of file (used by lpq)
24212111Sralph 	 *              U -- "unlink" name of file to remove
24312111Sralph 	 *                    (after we print it. (Pass 2 only)).
24412111Sralph 	 *		M -- "mail" to user when done printing
24512111Sralph 	 *
24612111Sralph 	 *      getline reads a line and expands tabs to blanks
24712111Sralph 	 */
24812111Sralph 
24912111Sralph 	/* pass 1 */
25012111Sralph 
25112111Sralph 	while (getline(cfp))
25212111Sralph 		switch (line[0]) {
25312111Sralph 		case 'H':
25414150Sralph 			strcpy(fromhost, line+1);
25512111Sralph 			if (class[0] == '\0')
25612111Sralph 				strcpy(class, line+1);
25712111Sralph 			continue;
25812111Sralph 
25912111Sralph 		case 'P':
26012111Sralph 			strcpy(logname, line+1);
26112463Sralph 			if (RS) {			/* restricted */
26212463Sralph 				if (getpwnam(logname) == (struct passwd *)0) {
26312463Sralph 					bombed = 2;
26412463Sralph 					sendmail(bombed);
26512463Sralph 					goto pass2;
26612463Sralph 				}
26712463Sralph 			}
26812111Sralph 			continue;
26912111Sralph 
27012111Sralph 		case 'J':
27112111Sralph 			if (line[1] != '\0')
27212111Sralph 				strcpy(jobname, line+1);
27312111Sralph 			else
27412111Sralph 				strcpy(jobname, " ");
27512111Sralph 			continue;
27612111Sralph 
27712111Sralph 		case 'C':
27812111Sralph 			if (line[1] != '\0')
27912111Sralph 				strcpy(class, line+1);
28012111Sralph 			else if (class[0] == '\0')
28112111Sralph 				gethostname(class, sizeof (class));
28212111Sralph 			continue;
28312111Sralph 
28412111Sralph 		case 'T':	/* header title for pr */
28512111Sralph 			strcpy(title, line+1);
28612111Sralph 			continue;
28712111Sralph 
28812111Sralph 		case 'L':	/* identification line */
28912111Sralph 			if (!SH)
29012111Sralph 				banner(line+1, jobname);
29112111Sralph 			continue;
29212111Sralph 
29312111Sralph 		case '1':	/* troff fonts */
29412111Sralph 		case '2':
29512111Sralph 		case '3':
29612111Sralph 		case '4':
29712111Sralph 			if (line[1] != '\0')
29812111Sralph 				strcpy(fonts[line[0]-'1'], line+1);
29912111Sralph 			continue;
30012111Sralph 
30112111Sralph 		case 'W':	/* page width */
30212111Sralph 			strcpy(width+2, line+1);
30312111Sralph 			continue;
30412111Sralph 
30512581Sralph 		case 'I':	/* indent amount */
30612581Sralph 			strcpy(indent+2, line+1);
30712581Sralph 			continue;
30812581Sralph 
30912111Sralph 		default:	/* some file to print */
31012111Sralph 			if ((i = print(line[0], line+1)) > 0) {
31112111Sralph 				(void) fclose(cfp);
31212111Sralph 				return(1);
31312111Sralph 			} else if (i < 0)
31412111Sralph 				bombed = 1;
31512111Sralph 			title[0] = '\0';
31612111Sralph 			continue;
31712111Sralph 
31812111Sralph 		case 'N':
31912111Sralph 		case 'U':
32012111Sralph 		case 'M':
32112111Sralph 			continue;
32212111Sralph 		}
32312111Sralph 
32412111Sralph 	/* pass 2 */
32512111Sralph 
32612463Sralph pass2:
32712111Sralph 	fseek(cfp, 0L, 0);
32812111Sralph 	while (getline(cfp))
32912111Sralph 		switch (line[0]) {
33012111Sralph 		case 'M':
33112463Sralph 			if (bombed != 2)		/* already sent if 2 */
33212463Sralph 				sendmail(bombed);
33312111Sralph 			continue;
33412111Sralph 
33512111Sralph 		case 'U':
33612111Sralph 			(void) unlink(line+1);
33712111Sralph 		}
33812111Sralph 	/*
33912111Sralph 	 * clean-up incase another control file exists
34012111Sralph 	 */
34112111Sralph 	(void) fclose(cfp);
34212111Sralph 	(void) unlink(file);
34314150Sralph 	return(bombed ? -1 : 0);
34412111Sralph }
34512111Sralph 
34612111Sralph /*
34712111Sralph  * Print a file.
34813233Sralph  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
34912111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
35012111Sralph  * 0 if all is well.
35112111Sralph  * Note: all filters take stdin as the file, stdout as the printer,
35212111Sralph  * stderr as the log file, and must not ignore SIGINT.
35312111Sralph  */
35412877Sralph static
35512111Sralph print(format, file)
35612111Sralph 	int format;
35712111Sralph 	char *file;
35812111Sralph {
35912111Sralph 	register int n, fi, fo;
36012111Sralph 	register char *prog;
36112111Sralph 	char *av[15], buf[BUFSIZ];
36212111Sralph 	int pid, p[2], stopped = 0;
36312111Sralph 	union wait status;
36412111Sralph 
36513148Ssam 	if ((fi = open(file, O_RDONLY)) < 0) {
36612111Sralph 		log("%s: open failure <errno = %d>", file, errno);
36712111Sralph 		return(-1);
36812111Sralph 	}
36912111Sralph 	if (!SF && !tof) {		/* start on a fresh page */
37012111Sralph 		(void) write(ofd, FF, strlen(FF));
37112111Sralph 		tof = 1;
37212111Sralph 	}
37312111Sralph 	if (IF == NULL && (format == 'f' || format == 'l')) {
37412111Sralph 		tof = 0;
37512111Sralph 		while ((n = read(fi, buf, BUFSIZ)) > 0)
37612111Sralph 			if (write(ofd, buf, n) != n) {
37712111Sralph 				(void) close(fi);
37812111Sralph 				return(1);
37912111Sralph 			}
38012111Sralph 		(void) close(fi);
38112111Sralph 		return(0);
38212111Sralph 	}
38312111Sralph 	switch (format) {
38412111Sralph 	case 'p':	/* print file using 'pr' */
38512111Sralph 		if (IF == NULL) {	/* use output filter */
38612111Sralph 			prog = PR;
38712111Sralph 			av[0] = "pr";
38812111Sralph 			av[1] = width;
38912111Sralph 			av[2] = length;
39012111Sralph 			av[3] = "-h";
39112111Sralph 			av[4] = *title ? title : " ";
39212111Sralph 			av[5] = 0;
39312111Sralph 			fo = ofd;
39412111Sralph 			goto start;
39512111Sralph 		}
39612111Sralph 		pipe(p);
39712111Sralph 		if ((prchild = dofork(DORETURN)) == 0) {	/* child */
39812111Sralph 			dup2(fi, 0);		/* file is stdin */
39912111Sralph 			dup2(p[1], 1);		/* pipe is stdout */
40012111Sralph 			for (n = 3; n < NOFILE; n++)
40112111Sralph 				(void) close(n);
40212111Sralph 			execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
40312111Sralph 			log("cannot execl %s", PR);
40412111Sralph 			exit(2);
40512111Sralph 		}
40612111Sralph 		(void) close(p[1]);		/* close output side */
40712111Sralph 		(void) close(fi);
40812111Sralph 		if (prchild < 0) {
40912111Sralph 			prchild = 0;
41012111Sralph 			(void) close(p[0]);
41112111Sralph 			return(-1);
41212111Sralph 		}
41312111Sralph 		fi = p[0];			/* use pipe for input */
41412111Sralph 	case 'f':	/* print plain text file */
41512111Sralph 		prog = IF;
41612111Sralph 		av[1] = width;
41712111Sralph 		av[2] = length;
41812581Sralph 		av[3] = indent;
41912581Sralph 		n = 4;
42012111Sralph 		break;
42112111Sralph 	case 'l':	/* like 'f' but pass control characters */
42212111Sralph 		prog = IF;
423*14325Sralph 		av[1] = "-c";
42412111Sralph 		av[2] = width;
42512111Sralph 		av[3] = length;
42612581Sralph 		av[4] = indent;
42712581Sralph 		n = 5;
42812111Sralph 		break;
42912463Sralph 	case 'r':	/* print a fortran text file */
43012463Sralph 		prog = RF;
43112463Sralph 		av[1] = width;
43212463Sralph 		av[2] = length;
43312463Sralph 		n = 3;
43412463Sralph 		break;
43512111Sralph 	case 't':	/* print troff output */
43613233Sralph 	case 'n':	/* print ditroff output */
43712463Sralph 	case 'd':	/* print tex output */
43812111Sralph 		(void) unlink(".railmag");
43912463Sralph 		if ((fo = creat(".railmag", FILMOD)) < 0) {
44012111Sralph 			log("cannot create .railmag");
44112111Sralph 			(void) unlink(".railmag");
44212111Sralph 		} else {
44312111Sralph 			for (n = 0; n < 4; n++) {
44412111Sralph 				if (fonts[n][0] != '/')
44512111Sralph 					(void) write(fo, "/usr/lib/vfont/", 15);
44612111Sralph 				(void) write(fo, fonts[n], strlen(fonts[n]));
44712111Sralph 				(void) write(fo, "\n", 1);
44812111Sralph 			}
44912111Sralph 			(void) close(fo);
45012111Sralph 		}
45113233Sralph 		prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
45212463Sralph 		av[1] = pxwidth;
45312463Sralph 		av[2] = pxlength;
45412463Sralph 		n = 3;
45512111Sralph 		break;
45612111Sralph 	case 'c':	/* print cifplot output */
45712111Sralph 		prog = CF;
45812463Sralph 		av[1] = pxwidth;
45912463Sralph 		av[2] = pxlength;
46012463Sralph 		n = 3;
46112111Sralph 		break;
46212111Sralph 	case 'g':	/* print plot(1G) output */
46312111Sralph 		prog = GF;
46412463Sralph 		av[1] = pxwidth;
46512463Sralph 		av[2] = pxlength;
46612463Sralph 		n = 3;
46712111Sralph 		break;
46812111Sralph 	case 'v':	/* print raster output */
46912111Sralph 		prog = VF;
47012463Sralph 		av[1] = pxwidth;
47112463Sralph 		av[2] = pxlength;
47212463Sralph 		n = 3;
47312111Sralph 		break;
47412111Sralph 	default:
47512111Sralph 		(void) close(fi);
47612111Sralph 		log("illegal format character '%c'", format);
47712111Sralph 		return(-1);
47812111Sralph 	}
47912111Sralph 	if ((av[0] = rindex(prog, '/')) != NULL)
48012111Sralph 		av[0]++;
48112111Sralph 	else
48212111Sralph 		av[0] = prog;
48312111Sralph 	av[n++] = "-n";
48412111Sralph 	av[n++] = logname;
48512111Sralph 	av[n++] = "-h";
48614150Sralph 	av[n++] = fromhost;
48712111Sralph 	av[n++] = AF;
48812111Sralph 	av[n] = 0;
48912111Sralph 	fo = pfd;
49012111Sralph 	if (ofilter > 0) {		/* stop output filter */
49112111Sralph 		write(ofd, "\031\1", 2);
49212111Sralph 		while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
49312111Sralph 			;
49412111Sralph 		if (status.w_stopval != WSTOPPED) {
49512111Sralph 			(void) close(fi);
49612111Sralph 			log("output filter died (%d)", status.w_retcode);
49712111Sralph 			return(1);
49812111Sralph 		}
49912111Sralph 		stopped++;
50012111Sralph 	}
50112111Sralph start:
50212111Sralph 	if ((child = dofork(DORETURN)) == 0) {	/* child */
50312111Sralph 		dup2(fi, 0);
50412111Sralph 		dup2(fo, 1);
50512111Sralph 		for (n = 3; n < NOFILE; n++)
50612111Sralph 			(void) close(n);
50712111Sralph 		execv(prog, av);
50812111Sralph 		log("cannot execl %s", prog);
50912111Sralph 		exit(2);
51012111Sralph 	}
51112111Sralph 	(void) close(fi);
51212111Sralph 	if (child < 0)
51312111Sralph 		status.w_retcode = 100;
51412111Sralph 	else
51512111Sralph 		while ((pid = wait(&status)) > 0 && pid != child)
51612111Sralph 			;
51712111Sralph 	child = 0;
51812111Sralph 	prchild = 0;
51912111Sralph 	if (stopped) {		/* restart output filter */
52012111Sralph 		if (kill(ofilter, SIGCONT) < 0) {
52112111Sralph 			log("cannot restart output filter");
52212111Sralph 			exit(1);
52312111Sralph 		}
52412111Sralph 	}
52512111Sralph 	tof = 0;
52612111Sralph 	if (!WIFEXITED(status) || status.w_retcode > 1) {
52712111Sralph 		log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode);
52812111Sralph 		return(-1);
52912111Sralph 	} else if (status.w_retcode == 1)
53012111Sralph 		return(1);
53112111Sralph 	tof = 1;
53212111Sralph 	return(0);
53312111Sralph }
53412111Sralph 
53512111Sralph /*
53612111Sralph  * Send the daemon control file (cf) and any data files.
53712111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
53812111Sralph  * 0 if all is well.
53912111Sralph  */
54012877Sralph static
54112111Sralph sendit(file)
54212111Sralph 	char *file;
54312111Sralph {
54412111Sralph 	register int linelen, err = 0;
54512111Sralph 	char last[132];
54612111Sralph 
54712111Sralph 	/*
54812111Sralph 	 * open control file
54912111Sralph 	 */
55012111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
55112111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
55212111Sralph 		return(0);
55312111Sralph 	}
55412111Sralph 	/*
55512111Sralph 	 *      read the control file for work to do
55612111Sralph 	 *
55712111Sralph 	 *      file format -- first character in the line is a command
55812111Sralph 	 *      rest of the line is the argument.
55912111Sralph 	 *      commands of interest are:
56012111Sralph 	 *
56112111Sralph 	 *            a-z -- "file name" name of file to print
56212111Sralph 	 *              U -- "unlink" name of file to remove
56312111Sralph 	 *                    (after we print it. (Pass 2 only)).
56412111Sralph 	 */
56512111Sralph 
56612111Sralph 	/*
56712111Sralph 	 * pass 1
56812111Sralph 	 */
56912111Sralph 	while (getline(cfp)) {
57012111Sralph 	again:
57112111Sralph 		if (line[0] >= 'a' && line[0] <= 'z') {
57212111Sralph 			strcpy(last, line);
57312111Sralph 			while (linelen = getline(cfp))
57412111Sralph 				if (strcmp(last, line))
57512111Sralph 					break;
57612111Sralph 			if ((err = sendfile('\3', last+1)) > 0) {
57712111Sralph 				(void) fclose(cfp);
57812111Sralph 				return(1);
57912111Sralph 			} else if (err)
58012111Sralph 				break;
58112111Sralph 			if (linelen)
58212111Sralph 				goto again;
58312111Sralph 			break;
58412111Sralph 		}
58512111Sralph 	}
58612111Sralph 	if (!err && sendfile('\2', file) > 0) {
58712111Sralph 		(void) fclose(cfp);
58812111Sralph 		return(1);
58912111Sralph 	}
59012111Sralph 	/*
59112111Sralph 	 * pass 2
59212111Sralph 	 */
59312111Sralph 	fseek(cfp, 0L, 0);
59412111Sralph 	while (getline(cfp))
59512111Sralph 		if (line[0] == 'U')
59612111Sralph 			(void) unlink(line+1);
59712111Sralph 	/*
59812111Sralph 	 * clean-up incase another control file exists
59912111Sralph 	 */
60012111Sralph 	(void) fclose(cfp);
60112111Sralph 	(void) unlink(file);
60212111Sralph 	return(0);
60312111Sralph }
60412111Sralph 
60512111Sralph /*
60612111Sralph  * Send a data file to the remote machine and spool it.
60712111Sralph  * Return positive if we should try resending.
60812111Sralph  */
60912877Sralph static
61012111Sralph sendfile(type, file)
61112111Sralph 	char type, *file;
61212111Sralph {
61312111Sralph 	register int f, i, amt;
61412111Sralph 	struct stat stb;
61512111Sralph 	char buf[BUFSIZ];
61612111Sralph 	int sizerr;
61712111Sralph 
61813148Ssam 	if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) {
61912111Sralph 		log("file (%s) open failure <errno = %d>", file, errno);
62012111Sralph 		return(-1);
62112111Sralph 	}
62212111Sralph 	(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
62312111Sralph 	amt = strlen(buf);
62412692Sralph 	if (write(pfd, buf, amt) != amt) {
62512692Sralph 		(void) close(f);
62612111Sralph 		return(1);
62712692Sralph 	}
62812692Sralph 	if (noresponse()) {
62912692Sralph 		(void) close(f);
63012111Sralph 		return(1);
63112692Sralph 	}
63212111Sralph 	sizerr = 0;
63312111Sralph 	for (i = 0; i < stb.st_size; i += BUFSIZ) {
63412111Sralph 		amt = BUFSIZ;
63512111Sralph 		if (i + amt > stb.st_size)
63612111Sralph 			amt = stb.st_size - i;
63712111Sralph 		if (sizerr == 0 && read(f, buf, amt) != amt)
63812111Sralph 			sizerr = 1;
63912692Sralph 		if (write(pfd, buf, amt) != amt) {
64012692Sralph 			(void) close(f);
64112111Sralph 			return(1);
64212692Sralph 		}
64312111Sralph 	}
64412111Sralph 	(void) close(f);
64512111Sralph 	if (sizerr) {
64612111Sralph 		log("%s: changed size", file);
64712111Sralph 		(void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
64812111Sralph 		return(-1);
64912111Sralph 	}
65012111Sralph 	if (write(pfd, "", 1) != 1)
65112111Sralph 		return(1);
65212111Sralph 	if (noresponse())
65312111Sralph 		return(1);
65412111Sralph 	return(0);
65512111Sralph }
65612111Sralph 
65712111Sralph /*
65812111Sralph  * Check to make sure there have been no errors and that both programs
65912111Sralph  * are in sync with eachother.
66012111Sralph  * Return non-zero if the connection was lost.
66112111Sralph  */
66212111Sralph static
66312111Sralph noresponse()
66412111Sralph {
66512111Sralph 	char resp;
66612111Sralph 
66712111Sralph 	if (read(pfd, &resp, 1) != 1 || resp != '\0') {
66812111Sralph 		log("lost connection or error in recvjob");
66912111Sralph 		return(1);
67012111Sralph 	}
67112111Sralph 	return(0);
67212111Sralph }
67312111Sralph 
67412111Sralph /*
67512111Sralph  * Banner printing stuff
67612111Sralph  */
67712877Sralph static
67812111Sralph banner(name1, name2)
67912111Sralph 	char *name1, *name2;
68012111Sralph {
68112111Sralph 	time_t tvec;
68212111Sralph 	extern char *ctime();
68312111Sralph 
68412111Sralph 	time(&tvec);
68512111Sralph 	if (!SF && !tof)
68612111Sralph 		(void) write(ofd, FF, strlen(FF));
68712111Sralph 	if (SB) {	/* short banner only */
68812111Sralph 		if (class[0]) {
68912111Sralph 			(void) write(ofd, class, strlen(class));
69012111Sralph 			(void) write(ofd, ":", 1);
69112111Sralph 		}
69212111Sralph 		(void) write(ofd, name1, strlen(name1));
69312111Sralph 		(void) write(ofd, "  Job: ", 7);
69412111Sralph 		(void) write(ofd, name2, strlen(name2));
69512111Sralph 		(void) write(ofd, "  Date: ", 8);
69612111Sralph 		(void) write(ofd, ctime(&tvec), 24);
69712111Sralph 		(void) write(ofd, "\n", 1);
69812111Sralph 	} else {	/* normal banner */
69912111Sralph 		(void) write(ofd, "\n\n\n", 3);
70012111Sralph 		scan_out(ofd, name1, '\0');
70112111Sralph 		(void) write(ofd, "\n\n", 2);
70212111Sralph 		scan_out(ofd, name2, '\0');
70312111Sralph 		if (class[0]) {
70412111Sralph 			(void) write(ofd,"\n\n\n",3);
70512111Sralph 			scan_out(ofd, class, '\0');
70612111Sralph 		}
70712111Sralph 		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
70812111Sralph 		(void) write(ofd, name2, strlen(name2));
70912111Sralph 		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
71012111Sralph 		(void) write(ofd, ctime(&tvec), 24);
71112111Sralph 		(void) write(ofd, "\n", 1);
71212111Sralph 	}
71312111Sralph 	if (!SF)
71412111Sralph 		(void) write(ofd, FF, strlen(FF));
71512111Sralph 	tof = 1;
71612111Sralph }
71712111Sralph 
71812877Sralph static char *
71912111Sralph scnline(key, p, c)
72012111Sralph 	register char key, *p;
72112111Sralph 	char c;
72212111Sralph {
72312111Sralph 	register scnwidth;
72412111Sralph 
72512111Sralph 	for (scnwidth = WIDTH; --scnwidth;) {
72612111Sralph 		key <<= 1;
72712111Sralph 		*p++ = key & 0200 ? c : BACKGND;
72812111Sralph 	}
72912111Sralph 	return (p);
73012111Sralph }
73112111Sralph 
73212111Sralph #define TRC(q)	(((q)-' ')&0177)
73312111Sralph 
73412877Sralph static
73512111Sralph scan_out(scfd, scsp, dlm)
73612111Sralph 	int scfd;
73712111Sralph 	char *scsp, dlm;
73812111Sralph {
73912111Sralph 	register char *strp;
74012111Sralph 	register nchrs, j;
74112111Sralph 	char outbuf[LINELEN+1], *sp, c, cc;
74212111Sralph 	int d, scnhgt;
74312111Sralph 	extern char scnkey[][HEIGHT];	/* in lpdchar.c */
74412111Sralph 
74512111Sralph 	for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
74612111Sralph 		strp = &outbuf[0];
74712111Sralph 		sp = scsp;
74812111Sralph 		for (nchrs = 0; ; ) {
74912111Sralph 			d = dropit(c = TRC(cc = *sp++));
75012111Sralph 			if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
75112111Sralph 				for (j = WIDTH; --j;)
75212111Sralph 					*strp++ = BACKGND;
75312111Sralph 			else
75412111Sralph 				strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
75512111Sralph 			if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
75612111Sralph 				break;
75712111Sralph 			*strp++ = BACKGND;
75812111Sralph 			*strp++ = BACKGND;
75912111Sralph 		}
76012111Sralph 		while (*--strp == BACKGND && strp >= outbuf)
76112111Sralph 			;
76212111Sralph 		strp++;
76312111Sralph 		*strp++ = '\n';
76412111Sralph 		(void) write(scfd, outbuf, strp-outbuf);
76512111Sralph 	}
76612111Sralph }
76712111Sralph 
76812877Sralph static
76912111Sralph dropit(c)
77012111Sralph 	char c;
77112111Sralph {
77212111Sralph 	switch(c) {
77312111Sralph 
77412111Sralph 	case TRC('_'):
77512111Sralph 	case TRC(';'):
77612111Sralph 	case TRC(','):
77712111Sralph 	case TRC('g'):
77812111Sralph 	case TRC('j'):
77912111Sralph 	case TRC('p'):
78012111Sralph 	case TRC('q'):
78112111Sralph 	case TRC('y'):
78212111Sralph 		return (DROP);
78312111Sralph 
78412111Sralph 	default:
78512111Sralph 		return (0);
78612111Sralph 	}
78712111Sralph }
78812111Sralph 
78912111Sralph /*
79012111Sralph  * sendmail ---
79112111Sralph  *   tell people about job completion
79212111Sralph  */
79312877Sralph static
79412111Sralph sendmail(bombed)
79512111Sralph 	int bombed;
79612111Sralph {
79712111Sralph 	static int p[2];
79812111Sralph 	register int i;
79912111Sralph 	int stat;
80012111Sralph 	register char *cp;
80112111Sralph 	char buf[100];
80212111Sralph 
80312111Sralph 	pipe(p);
80412111Sralph 	if ((stat = dofork(DORETURN)) == 0) {		/* child */
80512111Sralph 		dup2(p[0], 0);
80612111Sralph 		for (i = 3; i < NOFILE; i++)
80712111Sralph 			(void) close(i);
80812111Sralph 		if ((cp = rindex(MAIL, '/')) != NULL)
80912111Sralph 			cp++;
81012111Sralph 		else
81112111Sralph 			cp = MAIL;
81214150Sralph 		sprintf(buf, "%s@%s", line+1, fromhost);
81312111Sralph 		execl(MAIL, cp, buf, 0);
81412111Sralph 		exit(0);
81512111Sralph 	} else if (stat > 0) {				/* parent */
81612111Sralph 		dup2(p[1], 1);
81714150Sralph 		printf("To: %s@%s\n", line+1, fromhost);
81812111Sralph 		printf("Subject: printer job\n\n");
81912111Sralph 		printf("Your printer job ");
82012111Sralph 		if (*jobname)
82112111Sralph 			printf("(%s) ", jobname);
82212463Sralph 		switch (bombed) {
82312463Sralph 		case 0:
82412463Sralph 			printf("\ncompleted successfully\n");
82512463Sralph 			break;
82612463Sralph 		default:
82712463Sralph 		case 1:
82812463Sralph 			printf("\ncould not be printed\n");
82912463Sralph 			break;
83012463Sralph 		case 2:
83112463Sralph 			printf("\ncould not be printed without an account on %s\n", host);
83212463Sralph 			break;
83312463Sralph 		}
83412111Sralph 		fflush(stdout);
83512111Sralph 		(void) close(1);
83612111Sralph 	}
83712111Sralph 	(void) close(p[0]);
83812111Sralph 	(void) close(p[1]);
83912111Sralph 	wait(&stat);
84012111Sralph }
84112111Sralph 
84212111Sralph /*
84312111Sralph  * dofork - fork with retries on failure
84412111Sralph  */
84512877Sralph static
84612111Sralph dofork(action)
84712111Sralph 	int action;
84812111Sralph {
84912111Sralph 	register int i, pid;
85012111Sralph 
85112111Sralph 	for (i = 0; i < 20; i++) {
85212463Sralph 		if ((pid = fork()) < 0) {
85312111Sralph 			sleep((unsigned)(i*i));
85412463Sralph 			continue;
85512463Sralph 		}
85612463Sralph 		/*
85712463Sralph 		 * Child should run as daemon instead of root
85812463Sralph 		 */
85912463Sralph 		if (pid == 0)
86012463Sralph 			setuid(DU);
86112463Sralph 		return(pid);
86212111Sralph 	}
86312111Sralph 	log("can't fork");
86412111Sralph 
86512111Sralph 	switch (action) {
86612111Sralph 	case DORETURN:
86712111Sralph 		return (-1);
86812111Sralph 	default:
86912111Sralph 		log("bad action (%d) to dofork", action);
87012111Sralph 		/*FALL THRU*/
87112111Sralph 	case DOABORT:
87212111Sralph 		exit(1);
87312111Sralph 	}
87412111Sralph 	/*NOTREACHED*/
87512111Sralph }
87612111Sralph 
87712111Sralph /*
87812111Sralph  * Cleanup child processes when a SIGINT is caught.
87912111Sralph  */
88012877Sralph static
88112111Sralph onintr()
88212111Sralph {
88312111Sralph 	kill(0, SIGINT);
88412111Sralph 	if (ofilter > 0)
88512111Sralph 		kill(ofilter, SIGCONT);
88612111Sralph 	while (wait(0) > 0)
88712111Sralph 		;
88812111Sralph 	exit(0);
88912111Sralph }
89012111Sralph 
89112877Sralph static
89212111Sralph init()
89312111Sralph {
89412111Sralph 	int status;
89512111Sralph 
89613169Sralph 	if ((status = pgetent(line, printer)) < 0)
89713169Sralph 		fatal("can't open printer description file");
89813169Sralph 	else if (status == 0)
89913169Sralph 		fatal("unknown printer");
90012111Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
90112111Sralph 		LP = DEFDEVLP;
90212111Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
90312463Sralph 		RP = DEFLP;
90412111Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
90512111Sralph 		LO = DEFLOCK;
90612111Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
90712111Sralph 		ST = DEFSTAT;
90812111Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
90912111Sralph 		LF = DEFLOGF;
91012111Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
91112111Sralph 		SD = DEFSPOOL;
91212111Sralph 	if ((DU = pgetnum("du")) < 0)
91312111Sralph 		DU = DEFUID;
91412111Sralph 	if ((FF = pgetstr("ff", &bp)) == NULL)
91512111Sralph 		FF = DEFFF;
91612111Sralph 	if ((PW = pgetnum("pw")) < 0)
91712111Sralph 		PW = DEFWIDTH;
91812111Sralph 	sprintf(&width[2], "%d", PW);
91912111Sralph 	if ((PL = pgetnum("pl")) < 0)
92012111Sralph 		PL = DEFLENGTH;
92112111Sralph 	sprintf(&length[2], "%d", PL);
92212463Sralph 	if ((PX = pgetnum("px")) < 0)
92312463Sralph 		PX = 0;
92412463Sralph 	sprintf(&pxwidth[2], "%d", PX);
92512463Sralph 	if ((PY = pgetnum("py")) < 0)
92612463Sralph 		PY = 0;
92712463Sralph 	sprintf(&pxlength[2], "%d", PY);
92812111Sralph 	RM = pgetstr("rm", &bp);
92912111Sralph 	AF = pgetstr("af", &bp);
93012111Sralph 	OF = pgetstr("of", &bp);
93112111Sralph 	IF = pgetstr("if", &bp);
93212463Sralph 	RF = pgetstr("rf", &bp);
93312111Sralph 	TF = pgetstr("tf", &bp);
93413233Sralph 	NF = pgetstr("nf", &bp);
93512111Sralph 	DF = pgetstr("df", &bp);
93612111Sralph 	GF = pgetstr("gf", &bp);
93712111Sralph 	VF = pgetstr("vf", &bp);
93812111Sralph 	CF = pgetstr("cf", &bp);
93912111Sralph 	TR = pgetstr("tr", &bp);
94012463Sralph 	RS = pgetflag("rs");
94112111Sralph 	SF = pgetflag("sf");
94212111Sralph 	SH = pgetflag("sh");
94312111Sralph 	SB = pgetflag("sb");
94412111Sralph 	RW = pgetflag("rw");
94512111Sralph 	BR = pgetnum("br");
94612111Sralph 	if ((FC = pgetnum("fc")) < 0)
94712111Sralph 		FC = 0;
94812111Sralph 	if ((FS = pgetnum("fs")) < 0)
94912111Sralph 		FS = 0;
95012111Sralph 	if ((XC = pgetnum("xc")) < 0)
95112111Sralph 		XC = 0;
95212111Sralph 	if ((XS = pgetnum("xs")) < 0)
95312111Sralph 		XS = 0;
95412581Sralph 	tof = !pgetflag("fo");
95512111Sralph }
95612111Sralph 
95712463Sralph /*
95812463Sralph  * Acquire line printer or remote connection.
95912463Sralph  */
96012877Sralph static
96112463Sralph openpr()
96212463Sralph {
96312463Sralph 	register int i, n;
96412463Sralph 
96512463Sralph 	if (*LP) {
96612463Sralph 		for (i = 1; ; i = i < 32 ? i << 1 : i) {
96713148Ssam 			pfd = open(LP, RW ? O_RDWR : O_WRONLY);
96812463Sralph 			if (pfd >= 0)
96912463Sralph 				break;
97012463Sralph 			if (errno == ENOENT) {
97112463Sralph 				log("cannot open %s", LP);
97212463Sralph 				exit(1);
97312463Sralph 			}
97412463Sralph 			if (i == 1)
97512463Sralph 				status("waiting for %s to become ready (offline ?)", printer);
97612463Sralph 			sleep(i);
97712463Sralph 		}
97812463Sralph 		if (isatty(pfd))
97912463Sralph 			setty();
98012463Sralph 		status("%s is ready and printing", printer);
98112463Sralph 	} else if (RM != NULL) {
98212463Sralph 		for (i = 1; ; i = i < 512 ? i << 1 : i) {
98312528Sralph 			pfd = getport(RM);
98412463Sralph 			if (pfd >= 0) {
98512463Sralph 				(void) sprintf(line, "\2%s\n", RP);
98612463Sralph 				n = strlen(line);
98712463Sralph 				if (write(pfd, line, n) != n)
98812463Sralph 					break;
98912463Sralph 				if (noresponse())
99012463Sralph 					(void) close(pfd);
99112463Sralph 				else
99212463Sralph 					break;
99312463Sralph 			}
99412463Sralph 			if (i == 1)
99512463Sralph 				status("waiting for %s to come up", RM);
99612463Sralph 			sleep(i);
99712463Sralph 		}
99812463Sralph 		status("sending to %s", RM);
99912463Sralph 		remote = 1;
100012463Sralph 	} else {
100112463Sralph 		log("no line printer device or remote machine name");
100212463Sralph 		exit(1);
100312463Sralph 	}
100412463Sralph 	/*
100512463Sralph 	 * Start up an output filter, if needed.
100612463Sralph 	 */
100712463Sralph 	if (OF) {
100812463Sralph 		int p[2];
100912463Sralph 		char *cp;
101012463Sralph 
101112463Sralph 		pipe(p);
101212463Sralph 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
101312463Sralph 			dup2(p[0], 0);		/* pipe is std in */
101412463Sralph 			dup2(pfd, 1);		/* printer is std out */
101512463Sralph 			for (i = 3; i < NOFILE; i++)
101612463Sralph 				(void) close(i);
101712463Sralph 			if ((cp = rindex(OF, '/')) == NULL)
101812463Sralph 				cp = OF;
101912463Sralph 			else
102012463Sralph 				cp++;
102112463Sralph 			execl(OF, cp, width, length, 0);
102212463Sralph 			log("can't execl output filter %s", OF);
102312463Sralph 			exit(1);
102412463Sralph 		}
102512463Sralph 		(void) close(p[0]);		/* close input side */
102612463Sralph 		ofd = p[1];			/* use pipe for output */
102712463Sralph 	} else {
102812463Sralph 		ofd = pfd;
102912463Sralph 		ofilter = 0;
103012463Sralph 	}
103112463Sralph }
103212463Sralph 
103312111Sralph struct bauds {
103412111Sralph 	int	baud;
103512111Sralph 	int	speed;
103612111Sralph } bauds[] = {
103712111Sralph 	50,	B50,
103812111Sralph 	75,	B75,
103912111Sralph 	110,	B110,
104012111Sralph 	134,	B134,
104112111Sralph 	150,	B150,
104212111Sralph 	200,	B200,
104312111Sralph 	300,	B300,
104412111Sralph 	600,	B600,
104512111Sralph 	1200,	B1200,
104612111Sralph 	1800,	B1800,
104712111Sralph 	2400,	B2400,
104812111Sralph 	4800,	B4800,
104912111Sralph 	9600,	B9600,
105012111Sralph 	19200,	EXTA,
105112111Sralph 	38400,	EXTB,
105212111Sralph 	0,	0
105312111Sralph };
105412111Sralph 
105512111Sralph /*
105612111Sralph  * setup tty lines.
105712111Sralph  */
105812877Sralph static
105912111Sralph setty()
106012111Sralph {
106112111Sralph 	struct sgttyb ttybuf;
106212111Sralph 	register struct bauds *bp;
106312111Sralph 
106412111Sralph 	if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
106512111Sralph 		log("cannot set exclusive-use");
106612111Sralph 		exit(1);
106712111Sralph 	}
106812111Sralph 	if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
106912111Sralph 		log("cannot get tty parameters");
107012111Sralph 		exit(1);
107112111Sralph 	}
107212111Sralph 	if (BR > 0) {
107312111Sralph 		for (bp = bauds; bp->baud; bp++)
107412111Sralph 			if (BR == bp->baud)
107512111Sralph 				break;
107612111Sralph 		if (!bp->baud) {
107712111Sralph 			log("illegal baud rate %d", BR);
107812111Sralph 			exit(1);
107912111Sralph 		}
108012111Sralph 		ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
108112111Sralph 	}
108213169Sralph 	ttybuf.sg_flags &= ~FC;
108313169Sralph 	ttybuf.sg_flags |= FS;
108412111Sralph 	if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
108512111Sralph 		log("cannot set tty parameters");
108612111Sralph 		exit(1);
108712111Sralph 	}
108812111Sralph 	if (XC) {
108912111Sralph 		if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
109012111Sralph 			log("cannot set local tty parameters");
109112111Sralph 			exit(1);
109212111Sralph 		}
109312111Sralph 	}
109412111Sralph 	if (XS) {
109512111Sralph 		if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
109612111Sralph 			log("cannot set local tty parameters");
109712111Sralph 			exit(1);
109812111Sralph 		}
109912111Sralph 	}
110012111Sralph }
110112463Sralph 
110212463Sralph /*VARARGS1*/
110312463Sralph static
110412463Sralph status(msg, a1, a2, a3)
110512463Sralph 	char *msg;
110612463Sralph {
110712463Sralph 	register int fd;
110812463Sralph 	char buf[BUFSIZ];
110912463Sralph 
111012463Sralph 	umask(0);
111113148Ssam 	fd = open(ST, O_WRONLY|O_CREAT, 0664);
111213148Ssam 	if (fd < 0 || flock(fd, LOCK_EX) < 0)
111312463Sralph 		fatal("cannot create status file");
111413148Ssam 	ftruncate(fd, 0);
111512463Sralph 	sprintf(buf, msg, a1, a2, a3);
111612463Sralph 	strcat(buf, "\n");
111712463Sralph 	(void) write(fd, buf, strlen(buf));
111812463Sralph 	(void) close(fd);
111912463Sralph }
1120