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