xref: /csrg-svn/usr.sbin/lpr/lpd/printjob.c (revision 15552)
113954Ssam #ifndef lint
2*15552Sralph static char sccsid[] = "@(#)printjob.c	4.15 (Berkeley) 11/18/83";
313954Ssam #endif
413954Ssam 
512111Sralph /*
612111Sralph  * printjob -- print jobs in the queue.
712111Sralph  *
812111Sralph  *	NOTE: the lock file is used to pass information to lpq and lprm.
912111Sralph  *	it does not need to be removed because file locks are dynamic.
1012111Sralph  */
1112111Sralph 
1212111Sralph #include "lp.h"
1312111Sralph 
1412877Sralph #define DORETURN	0		/* absorb fork error */
1512877Sralph #define DOABORT		1		/* abort if dofork fails */
1612111Sralph 
1712877Sralph static char	title[80];		/* ``pr'' title */
1812877Sralph static FILE	*cfp;			/* control file */
1912877Sralph static int	pfd;			/* printer file descriptor */
2012877Sralph static int	ofd;			/* output filter file descriptor */
2112877Sralph static int	lfd;			/* lock file descriptor */
2212877Sralph static int	pid;			/* pid of lpd process */
2312877Sralph static int	prchild;		/* id of pr process */
2412877Sralph static int	child;			/* id of any filters */
2512877Sralph static int	ofilter;		/* id of output filter, if any */
2612877Sralph static int	tof;			/* true if at top of form */
2714150Sralph static int	count;			/* Number of files actually printed */
2812877Sralph static int	remote;			/* true if sending files to remote */
2912111Sralph 
3014150Sralph static char	fromhost[32];		/* user's host machine */
3112877Sralph static char	logname[32];		/* user's login name */
32*15552Sralph static char	jobname[100];		/* job or file name */
3312877Sralph static char	class[32];		/* classification field */
3412877Sralph static char	width[10] = "-w";	/* page width in characters */
3512877Sralph static char	length[10] = "-l";	/* page length in lines */
3612877Sralph static char	pxwidth[10] = "-x";	/* page width in pixels */
3712877Sralph static char	pxlength[10] = "-y";	/* page length in pixels */
3812877Sralph static char	indent[10] = "-i0";	/* indentation size in characters */
3912111Sralph 
4012111Sralph printjob()
4112111Sralph {
4212111Sralph 	struct stat stb;
4312111Sralph 	register struct queue *q, **qp;
4412111Sralph 	struct queue **queue;
4512111Sralph 	register int i, nitems;
4612111Sralph 	long pidoff;
4712111Sralph 	extern int onintr();
4812111Sralph 
4912111Sralph 	init();					/* set up capabilities */
5013442Sralph 	(void) write(1, "", 1);			/* ack that daemon is started */
5112877Sralph 	(void) close(1);			/* set up log file */
5212877Sralph 	(void) close(2);
5313148Ssam 	if (open(LF, O_WRONLY|O_APPEND) < 0)
5413148Ssam 		(void) open("/dev/null", O_WRONLY);
5512877Sralph 	dup(1);
5612463Sralph 	pid = getpid();				/* for use with lprm */
5712111Sralph 	setpgrp(0, pid);
5814709Sralph 	signal(SIGHUP, onintr);
5913148Ssam 	signal(SIGINT, onintr);
6014709Sralph 	signal(SIGQUIT, onintr);
6114709Sralph 	signal(SIGTERM, onintr);
6212111Sralph 
6312111Sralph 	/*
6412111Sralph 	 * uses short form file names
6512111Sralph 	 */
6612111Sralph 	if (chdir(SD) < 0) {
6712111Sralph 		log("cannot chdir to %s", SD);
6812111Sralph 		exit(1);
6912111Sralph 	}
7012463Sralph 	if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
7112463Sralph 		exit(0);		/* printing disabled */
7214150Sralph 	lfd = open(LO, O_WRONLY|O_CREAT, 0644);
7313169Sralph 	if (lfd < 0) {
7413169Sralph 		log("cannot create %s", LO);
7513169Sralph 		exit(1);
7613169Sralph 	}
7713169Sralph 	if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
7812111Sralph 		if (errno == EWOULDBLOCK)	/* active deamon present */
7912111Sralph 			exit(0);
8013169Sralph 		log("cannot lock %s", LO);
8112111Sralph 		exit(1);
8212111Sralph 	}
8313148Ssam 	ftruncate(lfd, 0);
8412111Sralph 	/*
8512111Sralph 	 * write process id for others to know
8612111Sralph 	 */
8712111Sralph 	sprintf(line, "%u\n", pid);
8812111Sralph 	pidoff = i = strlen(line);
8912463Sralph 	if (write(lfd, line, i) != i) {
9012111Sralph 		log("cannot write daemon pid");
9112111Sralph 		exit(1);
9212111Sralph 	}
9312111Sralph 	/*
9412111Sralph 	 * search the spool directory for work and sort by queue order.
9512111Sralph 	 */
9612111Sralph 	if ((nitems = getq(&queue)) < 0) {
9712111Sralph 		log("can't scan spool directory %s", SD);
9812111Sralph 		exit(1);
9912111Sralph 	}
10012463Sralph 	if (nitems == 0)		/* no work to do */
10112111Sralph 		exit(0);
10213169Sralph 	if (stb.st_mode & 01) {		/* reset queue flag */
10313169Sralph 		if (fchmod(lfd, stb.st_mode & 0776) < 0)
10413169Sralph 			log("cannot chmod %s", LO);
10513169Sralph 	}
10612463Sralph 	openpr();			/* open printer or remote */
10712463Sralph again:
10812111Sralph 	/*
10912111Sralph 	 * we found something to do now do it --
11012111Sralph 	 *    write the name of the current control file into the lock file
11112111Sralph 	 *    so the spool queue program can tell what we're working on
11212111Sralph 	 */
11312111Sralph 	for (qp = queue; nitems--; free((char *) q)) {
11412111Sralph 		q = *qp++;
11512111Sralph 		if (stat(q->q_name, &stb) < 0)
11612111Sralph 			continue;
11712463Sralph 	restart:
11812111Sralph 		(void) lseek(lfd, pidoff, 0);
11912111Sralph 		(void) sprintf(line, "%s\n", q->q_name);
12012111Sralph 		i = strlen(line);
12112111Sralph 		if (write(lfd, line, i) != i)
12212111Sralph 			log("can't write (%d) control file name", errno);
12312111Sralph 		if (!remote)
12412111Sralph 			i = printit(q->q_name);
12512111Sralph 		else
12612111Sralph 			i = sendit(q->q_name);
12712463Sralph 		/*
12813169Sralph 		 * Check to see if we are supposed to stop printing or
12913169Sralph 		 * if we are to rebuild the queue.
13012463Sralph 		 */
13113169Sralph 		if (fstat(lfd, &stb) == 0) {
13213169Sralph 			if (stb.st_mode & 0100)
13313169Sralph 				goto done;
13413169Sralph 			if (stb.st_mode & 01) {
13513169Sralph 				for (free((char *) q); nitems--; free((char *) q))
13613169Sralph 					q = *qp++;
13713169Sralph 				if (fchmod(lfd, stb.st_mode & 0776) < 0)
13813169Sralph 					log("cannot chmod %s", LO);
13913169Sralph 				break;
14013169Sralph 			}
14113169Sralph 		}
14214150Sralph 		if (i == 0)		/* file ok and printed */
14314150Sralph 			count++;
14414150Sralph 		else if (i > 0) {	/* try reprinting the job */
14512111Sralph 			log("restarting");
14612111Sralph 			if (ofilter > 0) {
14712111Sralph 				kill(ofilter, SIGCONT);	/* to be sure */
14812111Sralph 				(void) close(ofd);
14912111Sralph 				while ((i = wait(0)) > 0 && i != ofilter)
15012111Sralph 					;
15112111Sralph 				ofilter = 0;
15212111Sralph 			}
15312463Sralph 			(void) close(pfd);	/* close printer */
15412463Sralph 			(void) lseek(lfd, pidoff, 0);
15512463Sralph 			if (write(lfd, "\n", 1) != 1)
15612463Sralph 				log("can't write (%d) control file name", errno);
15712463Sralph 			openpr();		/* try to reopen printer */
15812111Sralph 			goto restart;
15912111Sralph 		}
16012111Sralph 	}
16112111Sralph 	free((char *) queue);
16212463Sralph 	/*
16312463Sralph 	 * search the spool directory for more work.
16412463Sralph 	 */
16512463Sralph 	if ((nitems = getq(&queue)) < 0) {
16612463Sralph 		log("can't scan spool directory %s", SD);
16712463Sralph 		exit(1);
16812463Sralph 	}
16912463Sralph 	if (nitems == 0) {		/* no more work to do */
17012463Sralph 	done:
17114150Sralph 		if (count > 0) {	/* Files actually printed */
17214150Sralph 			if (!SF && !tof)
17314150Sralph 				(void) write(ofd, FF, strlen(FF));
17414150Sralph 			if (TR != NULL)		/* output trailer */
17514150Sralph 				(void) write(ofd, TR, strlen(TR));
17614150Sralph 		}
17712463Sralph 		exit(0);
17812463Sralph 	}
17912111Sralph 	goto again;
18012111Sralph }
18112111Sralph 
18212111Sralph char	fonts[4][50];	/* fonts for troff */
18312111Sralph 
18412111Sralph static char ifonts[4][18] = {
18512111Sralph 	"/usr/lib/vfont/R",
18612111Sralph 	"/usr/lib/vfont/I",
18712111Sralph 	"/usr/lib/vfont/B",
18812111Sralph 	"/usr/lib/vfont/S"
18912111Sralph };
19012111Sralph 
19112111Sralph /*
19212111Sralph  * The remaining part is the reading of the control file (cf)
19312111Sralph  * and performing the various actions.
19412111Sralph  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
19512111Sralph  * -1 if a non-recoverable error occured.
19612111Sralph  */
19712877Sralph static
19812111Sralph printit(file)
19912111Sralph 	char *file;
20012111Sralph {
20112111Sralph 	register int i;
20212111Sralph 	int bombed = 0;
20312111Sralph 
20412111Sralph 	/*
20512111Sralph 	 * open control file
20612111Sralph 	 */
20712111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
20812111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
20912111Sralph 		return(0);
21012111Sralph 	}
21112111Sralph 	/*
21212111Sralph 	 * Reset troff fonts.
21312111Sralph 	 */
21412111Sralph 	for (i = 0; i < 4; i++)
21512111Sralph 		strcpy(fonts[i], ifonts[i]);
21612111Sralph 
21712111Sralph 	/*
21812111Sralph 	 *      read the control file for work to do
21912111Sralph 	 *
22012111Sralph 	 *      file format -- first character in the line is a command
22112111Sralph 	 *      rest of the line is the argument.
22212111Sralph 	 *      valid commands are:
22312111Sralph 	 *
22412111Sralph 	 *		J -- "job name" on banner page
22512111Sralph 	 *		C -- "class name" on banner page
22612111Sralph 	 *              L -- "literal" user's name to print on banner
22712111Sralph 	 *		T -- "title" for pr
22812111Sralph 	 *		H -- "host name" of machine where lpr was done
22912111Sralph 	 *              P -- "person" user's login name
23012581Sralph 	 *              I -- "indent" amount to indent output
23112111Sralph 	 *              f -- "file name" name of text file to print
23212111Sralph 	 *		l -- "file name" text file with control chars
23312111Sralph 	 *		p -- "file name" text file to print with pr(1)
23412111Sralph 	 *		t -- "file name" troff(1) file to print
23513233Sralph 	 *		n -- "file name" ditroff(1) file to print
23612111Sralph 	 *		d -- "file name" dvi file to print
23712111Sralph 	 *		g -- "file name" plot(1G) file to print
23812111Sralph 	 *		v -- "file name" plain raster file to print
23912111Sralph 	 *		c -- "file name" cifplot file to print
24012111Sralph 	 *		1 -- "R font file" for troff
24112111Sralph 	 *		2 -- "I font file" for troff
24212111Sralph 	 *		3 -- "B font file" for troff
24312111Sralph 	 *		4 -- "S font file" for troff
24412111Sralph 	 *		N -- "name" of file (used by lpq)
24512111Sralph 	 *              U -- "unlink" name of file to remove
24612111Sralph 	 *                    (after we print it. (Pass 2 only)).
24712111Sralph 	 *		M -- "mail" to user when done printing
24812111Sralph 	 *
24912111Sralph 	 *      getline reads a line and expands tabs to blanks
25012111Sralph 	 */
25112111Sralph 
25212111Sralph 	/* pass 1 */
25312111Sralph 
25412111Sralph 	while (getline(cfp))
25512111Sralph 		switch (line[0]) {
25612111Sralph 		case 'H':
25714150Sralph 			strcpy(fromhost, line+1);
25812111Sralph 			if (class[0] == '\0')
259*15552Sralph 				strncpy(class, line+1, sizeof(class)-1);
26012111Sralph 			continue;
26112111Sralph 
26212111Sralph 		case 'P':
263*15552Sralph 			strncpy(logname, line+1, sizeof(logname)-1);
26412463Sralph 			if (RS) {			/* restricted */
26512463Sralph 				if (getpwnam(logname) == (struct passwd *)0) {
26612463Sralph 					bombed = 2;
26712463Sralph 					sendmail(bombed);
26812463Sralph 					goto pass2;
26912463Sralph 				}
27012463Sralph 			}
27112111Sralph 			continue;
27212111Sralph 
27312111Sralph 		case 'J':
27412111Sralph 			if (line[1] != '\0')
275*15552Sralph 				strncpy(jobname, line+1, sizeof(jobname)-1);
27612111Sralph 			else
27712111Sralph 				strcpy(jobname, " ");
27812111Sralph 			continue;
27912111Sralph 
28012111Sralph 		case 'C':
28112111Sralph 			if (line[1] != '\0')
282*15552Sralph 				strncpy(class, line+1, sizeof(class)-1);
28312111Sralph 			else if (class[0] == '\0')
28412111Sralph 				gethostname(class, sizeof (class));
28512111Sralph 			continue;
28612111Sralph 
28712111Sralph 		case 'T':	/* header title for pr */
288*15552Sralph 			strncpy(title, line+1, sizeof(title)-1);
28912111Sralph 			continue;
29012111Sralph 
29112111Sralph 		case 'L':	/* identification line */
29212111Sralph 			if (!SH)
29312111Sralph 				banner(line+1, jobname);
29412111Sralph 			continue;
29512111Sralph 
29612111Sralph 		case '1':	/* troff fonts */
29712111Sralph 		case '2':
29812111Sralph 		case '3':
29912111Sralph 		case '4':
30012111Sralph 			if (line[1] != '\0')
30112111Sralph 				strcpy(fonts[line[0]-'1'], line+1);
30212111Sralph 			continue;
30312111Sralph 
30412111Sralph 		case 'W':	/* page width */
305*15552Sralph 			strncpy(width+2, line+1, sizeof(width)-3);
30612111Sralph 			continue;
30712111Sralph 
30812581Sralph 		case 'I':	/* indent amount */
309*15552Sralph 			strncpy(indent+2, line+1, sizeof(indent)-3);
31012581Sralph 			continue;
31112581Sralph 
31212111Sralph 		default:	/* some file to print */
31312111Sralph 			if ((i = print(line[0], line+1)) > 0) {
31412111Sralph 				(void) fclose(cfp);
31512111Sralph 				return(1);
31612111Sralph 			} else if (i < 0)
31712111Sralph 				bombed = 1;
31812111Sralph 			title[0] = '\0';
31912111Sralph 			continue;
32012111Sralph 
32112111Sralph 		case 'N':
32212111Sralph 		case 'U':
32312111Sralph 		case 'M':
32412111Sralph 			continue;
32512111Sralph 		}
32612111Sralph 
32712111Sralph 	/* pass 2 */
32812111Sralph 
32912463Sralph pass2:
33012111Sralph 	fseek(cfp, 0L, 0);
33112111Sralph 	while (getline(cfp))
33212111Sralph 		switch (line[0]) {
33312111Sralph 		case 'M':
33412463Sralph 			if (bombed != 2)		/* already sent if 2 */
33512463Sralph 				sendmail(bombed);
33612111Sralph 			continue;
33712111Sralph 
33812111Sralph 		case 'U':
33912111Sralph 			(void) unlink(line+1);
34012111Sralph 		}
34112111Sralph 	/*
34212111Sralph 	 * clean-up incase another control file exists
34312111Sralph 	 */
34412111Sralph 	(void) fclose(cfp);
34512111Sralph 	(void) unlink(file);
34614150Sralph 	return(bombed ? -1 : 0);
34712111Sralph }
34812111Sralph 
34912111Sralph /*
35012111Sralph  * Print a file.
35113233Sralph  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
35212111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
35312111Sralph  * 0 if all is well.
35412111Sralph  * Note: all filters take stdin as the file, stdout as the printer,
35512111Sralph  * stderr as the log file, and must not ignore SIGINT.
35612111Sralph  */
35712877Sralph static
35812111Sralph print(format, file)
35912111Sralph 	int format;
36012111Sralph 	char *file;
36112111Sralph {
36212111Sralph 	register int n, fi, fo;
36312111Sralph 	register char *prog;
36412111Sralph 	char *av[15], buf[BUFSIZ];
36512111Sralph 	int pid, p[2], stopped = 0;
36612111Sralph 	union wait status;
36712111Sralph 
36813148Ssam 	if ((fi = open(file, O_RDONLY)) < 0) {
36912111Sralph 		log("%s: open failure <errno = %d>", file, errno);
37012111Sralph 		return(-1);
37112111Sralph 	}
37212111Sralph 	if (!SF && !tof) {		/* start on a fresh page */
37312111Sralph 		(void) write(ofd, FF, strlen(FF));
37412111Sralph 		tof = 1;
37512111Sralph 	}
37612111Sralph 	if (IF == NULL && (format == 'f' || format == 'l')) {
37712111Sralph 		tof = 0;
37812111Sralph 		while ((n = read(fi, buf, BUFSIZ)) > 0)
37912111Sralph 			if (write(ofd, buf, n) != n) {
38012111Sralph 				(void) close(fi);
38112111Sralph 				return(1);
38212111Sralph 			}
38312111Sralph 		(void) close(fi);
38412111Sralph 		return(0);
38512111Sralph 	}
38612111Sralph 	switch (format) {
38712111Sralph 	case 'p':	/* print file using 'pr' */
38812111Sralph 		if (IF == NULL) {	/* use output filter */
38912111Sralph 			prog = PR;
39012111Sralph 			av[0] = "pr";
39112111Sralph 			av[1] = width;
39212111Sralph 			av[2] = length;
39312111Sralph 			av[3] = "-h";
39412111Sralph 			av[4] = *title ? title : " ";
39512111Sralph 			av[5] = 0;
39612111Sralph 			fo = ofd;
39712111Sralph 			goto start;
39812111Sralph 		}
39912111Sralph 		pipe(p);
40012111Sralph 		if ((prchild = dofork(DORETURN)) == 0) {	/* child */
40112111Sralph 			dup2(fi, 0);		/* file is stdin */
40212111Sralph 			dup2(p[1], 1);		/* pipe is stdout */
40312111Sralph 			for (n = 3; n < NOFILE; n++)
40412111Sralph 				(void) close(n);
40512111Sralph 			execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
40612111Sralph 			log("cannot execl %s", PR);
40712111Sralph 			exit(2);
40812111Sralph 		}
40912111Sralph 		(void) close(p[1]);		/* close output side */
41012111Sralph 		(void) close(fi);
41112111Sralph 		if (prchild < 0) {
41212111Sralph 			prchild = 0;
41312111Sralph 			(void) close(p[0]);
41412111Sralph 			return(-1);
41512111Sralph 		}
41612111Sralph 		fi = p[0];			/* use pipe for input */
41712111Sralph 	case 'f':	/* print plain text file */
41812111Sralph 		prog = IF;
41912111Sralph 		av[1] = width;
42012111Sralph 		av[2] = length;
42112581Sralph 		av[3] = indent;
42212581Sralph 		n = 4;
42312111Sralph 		break;
42412111Sralph 	case 'l':	/* like 'f' but pass control characters */
42512111Sralph 		prog = IF;
42614325Sralph 		av[1] = "-c";
42712111Sralph 		av[2] = width;
42812111Sralph 		av[3] = length;
42912581Sralph 		av[4] = indent;
43012581Sralph 		n = 5;
43112111Sralph 		break;
43212463Sralph 	case 'r':	/* print a fortran text file */
43312463Sralph 		prog = RF;
43412463Sralph 		av[1] = width;
43512463Sralph 		av[2] = length;
43612463Sralph 		n = 3;
43712463Sralph 		break;
43812111Sralph 	case 't':	/* print troff output */
43913233Sralph 	case 'n':	/* print ditroff output */
44012463Sralph 	case 'd':	/* print tex output */
44112111Sralph 		(void) unlink(".railmag");
44212463Sralph 		if ((fo = creat(".railmag", FILMOD)) < 0) {
44312111Sralph 			log("cannot create .railmag");
44412111Sralph 			(void) unlink(".railmag");
44512111Sralph 		} else {
44612111Sralph 			for (n = 0; n < 4; n++) {
44712111Sralph 				if (fonts[n][0] != '/')
44812111Sralph 					(void) write(fo, "/usr/lib/vfont/", 15);
44912111Sralph 				(void) write(fo, fonts[n], strlen(fonts[n]));
45012111Sralph 				(void) write(fo, "\n", 1);
45112111Sralph 			}
45212111Sralph 			(void) close(fo);
45312111Sralph 		}
45413233Sralph 		prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
45512463Sralph 		av[1] = pxwidth;
45612463Sralph 		av[2] = pxlength;
45712463Sralph 		n = 3;
45812111Sralph 		break;
45912111Sralph 	case 'c':	/* print cifplot output */
46012111Sralph 		prog = CF;
46112463Sralph 		av[1] = pxwidth;
46212463Sralph 		av[2] = pxlength;
46312463Sralph 		n = 3;
46412111Sralph 		break;
46512111Sralph 	case 'g':	/* print plot(1G) output */
46612111Sralph 		prog = GF;
46712463Sralph 		av[1] = pxwidth;
46812463Sralph 		av[2] = pxlength;
46912463Sralph 		n = 3;
47012111Sralph 		break;
47112111Sralph 	case 'v':	/* print raster output */
47212111Sralph 		prog = VF;
47312463Sralph 		av[1] = pxwidth;
47412463Sralph 		av[2] = pxlength;
47512463Sralph 		n = 3;
47612111Sralph 		break;
47712111Sralph 	default:
47812111Sralph 		(void) close(fi);
47912111Sralph 		log("illegal format character '%c'", format);
48012111Sralph 		return(-1);
48112111Sralph 	}
48212111Sralph 	if ((av[0] = rindex(prog, '/')) != NULL)
48312111Sralph 		av[0]++;
48412111Sralph 	else
48512111Sralph 		av[0] = prog;
48612111Sralph 	av[n++] = "-n";
48712111Sralph 	av[n++] = logname;
48812111Sralph 	av[n++] = "-h";
48914150Sralph 	av[n++] = fromhost;
49012111Sralph 	av[n++] = AF;
49112111Sralph 	av[n] = 0;
49212111Sralph 	fo = pfd;
49312111Sralph 	if (ofilter > 0) {		/* stop output filter */
49412111Sralph 		write(ofd, "\031\1", 2);
49512111Sralph 		while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
49612111Sralph 			;
49712111Sralph 		if (status.w_stopval != WSTOPPED) {
49812111Sralph 			(void) close(fi);
49912111Sralph 			log("output filter died (%d)", status.w_retcode);
50012111Sralph 			return(1);
50112111Sralph 		}
50212111Sralph 		stopped++;
50312111Sralph 	}
50412111Sralph start:
50512111Sralph 	if ((child = dofork(DORETURN)) == 0) {	/* child */
50612111Sralph 		dup2(fi, 0);
50712111Sralph 		dup2(fo, 1);
50812111Sralph 		for (n = 3; n < NOFILE; n++)
50912111Sralph 			(void) close(n);
51012111Sralph 		execv(prog, av);
51112111Sralph 		log("cannot execl %s", prog);
51212111Sralph 		exit(2);
51312111Sralph 	}
51412111Sralph 	(void) close(fi);
51512111Sralph 	if (child < 0)
51612111Sralph 		status.w_retcode = 100;
51712111Sralph 	else
51812111Sralph 		while ((pid = wait(&status)) > 0 && pid != child)
51912111Sralph 			;
52012111Sralph 	child = 0;
52112111Sralph 	prchild = 0;
52212111Sralph 	if (stopped) {		/* restart output filter */
52312111Sralph 		if (kill(ofilter, SIGCONT) < 0) {
52412111Sralph 			log("cannot restart output filter");
52512111Sralph 			exit(1);
52612111Sralph 		}
52712111Sralph 	}
52812111Sralph 	tof = 0;
52912111Sralph 	if (!WIFEXITED(status) || status.w_retcode > 1) {
53012111Sralph 		log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode);
53112111Sralph 		return(-1);
53212111Sralph 	} else if (status.w_retcode == 1)
53312111Sralph 		return(1);
53412111Sralph 	tof = 1;
53512111Sralph 	return(0);
53612111Sralph }
53712111Sralph 
53812111Sralph /*
53912111Sralph  * Send the daemon control file (cf) and any data files.
54012111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
54112111Sralph  * 0 if all is well.
54212111Sralph  */
54312877Sralph static
54412111Sralph sendit(file)
54512111Sralph 	char *file;
54612111Sralph {
54712111Sralph 	register int linelen, err = 0;
54812111Sralph 	char last[132];
54912111Sralph 
55012111Sralph 	/*
55112111Sralph 	 * open control file
55212111Sralph 	 */
55312111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
55412111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
55512111Sralph 		return(0);
55612111Sralph 	}
55712111Sralph 	/*
55812111Sralph 	 *      read the control file for work to do
55912111Sralph 	 *
56012111Sralph 	 *      file format -- first character in the line is a command
56112111Sralph 	 *      rest of the line is the argument.
56212111Sralph 	 *      commands of interest are:
56312111Sralph 	 *
56412111Sralph 	 *            a-z -- "file name" name of file to print
56512111Sralph 	 *              U -- "unlink" name of file to remove
56612111Sralph 	 *                    (after we print it. (Pass 2 only)).
56712111Sralph 	 */
56812111Sralph 
56912111Sralph 	/*
57012111Sralph 	 * pass 1
57112111Sralph 	 */
57212111Sralph 	while (getline(cfp)) {
57312111Sralph 	again:
57412111Sralph 		if (line[0] >= 'a' && line[0] <= 'z') {
57512111Sralph 			strcpy(last, line);
57612111Sralph 			while (linelen = getline(cfp))
57712111Sralph 				if (strcmp(last, line))
57812111Sralph 					break;
57912111Sralph 			if ((err = sendfile('\3', last+1)) > 0) {
58012111Sralph 				(void) fclose(cfp);
58112111Sralph 				return(1);
58212111Sralph 			} else if (err)
58312111Sralph 				break;
58412111Sralph 			if (linelen)
58512111Sralph 				goto again;
58612111Sralph 			break;
58712111Sralph 		}
58812111Sralph 	}
58912111Sralph 	if (!err && sendfile('\2', file) > 0) {
59012111Sralph 		(void) fclose(cfp);
59112111Sralph 		return(1);
59212111Sralph 	}
59312111Sralph 	/*
59412111Sralph 	 * pass 2
59512111Sralph 	 */
59612111Sralph 	fseek(cfp, 0L, 0);
59712111Sralph 	while (getline(cfp))
59812111Sralph 		if (line[0] == 'U')
59912111Sralph 			(void) unlink(line+1);
60012111Sralph 	/*
60112111Sralph 	 * clean-up incase another control file exists
60212111Sralph 	 */
60312111Sralph 	(void) fclose(cfp);
60412111Sralph 	(void) unlink(file);
60512111Sralph 	return(0);
60612111Sralph }
60712111Sralph 
60812111Sralph /*
60912111Sralph  * Send a data file to the remote machine and spool it.
61012111Sralph  * Return positive if we should try resending.
61112111Sralph  */
61212877Sralph static
61312111Sralph sendfile(type, file)
61412111Sralph 	char type, *file;
61512111Sralph {
61612111Sralph 	register int f, i, amt;
61712111Sralph 	struct stat stb;
61812111Sralph 	char buf[BUFSIZ];
61912111Sralph 	int sizerr;
62012111Sralph 
62113148Ssam 	if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) {
62212111Sralph 		log("file (%s) open failure <errno = %d>", file, errno);
62312111Sralph 		return(-1);
62412111Sralph 	}
62512111Sralph 	(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
62612111Sralph 	amt = strlen(buf);
62712692Sralph 	if (write(pfd, buf, amt) != amt) {
62812692Sralph 		(void) close(f);
62912111Sralph 		return(1);
63012692Sralph 	}
63112692Sralph 	if (noresponse()) {
63212692Sralph 		(void) close(f);
63312111Sralph 		return(1);
63412692Sralph 	}
63512111Sralph 	sizerr = 0;
63612111Sralph 	for (i = 0; i < stb.st_size; i += BUFSIZ) {
63712111Sralph 		amt = BUFSIZ;
63812111Sralph 		if (i + amt > stb.st_size)
63912111Sralph 			amt = stb.st_size - i;
64012111Sralph 		if (sizerr == 0 && read(f, buf, amt) != amt)
64112111Sralph 			sizerr = 1;
64212692Sralph 		if (write(pfd, buf, amt) != amt) {
64312692Sralph 			(void) close(f);
64412111Sralph 			return(1);
64512692Sralph 		}
64612111Sralph 	}
64712111Sralph 	(void) close(f);
64812111Sralph 	if (sizerr) {
64912111Sralph 		log("%s: changed size", file);
65012111Sralph 		(void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
65112111Sralph 		return(-1);
65212111Sralph 	}
65312111Sralph 	if (write(pfd, "", 1) != 1)
65412111Sralph 		return(1);
65512111Sralph 	if (noresponse())
65612111Sralph 		return(1);
65712111Sralph 	return(0);
65812111Sralph }
65912111Sralph 
66012111Sralph /*
66112111Sralph  * Check to make sure there have been no errors and that both programs
66212111Sralph  * are in sync with eachother.
66312111Sralph  * Return non-zero if the connection was lost.
66412111Sralph  */
66512111Sralph static
66612111Sralph noresponse()
66712111Sralph {
66812111Sralph 	char resp;
66912111Sralph 
67012111Sralph 	if (read(pfd, &resp, 1) != 1 || resp != '\0') {
67112111Sralph 		log("lost connection or error in recvjob");
67212111Sralph 		return(1);
67312111Sralph 	}
67412111Sralph 	return(0);
67512111Sralph }
67612111Sralph 
67712111Sralph /*
67812111Sralph  * Banner printing stuff
67912111Sralph  */
68012877Sralph static
68112111Sralph banner(name1, name2)
68212111Sralph 	char *name1, *name2;
68312111Sralph {
68412111Sralph 	time_t tvec;
68512111Sralph 	extern char *ctime();
68612111Sralph 
68712111Sralph 	time(&tvec);
68812111Sralph 	if (!SF && !tof)
68912111Sralph 		(void) write(ofd, FF, strlen(FF));
69012111Sralph 	if (SB) {	/* short banner only */
69112111Sralph 		if (class[0]) {
69212111Sralph 			(void) write(ofd, class, strlen(class));
69312111Sralph 			(void) write(ofd, ":", 1);
69412111Sralph 		}
69512111Sralph 		(void) write(ofd, name1, strlen(name1));
69612111Sralph 		(void) write(ofd, "  Job: ", 7);
69712111Sralph 		(void) write(ofd, name2, strlen(name2));
69812111Sralph 		(void) write(ofd, "  Date: ", 8);
69912111Sralph 		(void) write(ofd, ctime(&tvec), 24);
70012111Sralph 		(void) write(ofd, "\n", 1);
70112111Sralph 	} else {	/* normal banner */
70212111Sralph 		(void) write(ofd, "\n\n\n", 3);
70312111Sralph 		scan_out(ofd, name1, '\0');
70412111Sralph 		(void) write(ofd, "\n\n", 2);
70512111Sralph 		scan_out(ofd, name2, '\0');
70612111Sralph 		if (class[0]) {
70712111Sralph 			(void) write(ofd,"\n\n\n",3);
70812111Sralph 			scan_out(ofd, class, '\0');
70912111Sralph 		}
71012111Sralph 		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
71112111Sralph 		(void) write(ofd, name2, strlen(name2));
71212111Sralph 		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
71312111Sralph 		(void) write(ofd, ctime(&tvec), 24);
71412111Sralph 		(void) write(ofd, "\n", 1);
71512111Sralph 	}
71612111Sralph 	if (!SF)
71712111Sralph 		(void) write(ofd, FF, strlen(FF));
71812111Sralph 	tof = 1;
71912111Sralph }
72012111Sralph 
72112877Sralph static char *
72212111Sralph scnline(key, p, c)
72312111Sralph 	register char key, *p;
72412111Sralph 	char c;
72512111Sralph {
72612111Sralph 	register scnwidth;
72712111Sralph 
72812111Sralph 	for (scnwidth = WIDTH; --scnwidth;) {
72912111Sralph 		key <<= 1;
73012111Sralph 		*p++ = key & 0200 ? c : BACKGND;
73112111Sralph 	}
73212111Sralph 	return (p);
73312111Sralph }
73412111Sralph 
73512111Sralph #define TRC(q)	(((q)-' ')&0177)
73612111Sralph 
73712877Sralph static
73812111Sralph scan_out(scfd, scsp, dlm)
73912111Sralph 	int scfd;
74012111Sralph 	char *scsp, dlm;
74112111Sralph {
74212111Sralph 	register char *strp;
74312111Sralph 	register nchrs, j;
74412111Sralph 	char outbuf[LINELEN+1], *sp, c, cc;
74512111Sralph 	int d, scnhgt;
74612111Sralph 	extern char scnkey[][HEIGHT];	/* in lpdchar.c */
74712111Sralph 
74812111Sralph 	for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
74912111Sralph 		strp = &outbuf[0];
75012111Sralph 		sp = scsp;
75112111Sralph 		for (nchrs = 0; ; ) {
75212111Sralph 			d = dropit(c = TRC(cc = *sp++));
75312111Sralph 			if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
75412111Sralph 				for (j = WIDTH; --j;)
75512111Sralph 					*strp++ = BACKGND;
75612111Sralph 			else
75712111Sralph 				strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
75812111Sralph 			if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
75912111Sralph 				break;
76012111Sralph 			*strp++ = BACKGND;
76112111Sralph 			*strp++ = BACKGND;
76212111Sralph 		}
76312111Sralph 		while (*--strp == BACKGND && strp >= outbuf)
76412111Sralph 			;
76512111Sralph 		strp++;
76612111Sralph 		*strp++ = '\n';
76712111Sralph 		(void) write(scfd, outbuf, strp-outbuf);
76812111Sralph 	}
76912111Sralph }
77012111Sralph 
77112877Sralph static
77212111Sralph dropit(c)
77312111Sralph 	char c;
77412111Sralph {
77512111Sralph 	switch(c) {
77612111Sralph 
77712111Sralph 	case TRC('_'):
77812111Sralph 	case TRC(';'):
77912111Sralph 	case TRC(','):
78012111Sralph 	case TRC('g'):
78112111Sralph 	case TRC('j'):
78212111Sralph 	case TRC('p'):
78312111Sralph 	case TRC('q'):
78412111Sralph 	case TRC('y'):
78512111Sralph 		return (DROP);
78612111Sralph 
78712111Sralph 	default:
78812111Sralph 		return (0);
78912111Sralph 	}
79012111Sralph }
79112111Sralph 
79212111Sralph /*
79312111Sralph  * sendmail ---
79412111Sralph  *   tell people about job completion
79512111Sralph  */
79612877Sralph static
79712111Sralph sendmail(bombed)
79812111Sralph 	int bombed;
79912111Sralph {
80012111Sralph 	static int p[2];
80112111Sralph 	register int i;
80212111Sralph 	int stat;
80312111Sralph 	register char *cp;
80412111Sralph 	char buf[100];
80512111Sralph 
80612111Sralph 	pipe(p);
80712111Sralph 	if ((stat = dofork(DORETURN)) == 0) {		/* child */
80812111Sralph 		dup2(p[0], 0);
80912111Sralph 		for (i = 3; i < NOFILE; i++)
81012111Sralph 			(void) close(i);
81112111Sralph 		if ((cp = rindex(MAIL, '/')) != NULL)
81212111Sralph 			cp++;
81312111Sralph 		else
81412111Sralph 			cp = MAIL;
81514150Sralph 		sprintf(buf, "%s@%s", line+1, fromhost);
81612111Sralph 		execl(MAIL, cp, buf, 0);
81712111Sralph 		exit(0);
81812111Sralph 	} else if (stat > 0) {				/* parent */
81912111Sralph 		dup2(p[1], 1);
82014150Sralph 		printf("To: %s@%s\n", line+1, fromhost);
82112111Sralph 		printf("Subject: printer job\n\n");
82212111Sralph 		printf("Your printer job ");
82312111Sralph 		if (*jobname)
82412111Sralph 			printf("(%s) ", jobname);
82512463Sralph 		switch (bombed) {
82612463Sralph 		case 0:
82712463Sralph 			printf("\ncompleted successfully\n");
82812463Sralph 			break;
82912463Sralph 		default:
83012463Sralph 		case 1:
83112463Sralph 			printf("\ncould not be printed\n");
83212463Sralph 			break;
83312463Sralph 		case 2:
83412463Sralph 			printf("\ncould not be printed without an account on %s\n", host);
83512463Sralph 			break;
83612463Sralph 		}
83712111Sralph 		fflush(stdout);
83812111Sralph 		(void) close(1);
83912111Sralph 	}
84012111Sralph 	(void) close(p[0]);
84112111Sralph 	(void) close(p[1]);
84212111Sralph 	wait(&stat);
84312111Sralph }
84412111Sralph 
84512111Sralph /*
84612111Sralph  * dofork - fork with retries on failure
84712111Sralph  */
84812877Sralph static
84912111Sralph dofork(action)
85012111Sralph 	int action;
85112111Sralph {
85212111Sralph 	register int i, pid;
85312111Sralph 
85412111Sralph 	for (i = 0; i < 20; i++) {
85512463Sralph 		if ((pid = fork()) < 0) {
85612111Sralph 			sleep((unsigned)(i*i));
85712463Sralph 			continue;
85812463Sralph 		}
85912463Sralph 		/*
86012463Sralph 		 * Child should run as daemon instead of root
86112463Sralph 		 */
86212463Sralph 		if (pid == 0)
86312463Sralph 			setuid(DU);
86412463Sralph 		return(pid);
86512111Sralph 	}
86612111Sralph 	log("can't fork");
86712111Sralph 
86812111Sralph 	switch (action) {
86912111Sralph 	case DORETURN:
87012111Sralph 		return (-1);
87112111Sralph 	default:
87212111Sralph 		log("bad action (%d) to dofork", action);
87312111Sralph 		/*FALL THRU*/
87412111Sralph 	case DOABORT:
87512111Sralph 		exit(1);
87612111Sralph 	}
87712111Sralph 	/*NOTREACHED*/
87812111Sralph }
87912111Sralph 
88012111Sralph /*
88114709Sralph  * Cleanup child processes when a signal is caught.
88212111Sralph  */
88312877Sralph static
88412111Sralph onintr()
88512111Sralph {
88612111Sralph 	kill(0, SIGINT);
88712111Sralph 	if (ofilter > 0)
88812111Sralph 		kill(ofilter, SIGCONT);
88912111Sralph 	while (wait(0) > 0)
89012111Sralph 		;
89112111Sralph 	exit(0);
89212111Sralph }
89312111Sralph 
89412877Sralph static
89512111Sralph init()
89612111Sralph {
89712111Sralph 	int status;
89812111Sralph 
89913169Sralph 	if ((status = pgetent(line, printer)) < 0)
90013169Sralph 		fatal("can't open printer description file");
90113169Sralph 	else if (status == 0)
90213169Sralph 		fatal("unknown printer");
90312111Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
90412111Sralph 		LP = DEFDEVLP;
90512111Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
90612463Sralph 		RP = DEFLP;
90712111Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
90812111Sralph 		LO = DEFLOCK;
90912111Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
91012111Sralph 		ST = DEFSTAT;
91112111Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
91212111Sralph 		LF = DEFLOGF;
91312111Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
91412111Sralph 		SD = DEFSPOOL;
91512111Sralph 	if ((DU = pgetnum("du")) < 0)
91612111Sralph 		DU = DEFUID;
91712111Sralph 	if ((FF = pgetstr("ff", &bp)) == NULL)
91812111Sralph 		FF = DEFFF;
91912111Sralph 	if ((PW = pgetnum("pw")) < 0)
92012111Sralph 		PW = DEFWIDTH;
92112111Sralph 	sprintf(&width[2], "%d", PW);
92212111Sralph 	if ((PL = pgetnum("pl")) < 0)
92312111Sralph 		PL = DEFLENGTH;
92412111Sralph 	sprintf(&length[2], "%d", PL);
92512463Sralph 	if ((PX = pgetnum("px")) < 0)
92612463Sralph 		PX = 0;
92712463Sralph 	sprintf(&pxwidth[2], "%d", PX);
92812463Sralph 	if ((PY = pgetnum("py")) < 0)
92912463Sralph 		PY = 0;
93012463Sralph 	sprintf(&pxlength[2], "%d", PY);
93112111Sralph 	RM = pgetstr("rm", &bp);
93212111Sralph 	AF = pgetstr("af", &bp);
93312111Sralph 	OF = pgetstr("of", &bp);
93412111Sralph 	IF = pgetstr("if", &bp);
93512463Sralph 	RF = pgetstr("rf", &bp);
93612111Sralph 	TF = pgetstr("tf", &bp);
93713233Sralph 	NF = pgetstr("nf", &bp);
93812111Sralph 	DF = pgetstr("df", &bp);
93912111Sralph 	GF = pgetstr("gf", &bp);
94012111Sralph 	VF = pgetstr("vf", &bp);
94112111Sralph 	CF = pgetstr("cf", &bp);
94212111Sralph 	TR = pgetstr("tr", &bp);
94312463Sralph 	RS = pgetflag("rs");
94412111Sralph 	SF = pgetflag("sf");
94512111Sralph 	SH = pgetflag("sh");
94612111Sralph 	SB = pgetflag("sb");
94712111Sralph 	RW = pgetflag("rw");
94812111Sralph 	BR = pgetnum("br");
94912111Sralph 	if ((FC = pgetnum("fc")) < 0)
95012111Sralph 		FC = 0;
95112111Sralph 	if ((FS = pgetnum("fs")) < 0)
95212111Sralph 		FS = 0;
95312111Sralph 	if ((XC = pgetnum("xc")) < 0)
95412111Sralph 		XC = 0;
95512111Sralph 	if ((XS = pgetnum("xs")) < 0)
95612111Sralph 		XS = 0;
95712581Sralph 	tof = !pgetflag("fo");
95812111Sralph }
95912111Sralph 
96012463Sralph /*
96112463Sralph  * Acquire line printer or remote connection.
96212463Sralph  */
96312877Sralph static
96412463Sralph openpr()
96512463Sralph {
96612463Sralph 	register int i, n;
96712463Sralph 
96812463Sralph 	if (*LP) {
96912463Sralph 		for (i = 1; ; i = i < 32 ? i << 1 : i) {
97013148Ssam 			pfd = open(LP, RW ? O_RDWR : O_WRONLY);
97112463Sralph 			if (pfd >= 0)
97212463Sralph 				break;
97312463Sralph 			if (errno == ENOENT) {
97412463Sralph 				log("cannot open %s", LP);
97512463Sralph 				exit(1);
97612463Sralph 			}
97712463Sralph 			if (i == 1)
97812463Sralph 				status("waiting for %s to become ready (offline ?)", printer);
97912463Sralph 			sleep(i);
98012463Sralph 		}
98112463Sralph 		if (isatty(pfd))
98212463Sralph 			setty();
98312463Sralph 		status("%s is ready and printing", printer);
98412463Sralph 	} else if (RM != NULL) {
98512463Sralph 		for (i = 1; ; i = i < 512 ? i << 1 : i) {
98612528Sralph 			pfd = getport(RM);
98712463Sralph 			if (pfd >= 0) {
98812463Sralph 				(void) sprintf(line, "\2%s\n", RP);
98912463Sralph 				n = strlen(line);
99012463Sralph 				if (write(pfd, line, n) != n)
99112463Sralph 					break;
99212463Sralph 				if (noresponse())
99312463Sralph 					(void) close(pfd);
99412463Sralph 				else
99512463Sralph 					break;
99612463Sralph 			}
99712463Sralph 			if (i == 1)
99812463Sralph 				status("waiting for %s to come up", RM);
99912463Sralph 			sleep(i);
100012463Sralph 		}
100112463Sralph 		status("sending to %s", RM);
100212463Sralph 		remote = 1;
100312463Sralph 	} else {
100412463Sralph 		log("no line printer device or remote machine name");
100512463Sralph 		exit(1);
100612463Sralph 	}
100712463Sralph 	/*
100812463Sralph 	 * Start up an output filter, if needed.
100912463Sralph 	 */
101012463Sralph 	if (OF) {
101112463Sralph 		int p[2];
101212463Sralph 		char *cp;
101312463Sralph 
101412463Sralph 		pipe(p);
101512463Sralph 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
101612463Sralph 			dup2(p[0], 0);		/* pipe is std in */
101712463Sralph 			dup2(pfd, 1);		/* printer is std out */
101812463Sralph 			for (i = 3; i < NOFILE; i++)
101912463Sralph 				(void) close(i);
102012463Sralph 			if ((cp = rindex(OF, '/')) == NULL)
102112463Sralph 				cp = OF;
102212463Sralph 			else
102312463Sralph 				cp++;
102412463Sralph 			execl(OF, cp, width, length, 0);
102512463Sralph 			log("can't execl output filter %s", OF);
102612463Sralph 			exit(1);
102712463Sralph 		}
102812463Sralph 		(void) close(p[0]);		/* close input side */
102912463Sralph 		ofd = p[1];			/* use pipe for output */
103012463Sralph 	} else {
103112463Sralph 		ofd = pfd;
103212463Sralph 		ofilter = 0;
103312463Sralph 	}
103412463Sralph }
103512463Sralph 
103612111Sralph struct bauds {
103712111Sralph 	int	baud;
103812111Sralph 	int	speed;
103912111Sralph } bauds[] = {
104012111Sralph 	50,	B50,
104112111Sralph 	75,	B75,
104212111Sralph 	110,	B110,
104312111Sralph 	134,	B134,
104412111Sralph 	150,	B150,
104512111Sralph 	200,	B200,
104612111Sralph 	300,	B300,
104712111Sralph 	600,	B600,
104812111Sralph 	1200,	B1200,
104912111Sralph 	1800,	B1800,
105012111Sralph 	2400,	B2400,
105112111Sralph 	4800,	B4800,
105212111Sralph 	9600,	B9600,
105312111Sralph 	19200,	EXTA,
105412111Sralph 	38400,	EXTB,
105512111Sralph 	0,	0
105612111Sralph };
105712111Sralph 
105812111Sralph /*
105912111Sralph  * setup tty lines.
106012111Sralph  */
106112877Sralph static
106212111Sralph setty()
106312111Sralph {
106412111Sralph 	struct sgttyb ttybuf;
106512111Sralph 	register struct bauds *bp;
106612111Sralph 
106712111Sralph 	if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
106812111Sralph 		log("cannot set exclusive-use");
106912111Sralph 		exit(1);
107012111Sralph 	}
107112111Sralph 	if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
107212111Sralph 		log("cannot get tty parameters");
107312111Sralph 		exit(1);
107412111Sralph 	}
107512111Sralph 	if (BR > 0) {
107612111Sralph 		for (bp = bauds; bp->baud; bp++)
107712111Sralph 			if (BR == bp->baud)
107812111Sralph 				break;
107912111Sralph 		if (!bp->baud) {
108012111Sralph 			log("illegal baud rate %d", BR);
108112111Sralph 			exit(1);
108212111Sralph 		}
108312111Sralph 		ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
108412111Sralph 	}
108513169Sralph 	ttybuf.sg_flags &= ~FC;
108613169Sralph 	ttybuf.sg_flags |= FS;
108712111Sralph 	if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
108812111Sralph 		log("cannot set tty parameters");
108912111Sralph 		exit(1);
109012111Sralph 	}
109112111Sralph 	if (XC) {
109212111Sralph 		if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
109312111Sralph 			log("cannot set local tty parameters");
109412111Sralph 			exit(1);
109512111Sralph 		}
109612111Sralph 	}
109712111Sralph 	if (XS) {
109812111Sralph 		if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
109912111Sralph 			log("cannot set local tty parameters");
110012111Sralph 			exit(1);
110112111Sralph 		}
110212111Sralph 	}
110312111Sralph }
110412463Sralph 
110512463Sralph /*VARARGS1*/
110612463Sralph static
110712463Sralph status(msg, a1, a2, a3)
110812463Sralph 	char *msg;
110912463Sralph {
111012463Sralph 	register int fd;
111112463Sralph 	char buf[BUFSIZ];
111212463Sralph 
111312463Sralph 	umask(0);
111413148Ssam 	fd = open(ST, O_WRONLY|O_CREAT, 0664);
111513148Ssam 	if (fd < 0 || flock(fd, LOCK_EX) < 0)
111612463Sralph 		fatal("cannot create status file");
111713148Ssam 	ftruncate(fd, 0);
111812463Sralph 	sprintf(buf, msg, a1, a2, a3);
111912463Sralph 	strcat(buf, "\n");
112012463Sralph 	(void) write(fd, buf, strlen(buf));
112112463Sralph 	(void) close(fd);
112212463Sralph }
1123