xref: /csrg-svn/usr.sbin/lpr/lpd/printjob.c (revision 12877)
1*12877Sralph /*	printjob.c	4.6	83/06/02	*/
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 
11*12877Sralph #define DORETURN	0		/* absorb fork error */
12*12877Sralph #define DOABORT		1		/* abort if dofork fails */
1312111Sralph 
14*12877Sralph static char	title[80];		/* ``pr'' title */
15*12877Sralph static FILE	*cfp;			/* control file */
16*12877Sralph static int	pfd;			/* printer file descriptor */
17*12877Sralph static int	ofd;			/* output filter file descriptor */
18*12877Sralph static int	lfd;			/* lock file descriptor */
19*12877Sralph static int	pid;			/* pid of lpd process */
20*12877Sralph static int	prchild;		/* id of pr process */
21*12877Sralph static int	child;			/* id of any filters */
22*12877Sralph static int	ofilter;		/* id of output filter, if any */
23*12877Sralph static int	tof;			/* true if at top of form */
24*12877Sralph static int	remote;			/* true if sending files to remote */
2512111Sralph 
26*12877Sralph static char	logname[32];		/* user's login name */
27*12877Sralph static char	jobname[32];		/* job or file name */
28*12877Sralph static char	class[32];		/* classification field */
29*12877Sralph static char	width[10] = "-w";	/* page width in characters */
30*12877Sralph static char	length[10] = "-l";	/* page length in lines */
31*12877Sralph static char	pxwidth[10] = "-x";	/* page width in pixels */
32*12877Sralph static char	pxlength[10] = "-y";	/* page length in pixels */
33*12877Sralph static char	indent[10] = "-i0";	/* indentation size in characters */
3412111Sralph 
3512111Sralph printjob()
3612111Sralph {
3712111Sralph 	struct stat stb;
3812111Sralph 	register struct queue *q, **qp;
3912111Sralph 	struct queue **queue;
4012111Sralph 	register int i, nitems;
4112111Sralph 	long pidoff;
4212111Sralph 	extern int onintr();
4312111Sralph 
4412111Sralph 	init();					/* set up capabilities */
45*12877Sralph 	(void) close(1);			/* set up log file */
46*12877Sralph 	(void) close(2);
47*12877Sralph 	if (open(LF, FWRONLY|FAPPEND, 0) < 0)
48*12877Sralph 		(void) open("/dev/null", FWRONLY);
49*12877Sralph 	dup(1);
5012463Sralph 	pid = getpid();				/* for use with lprm */
5112111Sralph 	setpgrp(0, pid);
5212463Sralph 	sigset(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 */
6312111Sralph 	if ((lfd = open(LO, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK|FNBLOCK, 0664)) < 0) {
6412111Sralph 		if (errno == EWOULDBLOCK)	/* active deamon present */
6512111Sralph 			exit(0);
6612111Sralph 		log("cannot create %s", LO);
6712111Sralph 		exit(1);
6812111Sralph 	}
6912111Sralph 	/*
7012111Sralph 	 * write process id for others to know
7112111Sralph 	 */
7212111Sralph 	sprintf(line, "%u\n", pid);
7312111Sralph 	pidoff = i = strlen(line);
7412463Sralph 	if (write(lfd, line, i) != i) {
7512111Sralph 		log("cannot write daemon pid");
7612111Sralph 		exit(1);
7712111Sralph 	}
7812111Sralph 	/*
7912111Sralph 	 * search the spool directory for work and sort by queue order.
8012111Sralph 	 */
8112111Sralph 	if ((nitems = getq(&queue)) < 0) {
8212111Sralph 		log("can't scan spool directory %s", SD);
8312111Sralph 		exit(1);
8412111Sralph 	}
8512463Sralph 	if (nitems == 0)		/* no work to do */
8612111Sralph 		exit(0);
8712463Sralph 	openpr();			/* open printer or remote */
8812463Sralph again:
8912111Sralph 	/*
9012111Sralph 	 * we found something to do now do it --
9112111Sralph 	 *    write the name of the current control file into the lock file
9212111Sralph 	 *    so the spool queue program can tell what we're working on
9312111Sralph 	 */
9412111Sralph 	for (qp = queue; nitems--; free((char *) q)) {
9512111Sralph 		q = *qp++;
9612111Sralph 		if (stat(q->q_name, &stb) < 0)
9712111Sralph 			continue;
9812463Sralph 	restart:
9912111Sralph 		(void) lseek(lfd, pidoff, 0);
10012111Sralph 		(void) sprintf(line, "%s\n", q->q_name);
10112111Sralph 		i = strlen(line);
10212111Sralph 		if (write(lfd, line, i) != i)
10312111Sralph 			log("can't write (%d) control file name", errno);
10412111Sralph 		if (!remote)
10512111Sralph 			i = printit(q->q_name);
10612111Sralph 		else
10712111Sralph 			i = sendit(q->q_name);
10812463Sralph 		/*
10912463Sralph 		 * Check to see if we are supposed to stop printing.
11012463Sralph 		 */
11112463Sralph 		if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
11212463Sralph 			goto done;
11312463Sralph 		/*
11412463Sralph 		 * Check to see if we should try reprinting the job.
11512463Sralph 		 */
11612463Sralph 		if (i > 0) {
11712111Sralph 			log("restarting");
11812111Sralph 			if (ofilter > 0) {
11912111Sralph 				kill(ofilter, SIGCONT);	/* to be sure */
12012111Sralph 				(void) close(ofd);
12112111Sralph 				while ((i = wait(0)) > 0 && i != ofilter)
12212111Sralph 					;
12312111Sralph 				ofilter = 0;
12412111Sralph 			}
12512463Sralph 			(void) close(pfd);	/* close printer */
12612463Sralph 			(void) lseek(lfd, pidoff, 0);
12712463Sralph 			if (write(lfd, "\n", 1) != 1)
12812463Sralph 				log("can't write (%d) control file name", errno);
12912463Sralph 			openpr();		/* try to reopen printer */
13012111Sralph 			goto restart;
13112111Sralph 		}
13212111Sralph 	}
13312111Sralph 	free((char *) queue);
13412463Sralph 	/*
13512463Sralph 	 * search the spool directory for more work.
13612463Sralph 	 */
13712463Sralph 	if ((nitems = getq(&queue)) < 0) {
13812463Sralph 		log("can't scan spool directory %s", SD);
13912463Sralph 		exit(1);
14012463Sralph 	}
14112463Sralph 	if (nitems == 0) {		/* no more work to do */
14212463Sralph 	done:
14312463Sralph 		if (!SF && !tof)
14412463Sralph 			(void) write(ofd, FF, strlen(FF));
14512463Sralph 		if (TR != NULL)		/* output trailer */
14612463Sralph 			(void) write(ofd, TR, strlen(TR));
14712463Sralph 		exit(0);
14812463Sralph 	}
14912111Sralph 	goto again;
15012111Sralph }
15112111Sralph 
15212111Sralph char	fonts[4][50];	/* fonts for troff */
15312111Sralph 
15412111Sralph static char ifonts[4][18] = {
15512111Sralph 	"/usr/lib/vfont/R",
15612111Sralph 	"/usr/lib/vfont/I",
15712111Sralph 	"/usr/lib/vfont/B",
15812111Sralph 	"/usr/lib/vfont/S"
15912111Sralph };
16012111Sralph 
16112111Sralph /*
16212111Sralph  * The remaining part is the reading of the control file (cf)
16312111Sralph  * and performing the various actions.
16412111Sralph  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
16512111Sralph  * -1 if a non-recoverable error occured.
16612111Sralph  */
167*12877Sralph static
16812111Sralph printit(file)
16912111Sralph 	char *file;
17012111Sralph {
17112111Sralph 	register int i;
17212111Sralph 	int bombed = 0;
17312111Sralph 
17412111Sralph 	/*
17512111Sralph 	 * open control file
17612111Sralph 	 */
17712111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
17812111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
17912111Sralph 		return(0);
18012111Sralph 	}
18112111Sralph 	/*
18212111Sralph 	 * Reset troff fonts.
18312111Sralph 	 */
18412111Sralph 	for (i = 0; i < 4; i++)
18512111Sralph 		strcpy(fonts[i], ifonts[i]);
18612111Sralph 
18712111Sralph 	/*
18812111Sralph 	 *      read the control file for work to do
18912111Sralph 	 *
19012111Sralph 	 *      file format -- first character in the line is a command
19112111Sralph 	 *      rest of the line is the argument.
19212111Sralph 	 *      valid commands are:
19312111Sralph 	 *
19412111Sralph 	 *		J -- "job name" on banner page
19512111Sralph 	 *		C -- "class name" on banner page
19612111Sralph 	 *              L -- "literal" user's name to print on banner
19712111Sralph 	 *		T -- "title" for pr
19812111Sralph 	 *		H -- "host name" of machine where lpr was done
19912111Sralph 	 *              P -- "person" user's login name
20012581Sralph 	 *              I -- "indent" amount to indent output
20112111Sralph 	 *              f -- "file name" name of text file to print
20212111Sralph 	 *		l -- "file name" text file with control chars
20312111Sralph 	 *		p -- "file name" text file to print with pr(1)
20412111Sralph 	 *		t -- "file name" troff(1) file to print
20512111Sralph 	 *		d -- "file name" dvi file to print
20612111Sralph 	 *		g -- "file name" plot(1G) file to print
20712111Sralph 	 *		v -- "file name" plain raster file to print
20812111Sralph 	 *		c -- "file name" cifplot file to print
20912111Sralph 	 *		1 -- "R font file" for troff
21012111Sralph 	 *		2 -- "I font file" for troff
21112111Sralph 	 *		3 -- "B font file" for troff
21212111Sralph 	 *		4 -- "S font file" for troff
21312111Sralph 	 *		N -- "name" of file (used by lpq)
21412111Sralph 	 *              U -- "unlink" name of file to remove
21512111Sralph 	 *                    (after we print it. (Pass 2 only)).
21612111Sralph 	 *		M -- "mail" to user when done printing
21712111Sralph 	 *
21812111Sralph 	 *      getline reads a line and expands tabs to blanks
21912111Sralph 	 */
22012111Sralph 
22112111Sralph 	/* pass 1 */
22212111Sralph 
22312111Sralph 	while (getline(cfp))
22412111Sralph 		switch (line[0]) {
22512111Sralph 		case 'H':
22612111Sralph 			strcpy(host, line+1);
22712111Sralph 			if (class[0] == '\0')
22812111Sralph 				strcpy(class, line+1);
22912111Sralph 			continue;
23012111Sralph 
23112111Sralph 		case 'P':
23212111Sralph 			strcpy(logname, line+1);
23312463Sralph 			if (RS) {			/* restricted */
23412463Sralph 				if (getpwnam(logname) == (struct passwd *)0) {
23512463Sralph 					bombed = 2;
23612463Sralph 					sendmail(bombed);
23712463Sralph 					goto pass2;
23812463Sralph 				}
23912463Sralph 			}
24012111Sralph 			continue;
24112111Sralph 
24212111Sralph 		case 'J':
24312111Sralph 			if (line[1] != '\0')
24412111Sralph 				strcpy(jobname, line+1);
24512111Sralph 			else
24612111Sralph 				strcpy(jobname, " ");
24712111Sralph 			continue;
24812111Sralph 
24912111Sralph 		case 'C':
25012111Sralph 			if (line[1] != '\0')
25112111Sralph 				strcpy(class, line+1);
25212111Sralph 			else if (class[0] == '\0')
25312111Sralph 				gethostname(class, sizeof (class));
25412111Sralph 			continue;
25512111Sralph 
25612111Sralph 		case 'T':	/* header title for pr */
25712111Sralph 			strcpy(title, line+1);
25812111Sralph 			continue;
25912111Sralph 
26012111Sralph 		case 'L':	/* identification line */
26112111Sralph 			if (!SH)
26212111Sralph 				banner(line+1, jobname);
26312111Sralph 			continue;
26412111Sralph 
26512111Sralph 		case '1':	/* troff fonts */
26612111Sralph 		case '2':
26712111Sralph 		case '3':
26812111Sralph 		case '4':
26912111Sralph 			if (line[1] != '\0')
27012111Sralph 				strcpy(fonts[line[0]-'1'], line+1);
27112111Sralph 			continue;
27212111Sralph 
27312111Sralph 		case 'W':	/* page width */
27412111Sralph 			strcpy(width+2, line+1);
27512111Sralph 			continue;
27612111Sralph 
27712581Sralph 		case 'I':	/* indent amount */
27812581Sralph 			strcpy(indent+2, line+1);
27912581Sralph 			continue;
28012581Sralph 
28112111Sralph 		default:	/* some file to print */
28212111Sralph 			if ((i = print(line[0], line+1)) > 0) {
28312111Sralph 				(void) fclose(cfp);
28412111Sralph 				return(1);
28512111Sralph 			} else if (i < 0)
28612111Sralph 				bombed = 1;
28712111Sralph 			title[0] = '\0';
28812111Sralph 			continue;
28912111Sralph 
29012111Sralph 		case 'N':
29112111Sralph 		case 'U':
29212111Sralph 		case 'M':
29312111Sralph 			continue;
29412111Sralph 		}
29512111Sralph 
29612111Sralph 	/* pass 2 */
29712111Sralph 
29812463Sralph pass2:
29912111Sralph 	fseek(cfp, 0L, 0);
30012111Sralph 	while (getline(cfp))
30112111Sralph 		switch (line[0]) {
30212111Sralph 		case 'M':
30312463Sralph 			if (bombed != 2)		/* already sent if 2 */
30412463Sralph 				sendmail(bombed);
30512111Sralph 			continue;
30612111Sralph 
30712111Sralph 		case 'U':
30812111Sralph 			(void) unlink(line+1);
30912111Sralph 		}
31012111Sralph 	/*
31112111Sralph 	 * clean-up incase another control file exists
31212111Sralph 	 */
31312111Sralph 	(void) fclose(cfp);
31412111Sralph 	(void) unlink(file);
31512111Sralph 	return(0);
31612111Sralph }
31712111Sralph 
31812111Sralph /*
31912111Sralph  * Print a file.
32012111Sralph  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, TF, CF, VF}.
32112111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
32212111Sralph  * 0 if all is well.
32312111Sralph  * Note: all filters take stdin as the file, stdout as the printer,
32412111Sralph  * stderr as the log file, and must not ignore SIGINT.
32512111Sralph  */
326*12877Sralph static
32712111Sralph print(format, file)
32812111Sralph 	int format;
32912111Sralph 	char *file;
33012111Sralph {
33112111Sralph 	register int n, fi, fo;
33212111Sralph 	register char *prog;
33312111Sralph 	char *av[15], buf[BUFSIZ];
33412111Sralph 	int pid, p[2], stopped = 0;
33512111Sralph 	union wait status;
33612111Sralph 
33712111Sralph 	if ((fi = open(file, FRDONLY, 0)) < 0) {
33812111Sralph 		log("%s: open failure <errno = %d>", file, errno);
33912111Sralph 		return(-1);
34012111Sralph 	}
34112111Sralph 	if (!SF && !tof) {		/* start on a fresh page */
34212111Sralph 		(void) write(ofd, FF, strlen(FF));
34312111Sralph 		tof = 1;
34412111Sralph 	}
34512111Sralph 	if (IF == NULL && (format == 'f' || format == 'l')) {
34612111Sralph 		tof = 0;
34712111Sralph 		while ((n = read(fi, buf, BUFSIZ)) > 0)
34812111Sralph 			if (write(ofd, buf, n) != n) {
34912111Sralph 				(void) close(fi);
35012111Sralph 				return(1);
35112111Sralph 			}
35212111Sralph 		(void) close(fi);
35312111Sralph 		return(0);
35412111Sralph 	}
35512111Sralph 	switch (format) {
35612111Sralph 	case 'p':	/* print file using 'pr' */
35712111Sralph 		if (IF == NULL) {	/* use output filter */
35812111Sralph 			prog = PR;
35912111Sralph 			av[0] = "pr";
36012111Sralph 			av[1] = width;
36112111Sralph 			av[2] = length;
36212111Sralph 			av[3] = "-h";
36312111Sralph 			av[4] = *title ? title : " ";
36412111Sralph 			av[5] = 0;
36512111Sralph 			fo = ofd;
36612111Sralph 			goto start;
36712111Sralph 		}
36812111Sralph 		pipe(p);
36912111Sralph 		if ((prchild = dofork(DORETURN)) == 0) {	/* child */
37012111Sralph 			dup2(fi, 0);		/* file is stdin */
37112111Sralph 			dup2(p[1], 1);		/* pipe is stdout */
37212111Sralph 			for (n = 3; n < NOFILE; n++)
37312111Sralph 				(void) close(n);
37412111Sralph 			execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
37512111Sralph 			log("cannot execl %s", PR);
37612111Sralph 			exit(2);
37712111Sralph 		}
37812111Sralph 		(void) close(p[1]);		/* close output side */
37912111Sralph 		(void) close(fi);
38012111Sralph 		if (prchild < 0) {
38112111Sralph 			prchild = 0;
38212111Sralph 			(void) close(p[0]);
38312111Sralph 			return(-1);
38412111Sralph 		}
38512111Sralph 		fi = p[0];			/* use pipe for input */
38612111Sralph 	case 'f':	/* print plain text file */
38712111Sralph 		prog = IF;
38812111Sralph 		av[1] = width;
38912111Sralph 		av[2] = length;
39012581Sralph 		av[3] = indent;
39112581Sralph 		n = 4;
39212111Sralph 		break;
39312111Sralph 	case 'l':	/* like 'f' but pass control characters */
39412111Sralph 		prog = IF;
39512111Sralph 		av[1] = "-l";
39612111Sralph 		av[2] = width;
39712111Sralph 		av[3] = length;
39812581Sralph 		av[4] = indent;
39912581Sralph 		n = 5;
40012111Sralph 		break;
40112463Sralph 	case 'r':	/* print a fortran text file */
40212463Sralph 		prog = RF;
40312463Sralph 		av[1] = width;
40412463Sralph 		av[2] = length;
40512463Sralph 		n = 3;
40612463Sralph 		break;
40712111Sralph 	case 't':	/* print troff output */
40812463Sralph 	case 'd':	/* print tex output */
40912111Sralph 		(void) unlink(".railmag");
41012463Sralph 		if ((fo = creat(".railmag", FILMOD)) < 0) {
41112111Sralph 			log("cannot create .railmag");
41212111Sralph 			(void) unlink(".railmag");
41312111Sralph 		} else {
41412111Sralph 			for (n = 0; n < 4; n++) {
41512111Sralph 				if (fonts[n][0] != '/')
41612111Sralph 					(void) write(fo, "/usr/lib/vfont/", 15);
41712111Sralph 				(void) write(fo, fonts[n], strlen(fonts[n]));
41812111Sralph 				(void) write(fo, "\n", 1);
41912111Sralph 			}
42012111Sralph 			(void) close(fo);
42112111Sralph 		}
42212111Sralph 		prog = (format == 't') ? TF : DF;
42312463Sralph 		av[1] = pxwidth;
42412463Sralph 		av[2] = pxlength;
42512463Sralph 		n = 3;
42612111Sralph 		break;
42712111Sralph 	case 'c':	/* print cifplot output */
42812111Sralph 		prog = CF;
42912463Sralph 		av[1] = pxwidth;
43012463Sralph 		av[2] = pxlength;
43112463Sralph 		n = 3;
43212111Sralph 		break;
43312111Sralph 	case 'g':	/* print plot(1G) output */
43412111Sralph 		prog = GF;
43512463Sralph 		av[1] = pxwidth;
43612463Sralph 		av[2] = pxlength;
43712463Sralph 		n = 3;
43812111Sralph 		break;
43912111Sralph 	case 'v':	/* print raster output */
44012111Sralph 		prog = VF;
44112463Sralph 		av[1] = pxwidth;
44212463Sralph 		av[2] = pxlength;
44312463Sralph 		n = 3;
44412111Sralph 		break;
44512111Sralph 	default:
44612111Sralph 		(void) close(fi);
44712111Sralph 		log("illegal format character '%c'", format);
44812111Sralph 		return(-1);
44912111Sralph 	}
45012111Sralph 	if ((av[0] = rindex(prog, '/')) != NULL)
45112111Sralph 		av[0]++;
45212111Sralph 	else
45312111Sralph 		av[0] = prog;
45412111Sralph 	av[n++] = "-n";
45512111Sralph 	av[n++] = logname;
45612111Sralph 	av[n++] = "-h";
45712111Sralph 	av[n++] = host;
45812111Sralph 	av[n++] = AF;
45912111Sralph 	av[n] = 0;
46012111Sralph 	fo = pfd;
46112111Sralph 	if (ofilter > 0) {		/* stop output filter */
46212111Sralph 		write(ofd, "\031\1", 2);
46312111Sralph 		while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
46412111Sralph 			;
46512111Sralph 		if (status.w_stopval != WSTOPPED) {
46612111Sralph 			(void) close(fi);
46712111Sralph 			log("output filter died (%d)", status.w_retcode);
46812111Sralph 			return(1);
46912111Sralph 		}
47012111Sralph 		stopped++;
47112111Sralph 	}
47212111Sralph start:
47312111Sralph 	if ((child = dofork(DORETURN)) == 0) {	/* child */
47412111Sralph 		dup2(fi, 0);
47512111Sralph 		dup2(fo, 1);
47612111Sralph 		for (n = 3; n < NOFILE; n++)
47712111Sralph 			(void) close(n);
47812111Sralph 		execv(prog, av);
47912111Sralph 		log("cannot execl %s", prog);
48012111Sralph 		exit(2);
48112111Sralph 	}
48212111Sralph 	(void) close(fi);
48312111Sralph 	if (child < 0)
48412111Sralph 		status.w_retcode = 100;
48512111Sralph 	else
48612111Sralph 		while ((pid = wait(&status)) > 0 && pid != child)
48712111Sralph 			;
48812111Sralph 	child = 0;
48912111Sralph 	prchild = 0;
49012111Sralph 	if (stopped) {		/* restart output filter */
49112111Sralph 		if (kill(ofilter, SIGCONT) < 0) {
49212111Sralph 			log("cannot restart output filter");
49312111Sralph 			exit(1);
49412111Sralph 		}
49512111Sralph 	}
49612111Sralph 	tof = 0;
49712111Sralph 	if (!WIFEXITED(status) || status.w_retcode > 1) {
49812111Sralph 		log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode);
49912111Sralph 		return(-1);
50012111Sralph 	} else if (status.w_retcode == 1)
50112111Sralph 		return(1);
50212111Sralph 	tof = 1;
50312111Sralph 	return(0);
50412111Sralph }
50512111Sralph 
50612111Sralph /*
50712111Sralph  * Send the daemon control file (cf) and any data files.
50812111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
50912111Sralph  * 0 if all is well.
51012111Sralph  */
511*12877Sralph static
51212111Sralph sendit(file)
51312111Sralph 	char *file;
51412111Sralph {
51512111Sralph 	register int linelen, err = 0;
51612111Sralph 	char last[132];
51712111Sralph 
51812111Sralph 	/*
51912111Sralph 	 * open control file
52012111Sralph 	 */
52112111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
52212111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
52312111Sralph 		return(0);
52412111Sralph 	}
52512111Sralph 	/*
52612111Sralph 	 *      read the control file for work to do
52712111Sralph 	 *
52812111Sralph 	 *      file format -- first character in the line is a command
52912111Sralph 	 *      rest of the line is the argument.
53012111Sralph 	 *      commands of interest are:
53112111Sralph 	 *
53212111Sralph 	 *            a-z -- "file name" name of file to print
53312111Sralph 	 *              U -- "unlink" name of file to remove
53412111Sralph 	 *                    (after we print it. (Pass 2 only)).
53512111Sralph 	 */
53612111Sralph 
53712111Sralph 	/*
53812111Sralph 	 * pass 1
53912111Sralph 	 */
54012111Sralph 	while (getline(cfp)) {
54112111Sralph 	again:
54212111Sralph 		if (line[0] >= 'a' && line[0] <= 'z') {
54312111Sralph 			strcpy(last, line);
54412111Sralph 			while (linelen = getline(cfp))
54512111Sralph 				if (strcmp(last, line))
54612111Sralph 					break;
54712111Sralph 			if ((err = sendfile('\3', last+1)) > 0) {
54812111Sralph 				(void) fclose(cfp);
54912111Sralph 				return(1);
55012111Sralph 			} else if (err)
55112111Sralph 				break;
55212111Sralph 			if (linelen)
55312111Sralph 				goto again;
55412111Sralph 			break;
55512111Sralph 		}
55612111Sralph 	}
55712111Sralph 	if (!err && sendfile('\2', file) > 0) {
55812111Sralph 		(void) fclose(cfp);
55912111Sralph 		return(1);
56012111Sralph 	}
56112111Sralph 	/*
56212111Sralph 	 * pass 2
56312111Sralph 	 */
56412111Sralph 	fseek(cfp, 0L, 0);
56512111Sralph 	while (getline(cfp))
56612111Sralph 		if (line[0] == 'U')
56712111Sralph 			(void) unlink(line+1);
56812111Sralph 	/*
56912111Sralph 	 * clean-up incase another control file exists
57012111Sralph 	 */
57112111Sralph 	(void) fclose(cfp);
57212111Sralph 	(void) unlink(file);
57312111Sralph 	return(0);
57412111Sralph }
57512111Sralph 
57612111Sralph /*
57712111Sralph  * Send a data file to the remote machine and spool it.
57812111Sralph  * Return positive if we should try resending.
57912111Sralph  */
580*12877Sralph static
58112111Sralph sendfile(type, file)
58212111Sralph 	char type, *file;
58312111Sralph {
58412111Sralph 	register int f, i, amt;
58512111Sralph 	struct stat stb;
58612111Sralph 	char buf[BUFSIZ];
58712111Sralph 	int sizerr;
58812111Sralph 
58912111Sralph 	if ((f = open(file, FRDONLY, 0)) < 0 || fstat(f, &stb) < 0) {
59012111Sralph 		log("file (%s) open failure <errno = %d>", file, errno);
59112111Sralph 		return(-1);
59212111Sralph 	}
59312111Sralph 	(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
59412111Sralph 	amt = strlen(buf);
59512692Sralph 	if (write(pfd, buf, amt) != amt) {
59612692Sralph 		(void) close(f);
59712111Sralph 		return(1);
59812692Sralph 	}
59912692Sralph 	if (noresponse()) {
60012692Sralph 		(void) close(f);
60112111Sralph 		return(1);
60212692Sralph 	}
60312111Sralph 	sizerr = 0;
60412111Sralph 	for (i = 0; i < stb.st_size; i += BUFSIZ) {
60512111Sralph 		amt = BUFSIZ;
60612111Sralph 		if (i + amt > stb.st_size)
60712111Sralph 			amt = stb.st_size - i;
60812111Sralph 		if (sizerr == 0 && read(f, buf, amt) != amt)
60912111Sralph 			sizerr = 1;
61012692Sralph 		if (write(pfd, buf, amt) != amt) {
61112692Sralph 			(void) close(f);
61212111Sralph 			return(1);
61312692Sralph 		}
61412111Sralph 	}
61512111Sralph 	(void) close(f);
61612111Sralph 	if (sizerr) {
61712111Sralph 		log("%s: changed size", file);
61812111Sralph 		(void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
61912111Sralph 		return(-1);
62012111Sralph 	}
62112111Sralph 	if (write(pfd, "", 1) != 1)
62212111Sralph 		return(1);
62312111Sralph 	if (noresponse())
62412111Sralph 		return(1);
62512111Sralph 	return(0);
62612111Sralph }
62712111Sralph 
62812111Sralph /*
62912111Sralph  * Check to make sure there have been no errors and that both programs
63012111Sralph  * are in sync with eachother.
63112111Sralph  * Return non-zero if the connection was lost.
63212111Sralph  */
63312111Sralph static
63412111Sralph noresponse()
63512111Sralph {
63612111Sralph 	char resp;
63712111Sralph 
63812111Sralph 	if (read(pfd, &resp, 1) != 1 || resp != '\0') {
63912111Sralph 		log("lost connection or error in recvjob");
64012111Sralph 		return(1);
64112111Sralph 	}
64212111Sralph 	return(0);
64312111Sralph }
64412111Sralph 
64512111Sralph /*
64612111Sralph  * Banner printing stuff
64712111Sralph  */
648*12877Sralph static
64912111Sralph banner(name1, name2)
65012111Sralph 	char *name1, *name2;
65112111Sralph {
65212111Sralph 	time_t tvec;
65312111Sralph 	extern char *ctime();
65412111Sralph 
65512111Sralph 	time(&tvec);
65612111Sralph 	if (!SF && !tof)
65712111Sralph 		(void) write(ofd, FF, strlen(FF));
65812111Sralph 	if (SB) {	/* short banner only */
65912111Sralph 		if (class[0]) {
66012111Sralph 			(void) write(ofd, class, strlen(class));
66112111Sralph 			(void) write(ofd, ":", 1);
66212111Sralph 		}
66312111Sralph 		(void) write(ofd, name1, strlen(name1));
66412111Sralph 		(void) write(ofd, "  Job: ", 7);
66512111Sralph 		(void) write(ofd, name2, strlen(name2));
66612111Sralph 		(void) write(ofd, "  Date: ", 8);
66712111Sralph 		(void) write(ofd, ctime(&tvec), 24);
66812111Sralph 		(void) write(ofd, "\n", 1);
66912111Sralph 	} else {	/* normal banner */
67012111Sralph 		(void) write(ofd, "\n\n\n", 3);
67112111Sralph 		scan_out(ofd, name1, '\0');
67212111Sralph 		(void) write(ofd, "\n\n", 2);
67312111Sralph 		scan_out(ofd, name2, '\0');
67412111Sralph 		if (class[0]) {
67512111Sralph 			(void) write(ofd,"\n\n\n",3);
67612111Sralph 			scan_out(ofd, class, '\0');
67712111Sralph 		}
67812111Sralph 		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
67912111Sralph 		(void) write(ofd, name2, strlen(name2));
68012111Sralph 		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
68112111Sralph 		(void) write(ofd, ctime(&tvec), 24);
68212111Sralph 		(void) write(ofd, "\n", 1);
68312111Sralph 	}
68412111Sralph 	if (!SF)
68512111Sralph 		(void) write(ofd, FF, strlen(FF));
68612111Sralph 	tof = 1;
68712111Sralph }
68812111Sralph 
689*12877Sralph static char *
69012111Sralph scnline(key, p, c)
69112111Sralph 	register char key, *p;
69212111Sralph 	char c;
69312111Sralph {
69412111Sralph 	register scnwidth;
69512111Sralph 
69612111Sralph 	for (scnwidth = WIDTH; --scnwidth;) {
69712111Sralph 		key <<= 1;
69812111Sralph 		*p++ = key & 0200 ? c : BACKGND;
69912111Sralph 	}
70012111Sralph 	return (p);
70112111Sralph }
70212111Sralph 
70312111Sralph #define TRC(q)	(((q)-' ')&0177)
70412111Sralph 
705*12877Sralph static
70612111Sralph scan_out(scfd, scsp, dlm)
70712111Sralph 	int scfd;
70812111Sralph 	char *scsp, dlm;
70912111Sralph {
71012111Sralph 	register char *strp;
71112111Sralph 	register nchrs, j;
71212111Sralph 	char outbuf[LINELEN+1], *sp, c, cc;
71312111Sralph 	int d, scnhgt;
71412111Sralph 	extern char scnkey[][HEIGHT];	/* in lpdchar.c */
71512111Sralph 
71612111Sralph 	for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
71712111Sralph 		strp = &outbuf[0];
71812111Sralph 		sp = scsp;
71912111Sralph 		for (nchrs = 0; ; ) {
72012111Sralph 			d = dropit(c = TRC(cc = *sp++));
72112111Sralph 			if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
72212111Sralph 				for (j = WIDTH; --j;)
72312111Sralph 					*strp++ = BACKGND;
72412111Sralph 			else
72512111Sralph 				strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
72612111Sralph 			if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
72712111Sralph 				break;
72812111Sralph 			*strp++ = BACKGND;
72912111Sralph 			*strp++ = BACKGND;
73012111Sralph 		}
73112111Sralph 		while (*--strp == BACKGND && strp >= outbuf)
73212111Sralph 			;
73312111Sralph 		strp++;
73412111Sralph 		*strp++ = '\n';
73512111Sralph 		(void) write(scfd, outbuf, strp-outbuf);
73612111Sralph 	}
73712111Sralph }
73812111Sralph 
739*12877Sralph static
74012111Sralph dropit(c)
74112111Sralph 	char c;
74212111Sralph {
74312111Sralph 	switch(c) {
74412111Sralph 
74512111Sralph 	case TRC('_'):
74612111Sralph 	case TRC(';'):
74712111Sralph 	case TRC(','):
74812111Sralph 	case TRC('g'):
74912111Sralph 	case TRC('j'):
75012111Sralph 	case TRC('p'):
75112111Sralph 	case TRC('q'):
75212111Sralph 	case TRC('y'):
75312111Sralph 		return (DROP);
75412111Sralph 
75512111Sralph 	default:
75612111Sralph 		return (0);
75712111Sralph 	}
75812111Sralph }
75912111Sralph 
76012111Sralph /*
76112111Sralph  * sendmail ---
76212111Sralph  *   tell people about job completion
76312111Sralph  */
764*12877Sralph static
76512111Sralph sendmail(bombed)
76612111Sralph 	int bombed;
76712111Sralph {
76812111Sralph 	static int p[2];
76912111Sralph 	register int i;
77012111Sralph 	int stat;
77112111Sralph 	register char *cp;
77212111Sralph 	char buf[100];
77312111Sralph 
77412111Sralph 	pipe(p);
77512111Sralph 	if ((stat = dofork(DORETURN)) == 0) {		/* child */
77612111Sralph 		dup2(p[0], 0);
77712111Sralph 		for (i = 3; i < NOFILE; i++)
77812111Sralph 			(void) close(i);
77912111Sralph 		if ((cp = rindex(MAIL, '/')) != NULL)
78012111Sralph 			cp++;
78112111Sralph 		else
78212111Sralph 			cp = MAIL;
78312111Sralph 		sprintf(buf, "%s@%s", line+1, host);
78412111Sralph 		execl(MAIL, cp, buf, 0);
78512111Sralph 		exit(0);
78612111Sralph 	} else if (stat > 0) {				/* parent */
78712111Sralph 		dup2(p[1], 1);
78812111Sralph 		printf("To: %s\n", line+1);
78912111Sralph 		printf("Subject: printer job\n\n");
79012111Sralph 		printf("Your printer job ");
79112111Sralph 		if (*jobname)
79212111Sralph 			printf("(%s) ", jobname);
79312463Sralph 		switch (bombed) {
79412463Sralph 		case 0:
79512463Sralph 			printf("\ncompleted successfully\n");
79612463Sralph 			break;
79712463Sralph 		default:
79812463Sralph 		case 1:
79912463Sralph 			printf("\ncould not be printed\n");
80012463Sralph 			break;
80112463Sralph 		case 2:
80212463Sralph 			printf("\ncould not be printed without an account on %s\n", host);
80312463Sralph 			break;
80412463Sralph 		}
80512111Sralph 		fflush(stdout);
80612111Sralph 		(void) close(1);
80712111Sralph 	}
80812111Sralph 	(void) close(p[0]);
80912111Sralph 	(void) close(p[1]);
81012111Sralph 	wait(&stat);
81112111Sralph }
81212111Sralph 
81312111Sralph /*
81412111Sralph  * dofork - fork with retries on failure
81512111Sralph  */
816*12877Sralph static
81712111Sralph dofork(action)
81812111Sralph 	int action;
81912111Sralph {
82012111Sralph 	register int i, pid;
82112111Sralph 
82212111Sralph 	for (i = 0; i < 20; i++) {
82312463Sralph 		if ((pid = fork()) < 0) {
82412111Sralph 			sleep((unsigned)(i*i));
82512463Sralph 			continue;
82612463Sralph 		}
82712463Sralph 		/*
82812463Sralph 		 * Child should run as daemon instead of root
82912463Sralph 		 */
83012463Sralph 		if (pid == 0)
83112463Sralph 			setuid(DU);
83212463Sralph 		return(pid);
83312111Sralph 	}
83412111Sralph 	log("can't fork");
83512111Sralph 
83612111Sralph 	switch (action) {
83712111Sralph 	case DORETURN:
83812111Sralph 		return (-1);
83912111Sralph 	default:
84012111Sralph 		log("bad action (%d) to dofork", action);
84112111Sralph 		/*FALL THRU*/
84212111Sralph 	case DOABORT:
84312111Sralph 		exit(1);
84412111Sralph 	}
84512111Sralph 	/*NOTREACHED*/
84612111Sralph }
84712111Sralph 
84812111Sralph /*
84912111Sralph  * Cleanup child processes when a SIGINT is caught.
85012111Sralph  */
851*12877Sralph static
85212111Sralph onintr()
85312111Sralph {
85412111Sralph 	kill(0, SIGINT);
85512111Sralph 	if (ofilter > 0)
85612111Sralph 		kill(ofilter, SIGCONT);
85712111Sralph 	while (wait(0) > 0)
85812111Sralph 		;
85912111Sralph 	exit(0);
86012111Sralph }
86112111Sralph 
862*12877Sralph static
86312111Sralph init()
86412111Sralph {
86512111Sralph 	int status;
86612111Sralph 
86712111Sralph 	if ((status = pgetent(line, printer)) < 0) {
86812111Sralph 		log("can't open printer description file");
86912111Sralph 		exit(1);
87012111Sralph 	} else if (status == 0) {
87112111Sralph 		log("unknown printer");
87212111Sralph 		exit(1);
87312111Sralph 	}
87412111Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
87512111Sralph 		LP = DEFDEVLP;
87612111Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
87712463Sralph 		RP = DEFLP;
87812111Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
87912111Sralph 		LO = DEFLOCK;
88012111Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
88112111Sralph 		ST = DEFSTAT;
88212111Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
88312111Sralph 		LF = DEFLOGF;
88412111Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
88512111Sralph 		SD = DEFSPOOL;
88612111Sralph 	if ((DU = pgetnum("du")) < 0)
88712111Sralph 		DU = DEFUID;
88812111Sralph 	if ((FF = pgetstr("ff", &bp)) == NULL)
88912111Sralph 		FF = DEFFF;
89012111Sralph 	if ((PW = pgetnum("pw")) < 0)
89112111Sralph 		PW = DEFWIDTH;
89212111Sralph 	sprintf(&width[2], "%d", PW);
89312111Sralph 	if ((PL = pgetnum("pl")) < 0)
89412111Sralph 		PL = DEFLENGTH;
89512111Sralph 	sprintf(&length[2], "%d", PL);
89612463Sralph 	if ((PX = pgetnum("px")) < 0)
89712463Sralph 		PX = 0;
89812463Sralph 	sprintf(&pxwidth[2], "%d", PX);
89912463Sralph 	if ((PY = pgetnum("py")) < 0)
90012463Sralph 		PY = 0;
90112463Sralph 	sprintf(&pxlength[2], "%d", PY);
90212111Sralph 	RM = pgetstr("rm", &bp);
90312111Sralph 	AF = pgetstr("af", &bp);
90412111Sralph 	OF = pgetstr("of", &bp);
90512111Sralph 	IF = pgetstr("if", &bp);
90612463Sralph 	RF = pgetstr("rf", &bp);
90712111Sralph 	TF = pgetstr("tf", &bp);
90812111Sralph 	DF = pgetstr("df", &bp);
90912111Sralph 	GF = pgetstr("gf", &bp);
91012111Sralph 	VF = pgetstr("vf", &bp);
91112111Sralph 	CF = pgetstr("cf", &bp);
91212111Sralph 	TR = pgetstr("tr", &bp);
91312463Sralph 	RS = pgetflag("rs");
91412111Sralph 	SF = pgetflag("sf");
91512111Sralph 	SH = pgetflag("sh");
91612111Sralph 	SB = pgetflag("sb");
91712111Sralph 	RW = pgetflag("rw");
91812111Sralph 	BR = pgetnum("br");
91912111Sralph 	if ((FC = pgetnum("fc")) < 0)
92012111Sralph 		FC = 0;
92112111Sralph 	if ((FS = pgetnum("fs")) < 0)
92212111Sralph 		FS = 0;
92312111Sralph 	if ((XC = pgetnum("xc")) < 0)
92412111Sralph 		XC = 0;
92512111Sralph 	if ((XS = pgetnum("xs")) < 0)
92612111Sralph 		XS = 0;
92712581Sralph 	tof = !pgetflag("fo");
92812111Sralph }
92912111Sralph 
93012463Sralph /*
93112463Sralph  * Acquire line printer or remote connection.
93212463Sralph  */
933*12877Sralph static
93412463Sralph openpr()
93512463Sralph {
93612463Sralph 	register int i, n;
93712463Sralph 
93812463Sralph 	if (*LP) {
93912463Sralph 		for (i = 1; ; i = i < 32 ? i << 1 : i) {
94012463Sralph 			pfd = open(LP, RW ? FRDWR : FWRONLY, 0);
94112463Sralph 			if (pfd >= 0)
94212463Sralph 				break;
94312463Sralph 			if (errno == ENOENT) {
94412463Sralph 				log("cannot open %s", LP);
94512463Sralph 				exit(1);
94612463Sralph 			}
94712463Sralph 			if (i == 1)
94812463Sralph 				status("waiting for %s to become ready (offline ?)", printer);
94912463Sralph 			sleep(i);
95012463Sralph 		}
95112463Sralph 		if (isatty(pfd))
95212463Sralph 			setty();
95312463Sralph 		status("%s is ready and printing", printer);
95412463Sralph 	} else if (RM != NULL) {
95512463Sralph 		for (i = 1; ; i = i < 512 ? i << 1 : i) {
95612528Sralph 			pfd = getport(RM);
95712463Sralph 			if (pfd >= 0) {
95812463Sralph 				(void) sprintf(line, "\2%s\n", RP);
95912463Sralph 				n = strlen(line);
96012463Sralph 				if (write(pfd, line, n) != n)
96112463Sralph 					break;
96212463Sralph 				if (noresponse())
96312463Sralph 					(void) close(pfd);
96412463Sralph 				else
96512463Sralph 					break;
96612463Sralph 			}
96712463Sralph 			if (i == 1)
96812463Sralph 				status("waiting for %s to come up", RM);
96912463Sralph 			sleep(i);
97012463Sralph 		}
97112463Sralph 		status("sending to %s", RM);
97212463Sralph 		remote = 1;
97312463Sralph 	} else {
97412463Sralph 		log("no line printer device or remote machine name");
97512463Sralph 		exit(1);
97612463Sralph 	}
97712463Sralph 	/*
97812463Sralph 	 * Start up an output filter, if needed.
97912463Sralph 	 */
98012463Sralph 	if (OF) {
98112463Sralph 		int p[2];
98212463Sralph 		char *cp;
98312463Sralph 
98412463Sralph 		pipe(p);
98512463Sralph 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
98612463Sralph 			dup2(p[0], 0);		/* pipe is std in */
98712463Sralph 			dup2(pfd, 1);		/* printer is std out */
98812463Sralph 			for (i = 3; i < NOFILE; i++)
98912463Sralph 				(void) close(i);
99012463Sralph 			if ((cp = rindex(OF, '/')) == NULL)
99112463Sralph 				cp = OF;
99212463Sralph 			else
99312463Sralph 				cp++;
99412463Sralph 			execl(OF, cp, width, length, 0);
99512463Sralph 			log("can't execl output filter %s", OF);
99612463Sralph 			exit(1);
99712463Sralph 		}
99812463Sralph 		(void) close(p[0]);		/* close input side */
99912463Sralph 		ofd = p[1];			/* use pipe for output */
100012463Sralph 	} else {
100112463Sralph 		ofd = pfd;
100212463Sralph 		ofilter = 0;
100312463Sralph 	}
100412463Sralph }
100512463Sralph 
100612111Sralph struct bauds {
100712111Sralph 	int	baud;
100812111Sralph 	int	speed;
100912111Sralph } bauds[] = {
101012111Sralph 	50,	B50,
101112111Sralph 	75,	B75,
101212111Sralph 	110,	B110,
101312111Sralph 	134,	B134,
101412111Sralph 	150,	B150,
101512111Sralph 	200,	B200,
101612111Sralph 	300,	B300,
101712111Sralph 	600,	B600,
101812111Sralph 	1200,	B1200,
101912111Sralph 	1800,	B1800,
102012111Sralph 	2400,	B2400,
102112111Sralph 	4800,	B4800,
102212111Sralph 	9600,	B9600,
102312111Sralph 	19200,	EXTA,
102412111Sralph 	38400,	EXTB,
102512111Sralph 	0,	0
102612111Sralph };
102712111Sralph 
102812111Sralph /*
102912111Sralph  * setup tty lines.
103012111Sralph  */
1031*12877Sralph static
103212111Sralph setty()
103312111Sralph {
103412111Sralph 	struct sgttyb ttybuf;
103512111Sralph 	register struct bauds *bp;
103612111Sralph 
103712111Sralph 	if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
103812111Sralph 		log("cannot set exclusive-use");
103912111Sralph 		exit(1);
104012111Sralph 	}
104112111Sralph 	if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
104212111Sralph 		log("cannot get tty parameters");
104312111Sralph 		exit(1);
104412111Sralph 	}
104512111Sralph 	if (BR > 0) {
104612111Sralph 		for (bp = bauds; bp->baud; bp++)
104712111Sralph 			if (BR == bp->baud)
104812111Sralph 				break;
104912111Sralph 		if (!bp->baud) {
105012111Sralph 			log("illegal baud rate %d", BR);
105112111Sralph 			exit(1);
105212111Sralph 		}
105312111Sralph 		ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
105412111Sralph 	}
105512111Sralph 	if (FC)
105612111Sralph 		ttybuf.sg_flags &= ~FC;
105712111Sralph 	if (FS)
105812111Sralph 		ttybuf.sg_flags |= FS;
105912111Sralph 	if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
106012111Sralph 		log("cannot set tty parameters");
106112111Sralph 		exit(1);
106212111Sralph 	}
106312111Sralph 	if (XC) {
106412111Sralph 		if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
106512111Sralph 			log("cannot set local tty parameters");
106612111Sralph 			exit(1);
106712111Sralph 		}
106812111Sralph 	}
106912111Sralph 	if (XS) {
107012111Sralph 		if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
107112111Sralph 			log("cannot set local tty parameters");
107212111Sralph 			exit(1);
107312111Sralph 		}
107412111Sralph 	}
107512111Sralph }
107612463Sralph 
107712463Sralph /*VARARGS1*/
107812463Sralph static
107912463Sralph status(msg, a1, a2, a3)
108012463Sralph 	char *msg;
108112463Sralph {
108212463Sralph 	register int fd;
108312463Sralph 	char buf[BUFSIZ];
108412463Sralph 
108512463Sralph 	umask(0);
108612463Sralph 	if ((fd = open(ST, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK, 0664)) < 0)
108712463Sralph 		fatal("cannot create status file");
108812463Sralph 	sprintf(buf, msg, a1, a2, a3);
108912463Sralph 	strcat(buf, "\n");
109012463Sralph 	(void) write(fd, buf, strlen(buf));
109112463Sralph 	(void) close(fd);
109212463Sralph }
1093