xref: /csrg-svn/usr.sbin/lpr/lpd/printjob.c (revision 12528)
1*12528Sralph /*	printjob.c	4.3	83/05/18	*/
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 
1112111Sralph #define DORETURN	0	/* absorb fork error */
1212111Sralph #define DOABORT		1	/* abort if dofork fails */
1312111Sralph 
1412111Sralph char	title[80];		/* ``pr'' title */
1512111Sralph FILE	*cfp;			/* control file */
1612111Sralph int	pfd;			/* printer file descriptor */
1712111Sralph int	ofd;			/* output filter file descriptor */
1812111Sralph int	lfd;			/* lock file descriptor */
1912111Sralph int	pid;			/* pid of lpd process */
2012111Sralph int	prchild;		/* id of pr process */
2112111Sralph int	child;			/* id of any filters */
2212111Sralph int	ofilter;		/* id of output filter, if any */
2312111Sralph int	tof = 1;		/* top of form; init true if open does ff */
2412111Sralph int	remote;			/* non zero if sending files to remote */
2512111Sralph 
2612111Sralph extern	banner();		/* big character printer */
2712111Sralph char	logname[32];		/* user's login name */
2812111Sralph char	jobname[32];		/* job or file name */
2912111Sralph char	class[32];		/* classification field */
3012463Sralph char	width[10] = "-w";	/* page width in characters */
3112463Sralph char	length[10] = "-l";	/* page length in lines */
3212463Sralph char	pxwidth[10] = "-x";	/* page width in pixels */
3312463Sralph char	pxlength[10] = "-y";	/* page length in pixels */
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 */
4512111Sralph 	(void) close(2);			/* set up log file */
4612111Sralph 	(void) open(LF, FWRONLY|FAPPEND, 0);
4712463Sralph 	dup2(2, 1);				/* closes original connection */
4812463Sralph 	pid = getpid();				/* for use with lprm */
4912111Sralph 	setpgrp(0, pid);
5012463Sralph 	sigset(SIGINT, onintr);
5112111Sralph 
5212111Sralph 	/*
5312111Sralph 	 * uses short form file names
5412111Sralph 	 */
5512111Sralph 	if (chdir(SD) < 0) {
5612111Sralph 		log("cannot chdir to %s", SD);
5712111Sralph 		exit(1);
5812111Sralph 	}
5912463Sralph 	if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
6012463Sralph 		exit(0);		/* printing disabled */
6112111Sralph 	if ((lfd = open(LO, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK|FNBLOCK, 0664)) < 0) {
6212111Sralph 		if (errno == EWOULDBLOCK)	/* active deamon present */
6312111Sralph 			exit(0);
6412111Sralph 		log("cannot create %s", LO);
6512111Sralph 		exit(1);
6612111Sralph 	}
6712111Sralph 	/*
6812111Sralph 	 * write process id for others to know
6912111Sralph 	 */
7012111Sralph 	sprintf(line, "%u\n", pid);
7112111Sralph 	pidoff = i = strlen(line);
7212463Sralph 	if (write(lfd, line, i) != i) {
7312111Sralph 		log("cannot write daemon pid");
7412111Sralph 		exit(1);
7512111Sralph 	}
7612111Sralph 	/*
7712111Sralph 	 * search the spool directory for work and sort by queue order.
7812111Sralph 	 */
7912111Sralph 	if ((nitems = getq(&queue)) < 0) {
8012111Sralph 		log("can't scan spool directory %s", SD);
8112111Sralph 		exit(1);
8212111Sralph 	}
8312463Sralph 	if (nitems == 0)		/* no work to do */
8412111Sralph 		exit(0);
8512463Sralph 	openpr();			/* open printer or remote */
8612463Sralph again:
8712111Sralph 	/*
8812111Sralph 	 * we found something to do now do it --
8912111Sralph 	 *    write the name of the current control file into the lock file
9012111Sralph 	 *    so the spool queue program can tell what we're working on
9112111Sralph 	 */
9212111Sralph 	for (qp = queue; nitems--; free((char *) q)) {
9312111Sralph 		q = *qp++;
9412111Sralph 		if (stat(q->q_name, &stb) < 0)
9512111Sralph 			continue;
9612463Sralph 	restart:
9712111Sralph 		(void) lseek(lfd, pidoff, 0);
9812111Sralph 		(void) sprintf(line, "%s\n", q->q_name);
9912111Sralph 		i = strlen(line);
10012111Sralph 		if (write(lfd, line, i) != i)
10112111Sralph 			log("can't write (%d) control file name", errno);
10212111Sralph 		if (!remote)
10312111Sralph 			i = printit(q->q_name);
10412111Sralph 		else
10512111Sralph 			i = sendit(q->q_name);
10612463Sralph 		/*
10712463Sralph 		 * Check to see if we are supposed to stop printing.
10812463Sralph 		 */
10912463Sralph 		if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
11012463Sralph 			goto done;
11112463Sralph 		/*
11212463Sralph 		 * Check to see if we should try reprinting the job.
11312463Sralph 		 */
11412463Sralph 		if (i > 0) {
11512111Sralph 			log("restarting");
11612111Sralph 			if (ofilter > 0) {
11712111Sralph 				kill(ofilter, SIGCONT);	/* to be sure */
11812111Sralph 				(void) close(ofd);
11912111Sralph 				while ((i = wait(0)) > 0 && i != ofilter)
12012111Sralph 					;
12112111Sralph 				ofilter = 0;
12212111Sralph 			}
12312463Sralph 			(void) close(pfd);	/* close printer */
12412463Sralph 			(void) lseek(lfd, pidoff, 0);
12512463Sralph 			if (write(lfd, "\n", 1) != 1)
12612463Sralph 				log("can't write (%d) control file name", errno);
12712463Sralph 			openpr();		/* try to reopen printer */
12812111Sralph 			goto restart;
12912111Sralph 		}
13012111Sralph 	}
13112111Sralph 	free((char *) queue);
13212463Sralph 	/*
13312463Sralph 	 * search the spool directory for more work.
13412463Sralph 	 */
13512463Sralph 	if ((nitems = getq(&queue)) < 0) {
13612463Sralph 		log("can't scan spool directory %s", SD);
13712463Sralph 		exit(1);
13812463Sralph 	}
13912463Sralph 	if (nitems == 0) {		/* no more work to do */
14012463Sralph 	done:
14112463Sralph 		if (!SF && !tof)
14212463Sralph 			(void) write(ofd, FF, strlen(FF));
14312463Sralph 		if (TR != NULL)		/* output trailer */
14412463Sralph 			(void) write(ofd, TR, strlen(TR));
14512463Sralph 		exit(0);
14612463Sralph 	}
14712111Sralph 	goto again;
14812111Sralph }
14912111Sralph 
15012111Sralph char	fonts[4][50];	/* fonts for troff */
15112111Sralph 
15212111Sralph static char ifonts[4][18] = {
15312111Sralph 	"/usr/lib/vfont/R",
15412111Sralph 	"/usr/lib/vfont/I",
15512111Sralph 	"/usr/lib/vfont/B",
15612111Sralph 	"/usr/lib/vfont/S"
15712111Sralph };
15812111Sralph 
15912111Sralph /*
16012111Sralph  * The remaining part is the reading of the control file (cf)
16112111Sralph  * and performing the various actions.
16212111Sralph  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
16312111Sralph  * -1 if a non-recoverable error occured.
16412111Sralph  */
16512111Sralph printit(file)
16612111Sralph 	char *file;
16712111Sralph {
16812111Sralph 	register int i;
16912111Sralph 	int bombed = 0;
17012111Sralph 
17112111Sralph 	/*
17212111Sralph 	 * open control file
17312111Sralph 	 */
17412111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
17512111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
17612111Sralph 		return(0);
17712111Sralph 	}
17812111Sralph 	/*
17912111Sralph 	 * Reset troff fonts.
18012111Sralph 	 */
18112111Sralph 	for (i = 0; i < 4; i++)
18212111Sralph 		strcpy(fonts[i], ifonts[i]);
18312111Sralph 
18412111Sralph 	/*
18512111Sralph 	 *      read the control file for work to do
18612111Sralph 	 *
18712111Sralph 	 *      file format -- first character in the line is a command
18812111Sralph 	 *      rest of the line is the argument.
18912111Sralph 	 *      valid commands are:
19012111Sralph 	 *
19112111Sralph 	 *		J -- "job name" on banner page
19212111Sralph 	 *		C -- "class name" on banner page
19312111Sralph 	 *              L -- "literal" user's name to print on banner
19412111Sralph 	 *		T -- "title" for pr
19512111Sralph 	 *		H -- "host name" of machine where lpr was done
19612111Sralph 	 *              P -- "person" user's login name
19712111Sralph 	 *              I -- "indent" changes default indents driver
19812111Sralph 	 *                   must have stty/gtty avaialble
19912111Sralph 	 *              f -- "file name" name of text file to print
20012111Sralph 	 *		l -- "file name" text file with control chars
20112111Sralph 	 *		p -- "file name" text file to print with pr(1)
20212111Sralph 	 *		t -- "file name" troff(1) file to print
20312111Sralph 	 *		d -- "file name" dvi file to print
20412111Sralph 	 *		g -- "file name" plot(1G) file to print
20512111Sralph 	 *		v -- "file name" plain raster file to print
20612111Sralph 	 *		c -- "file name" cifplot file to print
20712111Sralph 	 *		1 -- "R font file" for troff
20812111Sralph 	 *		2 -- "I font file" for troff
20912111Sralph 	 *		3 -- "B font file" for troff
21012111Sralph 	 *		4 -- "S font file" for troff
21112111Sralph 	 *		N -- "name" of file (used by lpq)
21212111Sralph 	 *              U -- "unlink" name of file to remove
21312111Sralph 	 *                    (after we print it. (Pass 2 only)).
21412111Sralph 	 *		M -- "mail" to user when done printing
21512111Sralph 	 *
21612111Sralph 	 *      getline reads a line and expands tabs to blanks
21712111Sralph 	 */
21812111Sralph 
21912111Sralph 	/* pass 1 */
22012111Sralph 
22112111Sralph 	while (getline(cfp))
22212111Sralph 		switch (line[0]) {
22312111Sralph 		case 'H':
22412111Sralph 			strcpy(host, line+1);
22512111Sralph 			if (class[0] == '\0')
22612111Sralph 				strcpy(class, line+1);
22712111Sralph 			continue;
22812111Sralph 
22912111Sralph 		case 'P':
23012111Sralph 			strcpy(logname, line+1);
23112463Sralph 			if (RS) {			/* restricted */
23212463Sralph 				if (getpwnam(logname) == (struct passwd *)0) {
23312463Sralph 					bombed = 2;
23412463Sralph 					sendmail(bombed);
23512463Sralph 					goto pass2;
23612463Sralph 				}
23712463Sralph 			}
23812111Sralph 			continue;
23912111Sralph 
24012111Sralph 		case 'J':
24112111Sralph 			if (line[1] != '\0')
24212111Sralph 				strcpy(jobname, line+1);
24312111Sralph 			else
24412111Sralph 				strcpy(jobname, " ");
24512111Sralph 			continue;
24612111Sralph 
24712111Sralph 		case 'C':
24812111Sralph 			if (line[1] != '\0')
24912111Sralph 				strcpy(class, line+1);
25012111Sralph 			else if (class[0] == '\0')
25112111Sralph 				gethostname(class, sizeof (class));
25212111Sralph 			continue;
25312111Sralph 
25412111Sralph 		case 'T':	/* header title for pr */
25512111Sralph 			strcpy(title, line+1);
25612111Sralph 			continue;
25712111Sralph 
25812111Sralph 		case 'L':	/* identification line */
25912111Sralph 			if (!SH)
26012111Sralph 				banner(line+1, jobname);
26112111Sralph 			continue;
26212111Sralph 
26312111Sralph 		case '1':	/* troff fonts */
26412111Sralph 		case '2':
26512111Sralph 		case '3':
26612111Sralph 		case '4':
26712111Sralph 			if (line[1] != '\0')
26812111Sralph 				strcpy(fonts[line[0]-'1'], line+1);
26912111Sralph 			continue;
27012111Sralph 
27112111Sralph 		case 'W':	/* page width */
27212111Sralph 			strcpy(width+2, line+1);
27312111Sralph 			continue;
27412111Sralph 
27512111Sralph 		default:	/* some file to print */
27612111Sralph 			if ((i = print(line[0], line+1)) > 0) {
27712111Sralph 				(void) fclose(cfp);
27812111Sralph 				return(1);
27912111Sralph 			} else if (i < 0)
28012111Sralph 				bombed = 1;
28112111Sralph 			title[0] = '\0';
28212111Sralph 			continue;
28312111Sralph 
28412111Sralph 		case 'I':
28512111Sralph 		case 'N':
28612111Sralph 		case 'U':
28712111Sralph 		case 'M':
28812111Sralph 			continue;
28912111Sralph 		}
29012111Sralph 
29112111Sralph 	/* pass 2 */
29212111Sralph 
29312463Sralph pass2:
29412111Sralph 	fseek(cfp, 0L, 0);
29512111Sralph 	while (getline(cfp))
29612111Sralph 		switch (line[0]) {
29712111Sralph 		case 'M':
29812463Sralph 			if (bombed != 2)		/* already sent if 2 */
29912463Sralph 				sendmail(bombed);
30012111Sralph 			continue;
30112111Sralph 
30212111Sralph 		case 'U':
30312111Sralph 			(void) unlink(line+1);
30412111Sralph 		}
30512111Sralph 	/*
30612111Sralph 	 * clean-up incase another control file exists
30712111Sralph 	 */
30812111Sralph 	(void) fclose(cfp);
30912111Sralph 	(void) unlink(file);
31012111Sralph 	return(0);
31112111Sralph }
31212111Sralph 
31312111Sralph /*
31412111Sralph  * Print a file.
31512111Sralph  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, TF, CF, VF}.
31612111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
31712111Sralph  * 0 if all is well.
31812111Sralph  * Note: all filters take stdin as the file, stdout as the printer,
31912111Sralph  * stderr as the log file, and must not ignore SIGINT.
32012111Sralph  */
32112111Sralph print(format, file)
32212111Sralph 	int format;
32312111Sralph 	char *file;
32412111Sralph {
32512111Sralph 	register int n, fi, fo;
32612111Sralph 	register char *prog;
32712111Sralph 	char *av[15], buf[BUFSIZ];
32812111Sralph 	int pid, p[2], stopped = 0;
32912111Sralph 	union wait status;
33012111Sralph 
33112111Sralph 	if ((fi = open(file, FRDONLY, 0)) < 0) {
33212111Sralph 		log("%s: open failure <errno = %d>", file, errno);
33312111Sralph 		return(-1);
33412111Sralph 	}
33512111Sralph 	if (!SF && !tof) {		/* start on a fresh page */
33612111Sralph 		(void) write(ofd, FF, strlen(FF));
33712111Sralph 		tof = 1;
33812111Sralph 	}
33912111Sralph 	if (IF == NULL && (format == 'f' || format == 'l')) {
34012111Sralph 		tof = 0;
34112111Sralph 		while ((n = read(fi, buf, BUFSIZ)) > 0)
34212111Sralph 			if (write(ofd, buf, n) != n) {
34312111Sralph 				(void) close(fi);
34412111Sralph 				return(1);
34512111Sralph 			}
34612111Sralph 		(void) close(fi);
34712111Sralph 		return(0);
34812111Sralph 	}
34912111Sralph 	switch (format) {
35012111Sralph 	case 'p':	/* print file using 'pr' */
35112111Sralph 		if (IF == NULL) {	/* use output filter */
35212111Sralph 			prog = PR;
35312111Sralph 			av[0] = "pr";
35412111Sralph 			av[1] = width;
35512111Sralph 			av[2] = length;
35612111Sralph 			av[3] = "-h";
35712111Sralph 			av[4] = *title ? title : " ";
35812111Sralph 			av[5] = 0;
35912111Sralph 			fo = ofd;
36012111Sralph 			goto start;
36112111Sralph 		}
36212111Sralph 		pipe(p);
36312111Sralph 		if ((prchild = dofork(DORETURN)) == 0) {	/* child */
36412111Sralph 			dup2(fi, 0);		/* file is stdin */
36512111Sralph 			dup2(p[1], 1);		/* pipe is stdout */
36612111Sralph 			for (n = 3; n < NOFILE; n++)
36712111Sralph 				(void) close(n);
36812111Sralph 			execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
36912111Sralph 			log("cannot execl %s", PR);
37012111Sralph 			exit(2);
37112111Sralph 		}
37212111Sralph 		(void) close(p[1]);		/* close output side */
37312111Sralph 		(void) close(fi);
37412111Sralph 		if (prchild < 0) {
37512111Sralph 			prchild = 0;
37612111Sralph 			(void) close(p[0]);
37712111Sralph 			return(-1);
37812111Sralph 		}
37912111Sralph 		fi = p[0];			/* use pipe for input */
38012111Sralph 	case 'f':	/* print plain text file */
38112111Sralph 		prog = IF;
38212111Sralph 		av[1] = width;
38312111Sralph 		av[2] = length;
38412111Sralph 		n = 3;
38512111Sralph 		break;
38612111Sralph 	case 'l':	/* like 'f' but pass control characters */
38712111Sralph 		prog = IF;
38812111Sralph 		av[1] = "-l";
38912111Sralph 		av[2] = width;
39012111Sralph 		av[3] = length;
39112111Sralph 		n = 4;
39212111Sralph 		break;
39312463Sralph 	case 'r':	/* print a fortran text file */
39412463Sralph 		prog = RF;
39512463Sralph 		av[1] = width;
39612463Sralph 		av[2] = length;
39712463Sralph 		n = 3;
39812463Sralph 		break;
39912111Sralph 	case 't':	/* print troff output */
40012463Sralph 	case 'd':	/* print tex output */
40112111Sralph 		(void) unlink(".railmag");
40212463Sralph 		if ((fo = creat(".railmag", FILMOD)) < 0) {
40312111Sralph 			log("cannot create .railmag");
40412111Sralph 			(void) unlink(".railmag");
40512111Sralph 		} else {
40612111Sralph 			for (n = 0; n < 4; n++) {
40712111Sralph 				if (fonts[n][0] != '/')
40812111Sralph 					(void) write(fo, "/usr/lib/vfont/", 15);
40912111Sralph 				(void) write(fo, fonts[n], strlen(fonts[n]));
41012111Sralph 				(void) write(fo, "\n", 1);
41112111Sralph 			}
41212111Sralph 			(void) close(fo);
41312111Sralph 		}
41412111Sralph 		prog = (format == 't') ? TF : DF;
41512463Sralph 		av[1] = pxwidth;
41612463Sralph 		av[2] = pxlength;
41712463Sralph 		n = 3;
41812111Sralph 		break;
41912111Sralph 	case 'c':	/* print cifplot output */
42012111Sralph 		prog = CF;
42112463Sralph 		av[1] = pxwidth;
42212463Sralph 		av[2] = pxlength;
42312463Sralph 		n = 3;
42412111Sralph 		break;
42512111Sralph 	case 'g':	/* print plot(1G) output */
42612111Sralph 		prog = GF;
42712463Sralph 		av[1] = pxwidth;
42812463Sralph 		av[2] = pxlength;
42912463Sralph 		n = 3;
43012111Sralph 		break;
43112111Sralph 	case 'v':	/* print raster output */
43212111Sralph 		prog = VF;
43312463Sralph 		av[1] = pxwidth;
43412463Sralph 		av[2] = pxlength;
43512463Sralph 		n = 3;
43612111Sralph 		break;
43712111Sralph 	default:
43812111Sralph 		(void) close(fi);
43912111Sralph 		log("illegal format character '%c'", format);
44012111Sralph 		return(-1);
44112111Sralph 	}
44212111Sralph 	if ((av[0] = rindex(prog, '/')) != NULL)
44312111Sralph 		av[0]++;
44412111Sralph 	else
44512111Sralph 		av[0] = prog;
44612111Sralph 	av[n++] = "-n";
44712111Sralph 	av[n++] = logname;
44812111Sralph 	av[n++] = "-h";
44912111Sralph 	av[n++] = host;
45012111Sralph 	av[n++] = AF;
45112111Sralph 	av[n] = 0;
45212111Sralph 	fo = pfd;
45312111Sralph 	if (ofilter > 0) {		/* stop output filter */
45412111Sralph 		write(ofd, "\031\1", 2);
45512111Sralph 		while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
45612111Sralph 			;
45712111Sralph 		if (status.w_stopval != WSTOPPED) {
45812111Sralph 			(void) close(fi);
45912111Sralph 			log("output filter died (%d)", status.w_retcode);
46012111Sralph 			return(1);
46112111Sralph 		}
46212111Sralph 		stopped++;
46312111Sralph 	}
46412111Sralph start:
46512111Sralph 	if ((child = dofork(DORETURN)) == 0) {	/* child */
46612111Sralph 		dup2(fi, 0);
46712111Sralph 		dup2(fo, 1);
46812111Sralph 		for (n = 3; n < NOFILE; n++)
46912111Sralph 			(void) close(n);
47012111Sralph 		execv(prog, av);
47112111Sralph 		log("cannot execl %s", prog);
47212111Sralph 		exit(2);
47312111Sralph 	}
47412111Sralph 	(void) close(fi);
47512111Sralph 	if (child < 0)
47612111Sralph 		status.w_retcode = 100;
47712111Sralph 	else
47812111Sralph 		while ((pid = wait(&status)) > 0 && pid != child)
47912111Sralph 			;
48012111Sralph 	child = 0;
48112111Sralph 	prchild = 0;
48212111Sralph 	if (stopped) {		/* restart output filter */
48312111Sralph 		if (kill(ofilter, SIGCONT) < 0) {
48412111Sralph 			log("cannot restart output filter");
48512111Sralph 			exit(1);
48612111Sralph 		}
48712111Sralph 	}
48812111Sralph 	tof = 0;
48912111Sralph 	if (!WIFEXITED(status) || status.w_retcode > 1) {
49012111Sralph 		log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode);
49112111Sralph 		return(-1);
49212111Sralph 	} else if (status.w_retcode == 1)
49312111Sralph 		return(1);
49412111Sralph 	tof = 1;
49512111Sralph 	return(0);
49612111Sralph }
49712111Sralph 
49812111Sralph /*
49912111Sralph  * Send the daemon control file (cf) and any data files.
50012111Sralph  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
50112111Sralph  * 0 if all is well.
50212111Sralph  */
50312111Sralph sendit(file)
50412111Sralph 	char *file;
50512111Sralph {
50612111Sralph 	register int linelen, err = 0;
50712111Sralph 	char last[132];
50812111Sralph 
50912111Sralph 	/*
51012111Sralph 	 * open control file
51112111Sralph 	 */
51212111Sralph 	if ((cfp = fopen(file, "r")) == NULL) {
51312111Sralph 		log("control file (%s) open failure <errno = %d>", file, errno);
51412111Sralph 		return(0);
51512111Sralph 	}
51612111Sralph 	/*
51712111Sralph 	 *      read the control file for work to do
51812111Sralph 	 *
51912111Sralph 	 *      file format -- first character in the line is a command
52012111Sralph 	 *      rest of the line is the argument.
52112111Sralph 	 *      commands of interest are:
52212111Sralph 	 *
52312111Sralph 	 *            a-z -- "file name" name of file to print
52412111Sralph 	 *              U -- "unlink" name of file to remove
52512111Sralph 	 *                    (after we print it. (Pass 2 only)).
52612111Sralph 	 */
52712111Sralph 
52812111Sralph 	/*
52912111Sralph 	 * pass 1
53012111Sralph 	 */
53112111Sralph 	while (getline(cfp)) {
53212111Sralph 	again:
53312111Sralph 		if (line[0] >= 'a' && line[0] <= 'z') {
53412111Sralph 			strcpy(last, line);
53512111Sralph 			while (linelen = getline(cfp))
53612111Sralph 				if (strcmp(last, line))
53712111Sralph 					break;
53812111Sralph 			if ((err = sendfile('\3', last+1)) > 0) {
53912111Sralph 				(void) fclose(cfp);
54012111Sralph 				return(1);
54112111Sralph 			} else if (err)
54212111Sralph 				break;
54312111Sralph 			if (linelen)
54412111Sralph 				goto again;
54512111Sralph 			break;
54612111Sralph 		}
54712111Sralph 	}
54812111Sralph 	if (!err && sendfile('\2', file) > 0) {
54912111Sralph 		(void) fclose(cfp);
55012111Sralph 		return(1);
55112111Sralph 	}
55212111Sralph 	/*
55312111Sralph 	 * pass 2
55412111Sralph 	 */
55512111Sralph 	fseek(cfp, 0L, 0);
55612111Sralph 	while (getline(cfp))
55712111Sralph 		if (line[0] == 'U')
55812111Sralph 			(void) unlink(line+1);
55912111Sralph 	/*
56012111Sralph 	 * clean-up incase another control file exists
56112111Sralph 	 */
56212111Sralph 	(void) fclose(cfp);
56312111Sralph 	(void) unlink(file);
56412111Sralph 	return(0);
56512111Sralph }
56612111Sralph 
56712111Sralph /*
56812111Sralph  * Send a data file to the remote machine and spool it.
56912111Sralph  * Return positive if we should try resending.
57012111Sralph  */
57112111Sralph sendfile(type, file)
57212111Sralph 	char type, *file;
57312111Sralph {
57412111Sralph 	register int f, i, amt;
57512111Sralph 	struct stat stb;
57612111Sralph 	char buf[BUFSIZ];
57712111Sralph 	int sizerr;
57812111Sralph 
57912111Sralph 	if ((f = open(file, FRDONLY, 0)) < 0 || fstat(f, &stb) < 0) {
58012111Sralph 		log("file (%s) open failure <errno = %d>", file, errno);
58112111Sralph 		return(-1);
58212111Sralph 	}
58312111Sralph 	(void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
58412111Sralph 	amt = strlen(buf);
58512111Sralph 	if (write(pfd, buf, amt) != amt)
58612111Sralph 		return(1);
58712111Sralph 	if (noresponse())
58812111Sralph 		return(1);
58912111Sralph 	sizerr = 0;
59012111Sralph 	for (i = 0; i < stb.st_size; i += BUFSIZ) {
59112111Sralph 		amt = BUFSIZ;
59212111Sralph 		if (i + amt > stb.st_size)
59312111Sralph 			amt = stb.st_size - i;
59412111Sralph 		if (sizerr == 0 && read(f, buf, amt) != amt)
59512111Sralph 			sizerr = 1;
59612111Sralph 		if (write(pfd, buf, amt) != amt)
59712111Sralph 			return(1);
59812111Sralph 	}
59912111Sralph 	(void) close(f);
60012111Sralph 	if (sizerr) {
60112111Sralph 		log("%s: changed size", file);
60212111Sralph 		(void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
60312111Sralph 		return(-1);
60412111Sralph 	}
60512111Sralph 	if (write(pfd, "", 1) != 1)
60612111Sralph 		return(1);
60712111Sralph 	if (noresponse())
60812111Sralph 		return(1);
60912111Sralph 	return(0);
61012111Sralph }
61112111Sralph 
61212111Sralph /*
61312111Sralph  * Check to make sure there have been no errors and that both programs
61412111Sralph  * are in sync with eachother.
61512111Sralph  * Return non-zero if the connection was lost.
61612111Sralph  */
61712111Sralph static
61812111Sralph noresponse()
61912111Sralph {
62012111Sralph 	char resp;
62112111Sralph 
62212111Sralph 	if (read(pfd, &resp, 1) != 1 || resp != '\0') {
62312111Sralph 		log("lost connection or error in recvjob");
62412111Sralph 		return(1);
62512111Sralph 	}
62612111Sralph 	return(0);
62712111Sralph }
62812111Sralph 
62912111Sralph /*
63012111Sralph  * Banner printing stuff
63112111Sralph  */
63212111Sralph banner(name1, name2)
63312111Sralph 	char *name1, *name2;
63412111Sralph {
63512111Sralph 	time_t tvec;
63612111Sralph 	extern char *ctime();
63712111Sralph 
63812111Sralph 	time(&tvec);
63912111Sralph 	if (!SF && !tof)
64012111Sralph 		(void) write(ofd, FF, strlen(FF));
64112111Sralph 	if (SB) {	/* short banner only */
64212111Sralph 		if (class[0]) {
64312111Sralph 			(void) write(ofd, class, strlen(class));
64412111Sralph 			(void) write(ofd, ":", 1);
64512111Sralph 		}
64612111Sralph 		(void) write(ofd, name1, strlen(name1));
64712111Sralph 		(void) write(ofd, "  Job: ", 7);
64812111Sralph 		(void) write(ofd, name2, strlen(name2));
64912111Sralph 		(void) write(ofd, "  Date: ", 8);
65012111Sralph 		(void) write(ofd, ctime(&tvec), 24);
65112111Sralph 		(void) write(ofd, "\n", 1);
65212111Sralph 	} else {	/* normal banner */
65312111Sralph 		(void) write(ofd, "\n\n\n", 3);
65412111Sralph 		scan_out(ofd, name1, '\0');
65512111Sralph 		(void) write(ofd, "\n\n", 2);
65612111Sralph 		scan_out(ofd, name2, '\0');
65712111Sralph 		if (class[0]) {
65812111Sralph 			(void) write(ofd,"\n\n\n",3);
65912111Sralph 			scan_out(ofd, class, '\0');
66012111Sralph 		}
66112111Sralph 		(void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
66212111Sralph 		(void) write(ofd, name2, strlen(name2));
66312111Sralph 		(void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
66412111Sralph 		(void) write(ofd, ctime(&tvec), 24);
66512111Sralph 		(void) write(ofd, "\n", 1);
66612111Sralph 	}
66712111Sralph 	if (!SF)
66812111Sralph 		(void) write(ofd, FF, strlen(FF));
66912111Sralph 	tof = 1;
67012111Sralph }
67112111Sralph 
67212111Sralph char *
67312111Sralph scnline(key, p, c)
67412111Sralph 	register char key, *p;
67512111Sralph 	char c;
67612111Sralph {
67712111Sralph 	register scnwidth;
67812111Sralph 
67912111Sralph 	for (scnwidth = WIDTH; --scnwidth;) {
68012111Sralph 		key <<= 1;
68112111Sralph 		*p++ = key & 0200 ? c : BACKGND;
68212111Sralph 	}
68312111Sralph 	return (p);
68412111Sralph }
68512111Sralph 
68612111Sralph #define TRC(q)	(((q)-' ')&0177)
68712111Sralph 
68812111Sralph scan_out(scfd, scsp, dlm)
68912111Sralph 	int scfd;
69012111Sralph 	char *scsp, dlm;
69112111Sralph {
69212111Sralph 	register char *strp;
69312111Sralph 	register nchrs, j;
69412111Sralph 	char outbuf[LINELEN+1], *sp, c, cc;
69512111Sralph 	int d, scnhgt;
69612111Sralph 	extern char scnkey[][HEIGHT];	/* in lpdchar.c */
69712111Sralph 
69812111Sralph 	for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
69912111Sralph 		strp = &outbuf[0];
70012111Sralph 		sp = scsp;
70112111Sralph 		for (nchrs = 0; ; ) {
70212111Sralph 			d = dropit(c = TRC(cc = *sp++));
70312111Sralph 			if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
70412111Sralph 				for (j = WIDTH; --j;)
70512111Sralph 					*strp++ = BACKGND;
70612111Sralph 			else
70712111Sralph 				strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
70812111Sralph 			if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
70912111Sralph 				break;
71012111Sralph 			*strp++ = BACKGND;
71112111Sralph 			*strp++ = BACKGND;
71212111Sralph 		}
71312111Sralph 		while (*--strp == BACKGND && strp >= outbuf)
71412111Sralph 			;
71512111Sralph 		strp++;
71612111Sralph 		*strp++ = '\n';
71712111Sralph 		(void) write(scfd, outbuf, strp-outbuf);
71812111Sralph 	}
71912111Sralph }
72012111Sralph 
72112111Sralph dropit(c)
72212111Sralph 	char c;
72312111Sralph {
72412111Sralph 	switch(c) {
72512111Sralph 
72612111Sralph 	case TRC('_'):
72712111Sralph 	case TRC(';'):
72812111Sralph 	case TRC(','):
72912111Sralph 	case TRC('g'):
73012111Sralph 	case TRC('j'):
73112111Sralph 	case TRC('p'):
73212111Sralph 	case TRC('q'):
73312111Sralph 	case TRC('y'):
73412111Sralph 		return (DROP);
73512111Sralph 
73612111Sralph 	default:
73712111Sralph 		return (0);
73812111Sralph 	}
73912111Sralph }
74012111Sralph 
74112111Sralph /*
74212111Sralph  * sendmail ---
74312111Sralph  *   tell people about job completion
74412111Sralph  */
74512111Sralph sendmail(bombed)
74612111Sralph 	int bombed;
74712111Sralph {
74812111Sralph 	static int p[2];
74912111Sralph 	register int i;
75012111Sralph 	int stat;
75112111Sralph 	register char *cp;
75212111Sralph 	char buf[100];
75312111Sralph 
75412111Sralph 	pipe(p);
75512111Sralph 	if ((stat = dofork(DORETURN)) == 0) {		/* child */
75612111Sralph 		dup2(p[0], 0);
75712111Sralph 		for (i = 3; i < NOFILE; i++)
75812111Sralph 			(void) close(i);
75912111Sralph 		if ((cp = rindex(MAIL, '/')) != NULL)
76012111Sralph 			cp++;
76112111Sralph 		else
76212111Sralph 			cp = MAIL;
76312111Sralph 		sprintf(buf, "%s@%s", line+1, host);
76412111Sralph 		execl(MAIL, cp, buf, 0);
76512111Sralph 		exit(0);
76612111Sralph 	} else if (stat > 0) {				/* parent */
76712111Sralph 		dup2(p[1], 1);
76812111Sralph 		printf("To: %s\n", line+1);
76912111Sralph 		printf("Subject: printer job\n\n");
77012111Sralph 		printf("Your printer job ");
77112111Sralph 		if (*jobname)
77212111Sralph 			printf("(%s) ", jobname);
77312463Sralph 		switch (bombed) {
77412463Sralph 		case 0:
77512463Sralph 			printf("\ncompleted successfully\n");
77612463Sralph 			break;
77712463Sralph 		default:
77812463Sralph 		case 1:
77912463Sralph 			printf("\ncould not be printed\n");
78012463Sralph 			break;
78112463Sralph 		case 2:
78212463Sralph 			printf("\ncould not be printed without an account on %s\n", host);
78312463Sralph 			break;
78412463Sralph 		}
78512111Sralph 		fflush(stdout);
78612111Sralph 		(void) close(1);
78712111Sralph 	}
78812111Sralph 	(void) close(p[0]);
78912111Sralph 	(void) close(p[1]);
79012111Sralph 	wait(&stat);
79112111Sralph }
79212111Sralph 
79312111Sralph /*
79412111Sralph  * dofork - fork with retries on failure
79512111Sralph  */
79612111Sralph dofork(action)
79712111Sralph 	int action;
79812111Sralph {
79912111Sralph 	register int i, pid;
80012111Sralph 
80112111Sralph 	for (i = 0; i < 20; i++) {
80212463Sralph 		if ((pid = fork()) < 0) {
80312111Sralph 			sleep((unsigned)(i*i));
80412463Sralph 			continue;
80512463Sralph 		}
80612463Sralph 		/*
80712463Sralph 		 * Child should run as daemon instead of root
80812463Sralph 		 */
80912463Sralph 		if (pid == 0)
81012463Sralph 			setuid(DU);
81112463Sralph 		return(pid);
81212111Sralph 	}
81312111Sralph 	log("can't fork");
81412111Sralph 
81512111Sralph 	switch (action) {
81612111Sralph 	case DORETURN:
81712111Sralph 		return (-1);
81812111Sralph 	default:
81912111Sralph 		log("bad action (%d) to dofork", action);
82012111Sralph 		/*FALL THRU*/
82112111Sralph 	case DOABORT:
82212111Sralph 		exit(1);
82312111Sralph 	}
82412111Sralph 	/*NOTREACHED*/
82512111Sralph }
82612111Sralph 
82712111Sralph /*
82812111Sralph  * Cleanup child processes when a SIGINT is caught.
82912111Sralph  */
83012111Sralph onintr()
83112111Sralph {
83212111Sralph 	kill(0, SIGINT);
83312111Sralph 	if (ofilter > 0)
83412111Sralph 		kill(ofilter, SIGCONT);
83512111Sralph 	while (wait(0) > 0)
83612111Sralph 		;
83712111Sralph 	exit(0);
83812111Sralph }
83912111Sralph 
84012111Sralph init()
84112111Sralph {
84212111Sralph 	int status;
84312111Sralph 
84412111Sralph 	if ((status = pgetent(line, printer)) < 0) {
84512111Sralph 		log("can't open printer description file");
84612111Sralph 		exit(1);
84712111Sralph 	} else if (status == 0) {
84812111Sralph 		log("unknown printer");
84912111Sralph 		exit(1);
85012111Sralph 	}
85112111Sralph 	if ((LP = pgetstr("lp", &bp)) == NULL)
85212111Sralph 		LP = DEFDEVLP;
85312111Sralph 	if ((RP = pgetstr("rp", &bp)) == NULL)
85412463Sralph 		RP = DEFLP;
85512111Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
85612111Sralph 		LO = DEFLOCK;
85712111Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
85812111Sralph 		ST = DEFSTAT;
85912111Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
86012111Sralph 		LF = DEFLOGF;
86112111Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
86212111Sralph 		SD = DEFSPOOL;
86312111Sralph 	if ((DU = pgetnum("du")) < 0)
86412111Sralph 		DU = DEFUID;
86512111Sralph 	if ((FF = pgetstr("ff", &bp)) == NULL)
86612111Sralph 		FF = DEFFF;
86712111Sralph 	if ((PW = pgetnum("pw")) < 0)
86812111Sralph 		PW = DEFWIDTH;
86912111Sralph 	sprintf(&width[2], "%d", PW);
87012111Sralph 	if ((PL = pgetnum("pl")) < 0)
87112111Sralph 		PL = DEFLENGTH;
87212111Sralph 	sprintf(&length[2], "%d", PL);
87312463Sralph 	if ((PX = pgetnum("px")) < 0)
87412463Sralph 		PX = 0;
87512463Sralph 	sprintf(&pxwidth[2], "%d", PX);
87612463Sralph 	if ((PY = pgetnum("py")) < 0)
87712463Sralph 		PY = 0;
87812463Sralph 	sprintf(&pxlength[2], "%d", PY);
87912111Sralph 	RM = pgetstr("rm", &bp);
88012111Sralph 	AF = pgetstr("af", &bp);
88112111Sralph 	OF = pgetstr("of", &bp);
88212111Sralph 	IF = pgetstr("if", &bp);
88312463Sralph 	RF = pgetstr("rf", &bp);
88412111Sralph 	TF = pgetstr("tf", &bp);
88512111Sralph 	DF = pgetstr("df", &bp);
88612111Sralph 	GF = pgetstr("gf", &bp);
88712111Sralph 	VF = pgetstr("vf", &bp);
88812111Sralph 	CF = pgetstr("cf", &bp);
88912111Sralph 	TR = pgetstr("tr", &bp);
89012463Sralph 	RS = pgetflag("rs");
89112111Sralph 	SF = pgetflag("sf");
89212111Sralph 	SH = pgetflag("sh");
89312111Sralph 	SB = pgetflag("sb");
89412111Sralph 	RW = pgetflag("rw");
89512111Sralph 	BR = pgetnum("br");
89612111Sralph 	if ((FC = pgetnum("fc")) < 0)
89712111Sralph 		FC = 0;
89812111Sralph 	if ((FS = pgetnum("fs")) < 0)
89912111Sralph 		FS = 0;
90012111Sralph 	if ((XC = pgetnum("xc")) < 0)
90112111Sralph 		XC = 0;
90212111Sralph 	if ((XS = pgetnum("xs")) < 0)
90312111Sralph 		XS = 0;
90412111Sralph }
90512111Sralph 
90612463Sralph /*
90712463Sralph  * Acquire line printer or remote connection.
90812463Sralph  */
90912463Sralph openpr()
91012463Sralph {
91112463Sralph 	register int i, n;
91212463Sralph 
91312463Sralph 	if (*LP) {
91412463Sralph 		for (i = 1; ; i = i < 32 ? i << 1 : i) {
91512463Sralph 			pfd = open(LP, RW ? FRDWR : FWRONLY, 0);
91612463Sralph 			if (pfd >= 0)
91712463Sralph 				break;
91812463Sralph 			if (errno == ENOENT) {
91912463Sralph 				log("cannot open %s", LP);
92012463Sralph 				exit(1);
92112463Sralph 			}
92212463Sralph 			if (i == 1)
92312463Sralph 				status("waiting for %s to become ready (offline ?)", printer);
92412463Sralph 			sleep(i);
92512463Sralph 		}
92612463Sralph 		if (isatty(pfd))
92712463Sralph 			setty();
92812463Sralph 		status("%s is ready and printing", printer);
92912463Sralph 	} else if (RM != NULL) {
93012463Sralph 		for (i = 1; ; i = i < 512 ? i << 1 : i) {
931*12528Sralph 			pfd = getport(RM);
93212463Sralph 			if (pfd >= 0) {
93312463Sralph 				(void) sprintf(line, "\2%s\n", RP);
93412463Sralph 				n = strlen(line);
93512463Sralph 				if (write(pfd, line, n) != n)
93612463Sralph 					break;
93712463Sralph 				if (noresponse())
93812463Sralph 					(void) close(pfd);
93912463Sralph 				else
94012463Sralph 					break;
94112463Sralph 			}
94212463Sralph 			if (i == 1)
94312463Sralph 				status("waiting for %s to come up", RM);
94412463Sralph 			sleep(i);
94512463Sralph 		}
94612463Sralph 		status("sending to %s", RM);
94712463Sralph 		remote = 1;
94812463Sralph 	} else {
94912463Sralph 		log("no line printer device or remote machine name");
95012463Sralph 		exit(1);
95112463Sralph 	}
95212463Sralph 	/*
95312463Sralph 	 * Start up an output filter, if needed.
95412463Sralph 	 */
95512463Sralph 	if (OF) {
95612463Sralph 		int p[2];
95712463Sralph 		char *cp;
95812463Sralph 
95912463Sralph 		pipe(p);
96012463Sralph 		if ((ofilter = dofork(DOABORT)) == 0) {	/* child */
96112463Sralph 			dup2(p[0], 0);		/* pipe is std in */
96212463Sralph 			dup2(pfd, 1);		/* printer is std out */
96312463Sralph 			for (i = 3; i < NOFILE; i++)
96412463Sralph 				(void) close(i);
96512463Sralph 			if ((cp = rindex(OF, '/')) == NULL)
96612463Sralph 				cp = OF;
96712463Sralph 			else
96812463Sralph 				cp++;
96912463Sralph 			execl(OF, cp, width, length, 0);
97012463Sralph 			log("can't execl output filter %s", OF);
97112463Sralph 			exit(1);
97212463Sralph 		}
97312463Sralph 		(void) close(p[0]);		/* close input side */
97412463Sralph 		ofd = p[1];			/* use pipe for output */
97512463Sralph 	} else {
97612463Sralph 		ofd = pfd;
97712463Sralph 		ofilter = 0;
97812463Sralph 	}
97912463Sralph }
98012463Sralph 
98112111Sralph struct bauds {
98212111Sralph 	int	baud;
98312111Sralph 	int	speed;
98412111Sralph } bauds[] = {
98512111Sralph 	50,	B50,
98612111Sralph 	75,	B75,
98712111Sralph 	110,	B110,
98812111Sralph 	134,	B134,
98912111Sralph 	150,	B150,
99012111Sralph 	200,	B200,
99112111Sralph 	300,	B300,
99212111Sralph 	600,	B600,
99312111Sralph 	1200,	B1200,
99412111Sralph 	1800,	B1800,
99512111Sralph 	2400,	B2400,
99612111Sralph 	4800,	B4800,
99712111Sralph 	9600,	B9600,
99812111Sralph 	19200,	EXTA,
99912111Sralph 	38400,	EXTB,
100012111Sralph 	0,	0
100112111Sralph };
100212111Sralph 
100312111Sralph /*
100412111Sralph  * setup tty lines.
100512111Sralph  */
100612111Sralph setty()
100712111Sralph {
100812111Sralph 	struct sgttyb ttybuf;
100912111Sralph 	register struct bauds *bp;
101012111Sralph 
101112111Sralph 	if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
101212111Sralph 		log("cannot set exclusive-use");
101312111Sralph 		exit(1);
101412111Sralph 	}
101512111Sralph 	if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
101612111Sralph 		log("cannot get tty parameters");
101712111Sralph 		exit(1);
101812111Sralph 	}
101912111Sralph 	if (BR > 0) {
102012111Sralph 		for (bp = bauds; bp->baud; bp++)
102112111Sralph 			if (BR == bp->baud)
102212111Sralph 				break;
102312111Sralph 		if (!bp->baud) {
102412111Sralph 			log("illegal baud rate %d", BR);
102512111Sralph 			exit(1);
102612111Sralph 		}
102712111Sralph 		ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
102812111Sralph 	}
102912111Sralph 	if (FC)
103012111Sralph 		ttybuf.sg_flags &= ~FC;
103112111Sralph 	if (FS)
103212111Sralph 		ttybuf.sg_flags |= FS;
103312111Sralph 	if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
103412111Sralph 		log("cannot set tty parameters");
103512111Sralph 		exit(1);
103612111Sralph 	}
103712111Sralph 	if (XC) {
103812111Sralph 		if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
103912111Sralph 			log("cannot set local tty parameters");
104012111Sralph 			exit(1);
104112111Sralph 		}
104212111Sralph 	}
104312111Sralph 	if (XS) {
104412111Sralph 		if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
104512111Sralph 			log("cannot set local tty parameters");
104612111Sralph 			exit(1);
104712111Sralph 		}
104812111Sralph 	}
104912111Sralph }
105012463Sralph 
105112463Sralph /*VARARGS1*/
105212463Sralph static
105312463Sralph status(msg, a1, a2, a3)
105412463Sralph 	char *msg;
105512463Sralph {
105612463Sralph 	register int fd;
105712463Sralph 	char buf[BUFSIZ];
105812463Sralph 
105912463Sralph 	umask(0);
106012463Sralph 	if ((fd = open(ST, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK, 0664)) < 0)
106112463Sralph 		fatal("cannot create status file");
106212463Sralph 	sprintf(buf, msg, a1, a2, a3);
106312463Sralph 	strcat(buf, "\n");
106412463Sralph 	(void) write(fd, buf, strlen(buf));
106512463Sralph 	(void) close(fd);
106612463Sralph }
1067