xref: /csrg-svn/usr.sbin/lpr/lpd/printjob.c (revision 13169)
1*13169Sralph /*	printjob.c	4.8	83/06/17	*/
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 */
63*13169Sralph 	lfd = open(LO, O_WRONLY|O_CREAT|O_TRUNC, 0644);
64*13169Sralph 	if (lfd < 0) {
65*13169Sralph 		log("cannot create %s", LO);
66*13169Sralph 		exit(1);
67*13169Sralph 	}
68*13169Sralph 	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
6912111Sralph 		if (errno == EWOULDBLOCK)	/* active deamon present */
7012111Sralph 			exit(0);
71*13169Sralph 		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);
93*13169Sralph 	if (stb.st_mode & 01) {		/* reset queue flag */
94*13169Sralph 		if (fchmod(lfd, stb.st_mode & 0776) < 0)
95*13169Sralph 			log("cannot chmod %s", LO);
96*13169Sralph 	}
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 		/*
119*13169Sralph 		 * Check to see if we are supposed to stop printing or
120*13169Sralph 		 * if we are to rebuild the queue.
12112463Sralph 		 */
122*13169Sralph 		if (fstat(lfd, &stb) == 0) {
123*13169Sralph 			if (stb.st_mode & 0100)
124*13169Sralph 				goto done;
125*13169Sralph 			if (stb.st_mode & 01) {
126*13169Sralph 				for (free((char *) q); nitems--; free((char *) q))
127*13169Sralph 					q = *qp++;
128*13169Sralph 				if (fchmod(lfd, stb.st_mode & 0776) < 0)
129*13169Sralph 					log("cannot chmod %s", LO);
130*13169Sralph 				break;
131*13169Sralph 			}
132*13169Sralph 		}
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
22512111Sralph 	 *		d -- "file name" dvi file to print
22612111Sralph 	 *		g -- "file name" plot(1G) file to print
22712111Sralph 	 *		v -- "file name" plain raster file to print
22812111Sralph 	 *		c -- "file name" cifplot file to print
22912111Sralph 	 *		1 -- "R font file" for troff
23012111Sralph 	 *		2 -- "I font file" for troff
23112111Sralph 	 *		3 -- "B font file" for troff
23212111Sralph 	 *		4 -- "S font file" for troff
23312111Sralph 	 *		N -- "name" of file (used by lpq)
23412111Sralph 	 *              U -- "unlink" name of file to remove
23512111Sralph 	 *                    (after we print it. (Pass 2 only)).
23612111Sralph 	 *		M -- "mail" to user when done printing
23712111Sralph 	 *
23812111Sralph 	 *      getline reads a line and expands tabs to blanks
23912111Sralph 	 */
24012111Sralph 
24112111Sralph 	/* pass 1 */
24212111Sralph 
24312111Sralph 	while (getline(cfp))
24412111Sralph 		switch (line[0]) {
24512111Sralph 		case 'H':
24612111Sralph 			strcpy(host, line+1);
24712111Sralph 			if (class[0] == '\0')
24812111Sralph 				strcpy(class, line+1);
24912111Sralph 			continue;
25012111Sralph 
25112111Sralph 		case 'P':
25212111Sralph 			strcpy(logname, line+1);
25312463Sralph 			if (RS) {			/* restricted */
25412463Sralph 				if (getpwnam(logname) == (struct passwd *)0) {
25512463Sralph 					bombed = 2;
25612463Sralph 					sendmail(bombed);
25712463Sralph 					goto pass2;
25812463Sralph 				}
25912463Sralph 			}
26012111Sralph 			continue;
26112111Sralph 
26212111Sralph 		case 'J':
26312111Sralph 			if (line[1] != '\0')
26412111Sralph 				strcpy(jobname, line+1);
26512111Sralph 			else
26612111Sralph 				strcpy(jobname, " ");
26712111Sralph 			continue;
26812111Sralph 
26912111Sralph 		case 'C':
27012111Sralph 			if (line[1] != '\0')
27112111Sralph 				strcpy(class, line+1);
27212111Sralph 			else if (class[0] == '\0')
27312111Sralph 				gethostname(class, sizeof (class));
27412111Sralph 			continue;
27512111Sralph 
27612111Sralph 		case 'T':	/* header title for pr */
27712111Sralph 			strcpy(title, line+1);
27812111Sralph 			continue;
27912111Sralph 
28012111Sralph 		case 'L':	/* identification line */
28112111Sralph 			if (!SH)
28212111Sralph 				banner(line+1, jobname);
28312111Sralph 			continue;
28412111Sralph 
28512111Sralph 		case '1':	/* troff fonts */
28612111Sralph 		case '2':
28712111Sralph 		case '3':
28812111Sralph 		case '4':
28912111Sralph 			if (line[1] != '\0')
29012111Sralph 				strcpy(fonts[line[0]-'1'], line+1);
29112111Sralph 			continue;
29212111Sralph 
29312111Sralph 		case 'W':	/* page width */
29412111Sralph 			strcpy(width+2, line+1);
29512111Sralph 			continue;
29612111Sralph 
29712581Sralph 		case 'I':	/* indent amount */
29812581Sralph 			strcpy(indent+2, line+1);
29912581Sralph 			continue;
30012581Sralph 
30112111Sralph 		default:	/* some file to print */
30212111Sralph 			if ((i = print(line[0], line+1)) > 0) {
30312111Sralph 				(void) fclose(cfp);
30412111Sralph 				return(1);
30512111Sralph 			} else if (i < 0)
30612111Sralph 				bombed = 1;
30712111Sralph 			title[0] = '\0';
30812111Sralph 			continue;
30912111Sralph 
31012111Sralph 		case 'N':
31112111Sralph 		case 'U':
31212111Sralph 		case 'M':
31312111Sralph 			continue;
31412111Sralph 		}
31512111Sralph 
31612111Sralph 	/* pass 2 */
31712111Sralph 
31812463Sralph pass2:
31912111Sralph 	fseek(cfp, 0L, 0);
32012111Sralph 	while (getline(cfp))
32112111Sralph 		switch (line[0]) {
32212111Sralph 		case 'M':
32312463Sralph 			if (bombed != 2)		/* already sent if 2 */
32412463Sralph 				sendmail(bombed);
32512111Sralph 			continue;
32612111Sralph 
32712111Sralph 		case 'U':
32812111Sralph 			(void) unlink(line+1);
32912111Sralph 		}
33012111Sralph 	/*
33112111Sralph 	 * clean-up incase another control file exists
33212111Sralph 	 */
33312111Sralph 	(void) fclose(cfp);
33412111Sralph 	(void) unlink(file);
33512111Sralph 	return(0);
33612111Sralph }
33712111Sralph 
33812111Sralph /*
33912111Sralph  * Print a file.
34012111Sralph  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, TF, CF, VF}.
34112111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
34212111Sralph  * 0 if all is well.
34312111Sralph  * Note: all filters take stdin as the file, stdout as the printer,
34412111Sralph  * stderr as the log file, and must not ignore SIGINT.
34512111Sralph  */
34612877Sralph static
34712111Sralph print(format, file)
34812111Sralph 	int format;
34912111Sralph 	char *file;
35012111Sralph {
35112111Sralph 	register int n, fi, fo;
35212111Sralph 	register char *prog;
35312111Sralph 	char *av[15], buf[BUFSIZ];
35412111Sralph 	int pid, p[2], stopped = 0;
35512111Sralph 	union wait status;
35612111Sralph 
35713148Ssam 	if ((fi = open(file, O_RDONLY)) < 0) {
35812111Sralph 		log("%s: open failure <errno = %d>", file, errno);
35912111Sralph 		return(-1);
36012111Sralph 	}
36112111Sralph 	if (!SF && !tof) {		/* start on a fresh page */
36212111Sralph 		(void) write(ofd, FF, strlen(FF));
36312111Sralph 		tof = 1;
36412111Sralph 	}
36512111Sralph 	if (IF == NULL && (format == 'f' || format == 'l')) {
36612111Sralph 		tof = 0;
36712111Sralph 		while ((n = read(fi, buf, BUFSIZ)) > 0)
36812111Sralph 			if (write(ofd, buf, n) != n) {
36912111Sralph 				(void) close(fi);
37012111Sralph 				return(1);
37112111Sralph 			}
37212111Sralph 		(void) close(fi);
37312111Sralph 		return(0);
37412111Sralph 	}
37512111Sralph 	switch (format) {
37612111Sralph 	case 'p':	/* print file using 'pr' */
37712111Sralph 		if (IF == NULL) {	/* use output filter */
37812111Sralph 			prog = PR;
37912111Sralph 			av[0] = "pr";
38012111Sralph 			av[1] = width;
38112111Sralph 			av[2] = length;
38212111Sralph 			av[3] = "-h";
38312111Sralph 			av[4] = *title ? title : " ";
38412111Sralph 			av[5] = 0;
38512111Sralph 			fo = ofd;
38612111Sralph 			goto start;
38712111Sralph 		}
38812111Sralph 		pipe(p);
38912111Sralph 		if ((prchild = dofork(DORETURN)) == 0) {	/* child */
39012111Sralph 			dup2(fi, 0);		/* file is stdin */
39112111Sralph 			dup2(p[1], 1);		/* pipe is stdout */
39212111Sralph 			for (n = 3; n < NOFILE; n++)
39312111Sralph 				(void) close(n);
39412111Sralph 			execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
39512111Sralph 			log("cannot execl %s", PR);
39612111Sralph 			exit(2);
39712111Sralph 		}
39812111Sralph 		(void) close(p[1]);		/* close output side */
39912111Sralph 		(void) close(fi);
40012111Sralph 		if (prchild < 0) {
40112111Sralph 			prchild = 0;
40212111Sralph 			(void) close(p[0]);
40312111Sralph 			return(-1);
40412111Sralph 		}
40512111Sralph 		fi = p[0];			/* use pipe for input */
40612111Sralph 	case 'f':	/* print plain text file */
40712111Sralph 		prog = IF;
40812111Sralph 		av[1] = width;
40912111Sralph 		av[2] = length;
41012581Sralph 		av[3] = indent;
41112581Sralph 		n = 4;
41212111Sralph 		break;
41312111Sralph 	case 'l':	/* like 'f' but pass control characters */
41412111Sralph 		prog = IF;
41512111Sralph 		av[1] = "-l";
41612111Sralph 		av[2] = width;
41712111Sralph 		av[3] = length;
41812581Sralph 		av[4] = indent;
41912581Sralph 		n = 5;
42012111Sralph 		break;
42112463Sralph 	case 'r':	/* print a fortran text file */
42212463Sralph 		prog = RF;
42312463Sralph 		av[1] = width;
42412463Sralph 		av[2] = length;
42512463Sralph 		n = 3;
42612463Sralph 		break;
42712111Sralph 	case 't':	/* print troff output */
42812463Sralph 	case 'd':	/* print tex output */
42912111Sralph 		(void) unlink(".railmag");
43012463Sralph 		if ((fo = creat(".railmag", FILMOD)) < 0) {
43112111Sralph 			log("cannot create .railmag");
43212111Sralph 			(void) unlink(".railmag");
43312111Sralph 		} else {
43412111Sralph 			for (n = 0; n < 4; n++) {
43512111Sralph 				if (fonts[n][0] != '/')
43612111Sralph 					(void) write(fo, "/usr/lib/vfont/", 15);
43712111Sralph 				(void) write(fo, fonts[n], strlen(fonts[n]));
43812111Sralph 				(void) write(fo, "\n", 1);
43912111Sralph 			}
44012111Sralph 			(void) close(fo);
44112111Sralph 		}
44212111Sralph 		prog = (format == 't') ? TF : DF;
44312463Sralph 		av[1] = pxwidth;
44412463Sralph 		av[2] = pxlength;
44512463Sralph 		n = 3;
44612111Sralph 		break;
44712111Sralph 	case 'c':	/* print cifplot output */
44812111Sralph 		prog = CF;
44912463Sralph 		av[1] = pxwidth;
45012463Sralph 		av[2] = pxlength;
45112463Sralph 		n = 3;
45212111Sralph 		break;
45312111Sralph 	case 'g':	/* print plot(1G) output */
45412111Sralph 		prog = GF;
45512463Sralph 		av[1] = pxwidth;
45612463Sralph 		av[2] = pxlength;
45712463Sralph 		n = 3;
45812111Sralph 		break;
45912111Sralph 	case 'v':	/* print raster output */
46012111Sralph 		prog = VF;
46112463Sralph 		av[1] = pxwidth;
46212463Sralph 		av[2] = pxlength;
46312463Sralph 		n = 3;
46412111Sralph 		break;
46512111Sralph 	default:
46612111Sralph 		(void) close(fi);
46712111Sralph 		log("illegal format character '%c'", format);
46812111Sralph 		return(-1);
46912111Sralph 	}
47012111Sralph 	if ((av[0] = rindex(prog, '/')) != NULL)
47112111Sralph 		av[0]++;
47212111Sralph 	else
47312111Sralph 		av[0] = prog;
47412111Sralph 	av[n++] = "-n";
47512111Sralph 	av[n++] = logname;
47612111Sralph 	av[n++] = "-h";
47712111Sralph 	av[n++] = host;
47812111Sralph 	av[n++] = AF;
47912111Sralph 	av[n] = 0;
48012111Sralph 	fo = pfd;
48112111Sralph 	if (ofilter > 0) {		/* stop output filter */
48212111Sralph 		write(ofd, "\031\1", 2);
48312111Sralph 		while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
48412111Sralph 			;
48512111Sralph 		if (status.w_stopval != WSTOPPED) {
48612111Sralph 			(void) close(fi);
48712111Sralph 			log("output filter died (%d)", status.w_retcode);
48812111Sralph 			return(1);
48912111Sralph 		}
49012111Sralph 		stopped++;
49112111Sralph 	}
49212111Sralph start:
49312111Sralph 	if ((child = dofork(DORETURN)) == 0) {	/* child */
49412111Sralph 		dup2(fi, 0);
49512111Sralph 		dup2(fo, 1);
49612111Sralph 		for (n = 3; n < NOFILE; n++)
49712111Sralph 			(void) close(n);
49812111Sralph 		execv(prog, av);
49912111Sralph 		log("cannot execl %s", prog);
50012111Sralph 		exit(2);
50112111Sralph 	}
50212111Sralph 	(void) close(fi);
50312111Sralph 	if (child < 0)
50412111Sralph 		status.w_retcode = 100;
50512111Sralph 	else
50612111Sralph 		while ((pid = wait(&status)) > 0 && pid != child)
50712111Sralph 			;
50812111Sralph 	child = 0;
50912111Sralph 	prchild = 0;
51012111Sralph 	if (stopped) {		/* restart output filter */
51112111Sralph 		if (kill(ofilter, SIGCONT) < 0) {
51212111Sralph 			log("cannot restart output filter");
51312111Sralph 			exit(1);
51412111Sralph 		}
51512111Sralph 	}
51612111Sralph 	tof = 0;
51712111Sralph 	if (!WIFEXITED(status) || status.w_retcode > 1) {
51812111Sralph 		log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode);
51912111Sralph 		return(-1);
52012111Sralph 	} else if (status.w_retcode == 1)
52112111Sralph 		return(1);
52212111Sralph 	tof = 1;
52312111Sralph 	return(0);
52412111Sralph }
52512111Sralph 
52612111Sralph /*
52712111Sralph  * Send the daemon control file (cf) and any data files.
52812111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
52912111Sralph  * 0 if all is well.
53012111Sralph  */
53112877Sralph static
53212111Sralph sendit(file)
53312111Sralph 	char *file;
53412111Sralph {
53512111Sralph 	register int linelen, err = 0;
53612111Sralph 	char last[132];
53712111Sralph 
53812111Sralph 	/*
53912111Sralph 	 * open control file
54012111Sralph 	 */
54112111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
54212111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
54312111Sralph 		return(0);
54412111Sralph 	}
54512111Sralph 	/*
54612111Sralph 	 *      read the control file for work to do
54712111Sralph 	 *
54812111Sralph 	 *      file format -- first character in the line is a command
54912111Sralph 	 *      rest of the line is the argument.
55012111Sralph 	 *      commands of interest are:
55112111Sralph 	 *
55212111Sralph 	 *            a-z -- "file name" name of file to print
55312111Sralph 	 *              U -- "unlink" name of file to remove
55412111Sralph 	 *                    (after we print it. (Pass 2 only)).
55512111Sralph 	 */
55612111Sralph 
55712111Sralph 	/*
55812111Sralph 	 * pass 1
55912111Sralph 	 */
56012111Sralph 	while (getline(cfp)) {
56112111Sralph 	again:
56212111Sralph 		if (line[0] >= 'a' && line[0] <= 'z') {
56312111Sralph 			strcpy(last, line);
56412111Sralph 			while (linelen = getline(cfp))
56512111Sralph 				if (strcmp(last, line))
56612111Sralph 					break;
56712111Sralph 			if ((err = sendfile('\3', last+1)) > 0) {
56812111Sralph 				(void) fclose(cfp);
56912111Sralph 				return(1);
57012111Sralph 			} else if (err)
57112111Sralph 				break;
57212111Sralph 			if (linelen)
57312111Sralph 				goto again;
57412111Sralph 			break;
57512111Sralph 		}
57612111Sralph 	}
57712111Sralph 	if (!err && sendfile('\2', file) > 0) {
57812111Sralph 		(void) fclose(cfp);
57912111Sralph 		return(1);
58012111Sralph 	}
58112111Sralph 	/*
58212111Sralph 	 * pass 2
58312111Sralph 	 */
58412111Sralph 	fseek(cfp, 0L, 0);
58512111Sralph 	while (getline(cfp))
58612111Sralph 		if (line[0] == 'U')
58712111Sralph 			(void) unlink(line+1);
58812111Sralph 	/*
58912111Sralph 	 * clean-up incase another control file exists
59012111Sralph 	 */
59112111Sralph 	(void) fclose(cfp);
59212111Sralph 	(void) unlink(file);
59312111Sralph 	return(0);
59412111Sralph }
59512111Sralph 
59612111Sralph /*
59712111Sralph  * Send a data file to the remote machine and spool it.
59812111Sralph  * Return positive if we should try resending.
59912111Sralph  */
60012877Sralph static
60112111Sralph sendfile(type, file)
60212111Sralph 	char type, *file;
60312111Sralph {
60412111Sralph 	register int f, i, amt;
60512111Sralph 	struct stat stb;
60612111Sralph 	char buf[BUFSIZ];
60712111Sralph 	int sizerr;
60812111Sralph 
60913148Ssam 	if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) {
61012111Sralph 		log("file (%s) open failure <errno = %d>", file, errno);
61112111Sralph 		return(-1);
61212111Sralph 	}
61312111Sralph 	(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
61412111Sralph 	amt = strlen(buf);
61512692Sralph 	if (write(pfd, buf, amt) != amt) {
61612692Sralph 		(void) close(f);
61712111Sralph 		return(1);
61812692Sralph 	}
61912692Sralph 	if (noresponse()) {
62012692Sralph 		(void) close(f);
62112111Sralph 		return(1);
62212692Sralph 	}
62312111Sralph 	sizerr = 0;
62412111Sralph 	for (i = 0; i < stb.st_size; i += BUFSIZ) {
62512111Sralph 		amt = BUFSIZ;
62612111Sralph 		if (i + amt > stb.st_size)
62712111Sralph 			amt = stb.st_size - i;
62812111Sralph 		if (sizerr == 0 && read(f, buf, amt) != amt)
62912111Sralph 			sizerr = 1;
63012692Sralph 		if (write(pfd, buf, amt) != amt) {
63112692Sralph 			(void) close(f);
63212111Sralph 			return(1);
63312692Sralph 		}
63412111Sralph 	}
63512111Sralph 	(void) close(f);
63612111Sralph 	if (sizerr) {
63712111Sralph 		log("%s: changed size", file);
63812111Sralph 		(void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
63912111Sralph 		return(-1);
64012111Sralph 	}
64112111Sralph 	if (write(pfd, "", 1) != 1)
64212111Sralph 		return(1);
64312111Sralph 	if (noresponse())
64412111Sralph 		return(1);
64512111Sralph 	return(0);
64612111Sralph }
64712111Sralph 
64812111Sralph /*
64912111Sralph  * Check to make sure there have been no errors and that both programs
65012111Sralph  * are in sync with eachother.
65112111Sralph  * Return non-zero if the connection was lost.
65212111Sralph  */
65312111Sralph static
65412111Sralph noresponse()
65512111Sralph {
65612111Sralph 	char resp;
65712111Sralph 
65812111Sralph 	if (read(pfd, &resp, 1) != 1 || resp != '\0') {
65912111Sralph 		log("lost connection or error in recvjob");
66012111Sralph 		return(1);
66112111Sralph 	}
66212111Sralph 	return(0);
66312111Sralph }
66412111Sralph 
66512111Sralph /*
66612111Sralph  * Banner printing stuff
66712111Sralph  */
66812877Sralph static
66912111Sralph banner(name1, name2)
67012111Sralph 	char *name1, *name2;
67112111Sralph {
67212111Sralph 	time_t tvec;
67312111Sralph 	extern char *ctime();
67412111Sralph 
67512111Sralph 	time(&tvec);
67612111Sralph 	if (!SF && !tof)
67712111Sralph 		(void) write(ofd, FF, strlen(FF));
67812111Sralph 	if (SB) {	/* short banner only */
67912111Sralph 		if (class[0]) {
68012111Sralph 			(void) write(ofd, class, strlen(class));
68112111Sralph 			(void) write(ofd, ":", 1);
68212111Sralph 		}
68312111Sralph 		(void) write(ofd, name1, strlen(name1));
68412111Sralph 		(void) write(ofd, "  Job: ", 7);
68512111Sralph 		(void) write(ofd, name2, strlen(name2));
68612111Sralph 		(void) write(ofd, "  Date: ", 8);
68712111Sralph 		(void) write(ofd, ctime(&tvec), 24);
68812111Sralph 		(void) write(ofd, "\n", 1);
68912111Sralph 	} else {	/* normal banner */
69012111Sralph 		(void) write(ofd, "\n\n\n", 3);
69112111Sralph 		scan_out(ofd, name1, '\0');
69212111Sralph 		(void) write(ofd, "\n\n", 2);
69312111Sralph 		scan_out(ofd, name2, '\0');
69412111Sralph 		if (class[0]) {
69512111Sralph 			(void) write(ofd,"\n\n\n",3);
69612111Sralph 			scan_out(ofd, class, '\0');
69712111Sralph 		}
69812111Sralph 		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
69912111Sralph 		(void) write(ofd, name2, strlen(name2));
70012111Sralph 		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
70112111Sralph 		(void) write(ofd, ctime(&tvec), 24);
70212111Sralph 		(void) write(ofd, "\n", 1);
70312111Sralph 	}
70412111Sralph 	if (!SF)
70512111Sralph 		(void) write(ofd, FF, strlen(FF));
70612111Sralph 	tof = 1;
70712111Sralph }
70812111Sralph 
70912877Sralph static char *
71012111Sralph scnline(key, p, c)
71112111Sralph 	register char key, *p;
71212111Sralph 	char c;
71312111Sralph {
71412111Sralph 	register scnwidth;
71512111Sralph 
71612111Sralph 	for (scnwidth = WIDTH; --scnwidth;) {
71712111Sralph 		key <<= 1;
71812111Sralph 		*p++ = key & 0200 ? c : BACKGND;
71912111Sralph 	}
72012111Sralph 	return (p);
72112111Sralph }
72212111Sralph 
72312111Sralph #define TRC(q)	(((q)-' ')&0177)
72412111Sralph 
72512877Sralph static
72612111Sralph scan_out(scfd, scsp, dlm)
72712111Sralph 	int scfd;
72812111Sralph 	char *scsp, dlm;
72912111Sralph {
73012111Sralph 	register char *strp;
73112111Sralph 	register nchrs, j;
73212111Sralph 	char outbuf[LINELEN+1], *sp, c, cc;
73312111Sralph 	int d, scnhgt;
73412111Sralph 	extern char scnkey[][HEIGHT];	/* in lpdchar.c */
73512111Sralph 
73612111Sralph 	for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
73712111Sralph 		strp = &outbuf[0];
73812111Sralph 		sp = scsp;
73912111Sralph 		for (nchrs = 0; ; ) {
74012111Sralph 			d = dropit(c = TRC(cc = *sp++));
74112111Sralph 			if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
74212111Sralph 				for (j = WIDTH; --j;)
74312111Sralph 					*strp++ = BACKGND;
74412111Sralph 			else
74512111Sralph 				strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
74612111Sralph 			if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
74712111Sralph 				break;
74812111Sralph 			*strp++ = BACKGND;
74912111Sralph 			*strp++ = BACKGND;
75012111Sralph 		}
75112111Sralph 		while (*--strp == BACKGND && strp >= outbuf)
75212111Sralph 			;
75312111Sralph 		strp++;
75412111Sralph 		*strp++ = '\n';
75512111Sralph 		(void) write(scfd, outbuf, strp-outbuf);
75612111Sralph 	}
75712111Sralph }
75812111Sralph 
75912877Sralph static
76012111Sralph dropit(c)
76112111Sralph 	char c;
76212111Sralph {
76312111Sralph 	switch(c) {
76412111Sralph 
76512111Sralph 	case TRC('_'):
76612111Sralph 	case TRC(';'):
76712111Sralph 	case TRC(','):
76812111Sralph 	case TRC('g'):
76912111Sralph 	case TRC('j'):
77012111Sralph 	case TRC('p'):
77112111Sralph 	case TRC('q'):
77212111Sralph 	case TRC('y'):
77312111Sralph 		return (DROP);
77412111Sralph 
77512111Sralph 	default:
77612111Sralph 		return (0);
77712111Sralph 	}
77812111Sralph }
77912111Sralph 
78012111Sralph /*
78112111Sralph  * sendmail ---
78212111Sralph  *   tell people about job completion
78312111Sralph  */
78412877Sralph static
78512111Sralph sendmail(bombed)
78612111Sralph 	int bombed;
78712111Sralph {
78812111Sralph 	static int p[2];
78912111Sralph 	register int i;
79012111Sralph 	int stat;
79112111Sralph 	register char *cp;
79212111Sralph 	char buf[100];
79312111Sralph 
79412111Sralph 	pipe(p);
79512111Sralph 	if ((stat = dofork(DORETURN)) == 0) {		/* child */
79612111Sralph 		dup2(p[0], 0);
79712111Sralph 		for (i = 3; i < NOFILE; i++)
79812111Sralph 			(void) close(i);
79912111Sralph 		if ((cp = rindex(MAIL, '/')) != NULL)
80012111Sralph 			cp++;
80112111Sralph 		else
80212111Sralph 			cp = MAIL;
80312111Sralph 		sprintf(buf, "%s@%s", line+1, host);
80412111Sralph 		execl(MAIL, cp, buf, 0);
80512111Sralph 		exit(0);
80612111Sralph 	} else if (stat > 0) {				/* parent */
80712111Sralph 		dup2(p[1], 1);
80812111Sralph 		printf("To: %s\n", line+1);
80912111Sralph 		printf("Subject: printer job\n\n");
81012111Sralph 		printf("Your printer job ");
81112111Sralph 		if (*jobname)
81212111Sralph 			printf("(%s) ", jobname);
81312463Sralph 		switch (bombed) {
81412463Sralph 		case 0:
81512463Sralph 			printf("\ncompleted successfully\n");
81612463Sralph 			break;
81712463Sralph 		default:
81812463Sralph 		case 1:
81912463Sralph 			printf("\ncould not be printed\n");
82012463Sralph 			break;
82112463Sralph 		case 2:
82212463Sralph 			printf("\ncould not be printed without an account on %s\n", host);
82312463Sralph 			break;
82412463Sralph 		}
82512111Sralph 		fflush(stdout);
82612111Sralph 		(void) close(1);
82712111Sralph 	}
82812111Sralph 	(void) close(p[0]);
82912111Sralph 	(void) close(p[1]);
83012111Sralph 	wait(&stat);
83112111Sralph }
83212111Sralph 
83312111Sralph /*
83412111Sralph  * dofork - fork with retries on failure
83512111Sralph  */
83612877Sralph static
83712111Sralph dofork(action)
83812111Sralph 	int action;
83912111Sralph {
84012111Sralph 	register int i, pid;
84112111Sralph 
84212111Sralph 	for (i = 0; i < 20; i++) {
84312463Sralph 		if ((pid = fork()) < 0) {
84412111Sralph 			sleep((unsigned)(i*i));
84512463Sralph 			continue;
84612463Sralph 		}
84712463Sralph 		/*
84812463Sralph 		 * Child should run as daemon instead of root
84912463Sralph 		 */
85012463Sralph 		if (pid == 0)
85112463Sralph 			setuid(DU);
85212463Sralph 		return(pid);
85312111Sralph 	}
85412111Sralph 	log("can't fork");
85512111Sralph 
85612111Sralph 	switch (action) {
85712111Sralph 	case DORETURN:
85812111Sralph 		return (-1);
85912111Sralph 	default:
86012111Sralph 		log("bad action (%d) to dofork", action);
86112111Sralph 		/*FALL THRU*/
86212111Sralph 	case DOABORT:
86312111Sralph 		exit(1);
86412111Sralph 	}
86512111Sralph 	/*NOTREACHED*/
86612111Sralph }
86712111Sralph 
86812111Sralph /*
86912111Sralph  * Cleanup child processes when a SIGINT is caught.
87012111Sralph  */
87112877Sralph static
87212111Sralph onintr()
87312111Sralph {
87412111Sralph 	kill(0, SIGINT);
87512111Sralph 	if (ofilter > 0)
87612111Sralph 		kill(ofilter, SIGCONT);
87712111Sralph 	while (wait(0) > 0)
87812111Sralph 		;
87912111Sralph 	exit(0);
88012111Sralph }
88112111Sralph 
88212877Sralph static
88312111Sralph init()
88412111Sralph {
88512111Sralph 	int status;
88612111Sralph 
887*13169Sralph 	if ((status = pgetent(line, printer)) < 0)
888*13169Sralph 		fatal("can't open printer description file");
889*13169Sralph 	else if (status == 0)
890*13169Sralph 		fatal("unknown printer");
89112111Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
89212111Sralph 		LP = DEFDEVLP;
89312111Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
89412463Sralph 		RP = DEFLP;
89512111Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
89612111Sralph 		LO = DEFLOCK;
89712111Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
89812111Sralph 		ST = DEFSTAT;
89912111Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
90012111Sralph 		LF = DEFLOGF;
90112111Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
90212111Sralph 		SD = DEFSPOOL;
90312111Sralph 	if ((DU = pgetnum("du")) < 0)
90412111Sralph 		DU = DEFUID;
90512111Sralph 	if ((FF = pgetstr("ff", &bp)) == NULL)
90612111Sralph 		FF = DEFFF;
90712111Sralph 	if ((PW = pgetnum("pw")) < 0)
90812111Sralph 		PW = DEFWIDTH;
90912111Sralph 	sprintf(&width[2], "%d", PW);
91012111Sralph 	if ((PL = pgetnum("pl")) < 0)
91112111Sralph 		PL = DEFLENGTH;
91212111Sralph 	sprintf(&length[2], "%d", PL);
91312463Sralph 	if ((PX = pgetnum("px")) < 0)
91412463Sralph 		PX = 0;
91512463Sralph 	sprintf(&pxwidth[2], "%d", PX);
91612463Sralph 	if ((PY = pgetnum("py")) < 0)
91712463Sralph 		PY = 0;
91812463Sralph 	sprintf(&pxlength[2], "%d", PY);
91912111Sralph 	RM = pgetstr("rm", &bp);
92012111Sralph 	AF = pgetstr("af", &bp);
92112111Sralph 	OF = pgetstr("of", &bp);
92212111Sralph 	IF = pgetstr("if", &bp);
92312463Sralph 	RF = pgetstr("rf", &bp);
92412111Sralph 	TF = pgetstr("tf", &bp);
92512111Sralph 	DF = pgetstr("df", &bp);
92612111Sralph 	GF = pgetstr("gf", &bp);
92712111Sralph 	VF = pgetstr("vf", &bp);
92812111Sralph 	CF = pgetstr("cf", &bp);
92912111Sralph 	TR = pgetstr("tr", &bp);
93012463Sralph 	RS = pgetflag("rs");
93112111Sralph 	SF = pgetflag("sf");
93212111Sralph 	SH = pgetflag("sh");
93312111Sralph 	SB = pgetflag("sb");
93412111Sralph 	RW = pgetflag("rw");
93512111Sralph 	BR = pgetnum("br");
93612111Sralph 	if ((FC = pgetnum("fc")) < 0)
93712111Sralph 		FC = 0;
93812111Sralph 	if ((FS = pgetnum("fs")) < 0)
93912111Sralph 		FS = 0;
94012111Sralph 	if ((XC = pgetnum("xc")) < 0)
94112111Sralph 		XC = 0;
94212111Sralph 	if ((XS = pgetnum("xs")) < 0)
94312111Sralph 		XS = 0;
94412581Sralph 	tof = !pgetflag("fo");
94512111Sralph }
94612111Sralph 
94712463Sralph /*
94812463Sralph  * Acquire line printer or remote connection.
94912463Sralph  */
95012877Sralph static
95112463Sralph openpr()
95212463Sralph {
95312463Sralph 	register int i, n;
95412463Sralph 
95512463Sralph 	if (*LP) {
95612463Sralph 		for (i = 1; ; i = i < 32 ? i << 1 : i) {
95713148Ssam 			pfd = open(LP, RW ? O_RDWR : O_WRONLY);
95812463Sralph 			if (pfd >= 0)
95912463Sralph 				break;
96012463Sralph 			if (errno == ENOENT) {
96112463Sralph 				log("cannot open %s", LP);
96212463Sralph 				exit(1);
96312463Sralph 			}
96412463Sralph 			if (i == 1)
96512463Sralph 				status("waiting for %s to become ready (offline ?)", printer);
96612463Sralph 			sleep(i);
96712463Sralph 		}
96812463Sralph 		if (isatty(pfd))
96912463Sralph 			setty();
97012463Sralph 		status("%s is ready and printing", printer);
97112463Sralph 	} else if (RM != NULL) {
97212463Sralph 		for (i = 1; ; i = i < 512 ? i << 1 : i) {
97312528Sralph 			pfd = getport(RM);
97412463Sralph 			if (pfd >= 0) {
97512463Sralph 				(void) sprintf(line, "\2%s\n", RP);
97612463Sralph 				n = strlen(line);
97712463Sralph 				if (write(pfd, line, n) != n)
97812463Sralph 					break;
97912463Sralph 				if (noresponse())
98012463Sralph 					(void) close(pfd);
98112463Sralph 				else
98212463Sralph 					break;
98312463Sralph 			}
98412463Sralph 			if (i == 1)
98512463Sralph 				status("waiting for %s to come up", RM);
98612463Sralph 			sleep(i);
98712463Sralph 		}
98812463Sralph 		status("sending to %s", RM);
98912463Sralph 		remote = 1;
99012463Sralph 	} else {
99112463Sralph 		log("no line printer device or remote machine name");
99212463Sralph 		exit(1);
99312463Sralph 	}
99412463Sralph 	/*
99512463Sralph 	 * Start up an output filter, if needed.
99612463Sralph 	 */
99712463Sralph 	if (OF) {
99812463Sralph 		int p[2];
99912463Sralph 		char *cp;
100012463Sralph 
100112463Sralph 		pipe(p);
100212463Sralph 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
100312463Sralph 			dup2(p[0], 0);		/* pipe is std in */
100412463Sralph 			dup2(pfd, 1);		/* printer is std out */
100512463Sralph 			for (i = 3; i < NOFILE; i++)
100612463Sralph 				(void) close(i);
100712463Sralph 			if ((cp = rindex(OF, '/')) == NULL)
100812463Sralph 				cp = OF;
100912463Sralph 			else
101012463Sralph 				cp++;
101112463Sralph 			execl(OF, cp, width, length, 0);
101212463Sralph 			log("can't execl output filter %s", OF);
101312463Sralph 			exit(1);
101412463Sralph 		}
101512463Sralph 		(void) close(p[0]);		/* close input side */
101612463Sralph 		ofd = p[1];			/* use pipe for output */
101712463Sralph 	} else {
101812463Sralph 		ofd = pfd;
101912463Sralph 		ofilter = 0;
102012463Sralph 	}
102112463Sralph }
102212463Sralph 
102312111Sralph struct bauds {
102412111Sralph 	int	baud;
102512111Sralph 	int	speed;
102612111Sralph } bauds[] = {
102712111Sralph 	50,	B50,
102812111Sralph 	75,	B75,
102912111Sralph 	110,	B110,
103012111Sralph 	134,	B134,
103112111Sralph 	150,	B150,
103212111Sralph 	200,	B200,
103312111Sralph 	300,	B300,
103412111Sralph 	600,	B600,
103512111Sralph 	1200,	B1200,
103612111Sralph 	1800,	B1800,
103712111Sralph 	2400,	B2400,
103812111Sralph 	4800,	B4800,
103912111Sralph 	9600,	B9600,
104012111Sralph 	19200,	EXTA,
104112111Sralph 	38400,	EXTB,
104212111Sralph 	0,	0
104312111Sralph };
104412111Sralph 
104512111Sralph /*
104612111Sralph  * setup tty lines.
104712111Sralph  */
104812877Sralph static
104912111Sralph setty()
105012111Sralph {
105112111Sralph 	struct sgttyb ttybuf;
105212111Sralph 	register struct bauds *bp;
105312111Sralph 
105412111Sralph 	if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
105512111Sralph 		log("cannot set exclusive-use");
105612111Sralph 		exit(1);
105712111Sralph 	}
105812111Sralph 	if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
105912111Sralph 		log("cannot get tty parameters");
106012111Sralph 		exit(1);
106112111Sralph 	}
106212111Sralph 	if (BR > 0) {
106312111Sralph 		for (bp = bauds; bp->baud; bp++)
106412111Sralph 			if (BR == bp->baud)
106512111Sralph 				break;
106612111Sralph 		if (!bp->baud) {
106712111Sralph 			log("illegal baud rate %d", BR);
106812111Sralph 			exit(1);
106912111Sralph 		}
107012111Sralph 		ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
107112111Sralph 	}
1072*13169Sralph 	ttybuf.sg_flags &= ~FC;
1073*13169Sralph 	ttybuf.sg_flags |= FS;
107412111Sralph 	if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
107512111Sralph 		log("cannot set tty parameters");
107612111Sralph 		exit(1);
107712111Sralph 	}
107812111Sralph 	if (XC) {
107912111Sralph 		if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
108012111Sralph 			log("cannot set local tty parameters");
108112111Sralph 			exit(1);
108212111Sralph 		}
108312111Sralph 	}
108412111Sralph 	if (XS) {
108512111Sralph 		if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
108612111Sralph 			log("cannot set local tty parameters");
108712111Sralph 			exit(1);
108812111Sralph 		}
108912111Sralph 	}
109012111Sralph }
109112463Sralph 
109212463Sralph /*VARARGS1*/
109312463Sralph static
109412463Sralph status(msg, a1, a2, a3)
109512463Sralph 	char *msg;
109612463Sralph {
109712463Sralph 	register int fd;
109812463Sralph 	char buf[BUFSIZ];
109912463Sralph 
110012463Sralph 	umask(0);
110113148Ssam 	fd = open(ST, O_WRONLY|O_CREAT, 0664);
110213148Ssam 	if (fd < 0 || flock(fd, LOCK_EX) < 0)
110312463Sralph 		fatal("cannot create status file");
110413148Ssam 	ftruncate(fd, 0);
110512463Sralph 	sprintf(buf, msg, a1, a2, a3);
110612463Sralph 	strcat(buf, "\n");
110712463Sralph 	(void) write(fd, buf, strlen(buf));
110812463Sralph 	(void) close(fd);
110912463Sralph }
1110