xref: /csrg-svn/usr.sbin/lpr/lpd/recvjob.c (revision 16763)
113955Ssam #ifndef lint
2*16763Sralph static char sccsid[] = "@(#)recvjob.c	4.7 (Berkeley) 07/25/84";
313955Ssam #endif
413955Ssam 
512115Sralph /*
612115Sralph  * Receive printer jobs from the network, queue them and
712115Sralph  * start the printer daemon.
812115Sralph  */
912115Sralph 
1012115Sralph #include "lp.h"
11*16763Sralph #include <sys/fs.h>
1212115Sralph 
13*16763Sralph char	*sp = "";
14*16763Sralph #define ack()	(void) write(1, sp, 1);
1512115Sralph 
16*16763Sralph char    tfname[40];		/* tmp copy of cf before linking */
17*16763Sralph char    *dfname;		/* data files */
18*16763Sralph int	minfree;		/* keep at least minfree blocks available */
19*16763Sralph char	*ddev;			/* disk device (for checking free space) */
20*16763Sralph int	dfd;			/* file system device descriptor */
21*16763Sralph 
22*16763Sralph char	*find_dev();
23*16763Sralph 
2412115Sralph recvjob()
2512115Sralph {
2612464Sralph 	struct stat stb;
2712115Sralph 	char *bp = pbuf;
28*16763Sralph 	int status, rcleanup();
2912115Sralph 
3012115Sralph 	/*
3112115Sralph 	 * Perform lookup for printer name or abbreviation
3212115Sralph 	 */
3312115Sralph 	if ((status = pgetent(line, printer)) < 0)
34*16763Sralph 		frecverr("cannot open printer description file");
3512115Sralph 	else if (status == 0)
36*16763Sralph 		frecverr("unknown printer %s", printer);
3712115Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
3812115Sralph 		LF = DEFLOGF;
3912115Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
4012115Sralph 		SD = DEFSPOOL;
4112464Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
4212464Sralph 		LO = DEFLOCK;
4312115Sralph 
4412115Sralph 	if (chdir(SD) < 0)
45*16763Sralph 		frecverr("%s: %s: %m", printer, SD);
46*16763Sralph 	if (stat(LO, &stb) == 0) {
47*16763Sralph 		if (stb.st_mode & 010) {
48*16763Sralph 			/* queue is disabled */
49*16763Sralph 			putchar('\1');		/* return error code */
50*16763Sralph 			exit(1);
51*16763Sralph 		}
52*16763Sralph 	} else if (stat(SD, &stb) < 0)
53*16763Sralph 		frecverr("%s: %s: %m", printer, SD);
54*16763Sralph 	minfree = read_number("minfree");
55*16763Sralph 	ddev = find_dev(stb.st_dev, S_IFBLK);
56*16763Sralph 	if ((dfd = open(ddev, O_RDONLY)) < 0)
57*16763Sralph 		syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
58*16763Sralph 	signal(SIGTERM, rcleanup);
59*16763Sralph 	signal(SIGPIPE, rcleanup);
6012115Sralph 
6112115Sralph 	if (readjob())
6212115Sralph 		printjob();
6312115Sralph }
6412115Sralph 
65*16763Sralph char *
66*16763Sralph find_dev(dev, type)
67*16763Sralph 	register dev_t dev;
68*16763Sralph 	register int type;
69*16763Sralph {
70*16763Sralph 	register DIR *dfd = opendir("/dev");
71*16763Sralph 	struct direct *dir;
72*16763Sralph 	struct stat stb;
73*16763Sralph 	char devname[MAXNAMLEN+6];
74*16763Sralph 	char *dp;
7512115Sralph 
76*16763Sralph 	strcpy(devname, "/dev/");
77*16763Sralph 	while ((dir = readdir(dfd))) {
78*16763Sralph 		strcpy(devname + 5, dir->d_name);
79*16763Sralph 		if (stat(devname, &stb))
80*16763Sralph 			continue;
81*16763Sralph 		if ((stb.st_mode & S_IFMT) != type)
82*16763Sralph 			continue;
83*16763Sralph 		if (dev == stb.st_rdev) {
84*16763Sralph 			closedir(dfd);
85*16763Sralph 			dp = (char *)malloc(strlen(devname)+1);
86*16763Sralph 			strcpy(dp, devname);
87*16763Sralph 			return(dp);
88*16763Sralph 		}
89*16763Sralph 	}
90*16763Sralph 	closedir(dfd);
91*16763Sralph 	frecverr("cannot find device %d, %d", major(dev), minor(dev));
92*16763Sralph 	/*NOTREACHED*/
93*16763Sralph }
94*16763Sralph 
9512115Sralph /*
9612115Sralph  * Read printer jobs sent by lpd and copy them to the spooling directory.
9712115Sralph  * Return the number of jobs successfully transfered.
9812115Sralph  */
99*16763Sralph readjob()
10012115Sralph {
10112115Sralph 	register int size, nfiles;
10212115Sralph 	register char *cp;
10312115Sralph 
10412115Sralph 	ack();
10512115Sralph 	nfiles = 0;
10612115Sralph 	for (;;) {
10712115Sralph 		/*
10812115Sralph 		 * Read a command to tell us what to do
10912115Sralph 		 */
11012115Sralph 		cp = line;
11112115Sralph 		do {
11212115Sralph 			if ((size = read(1, cp, 1)) != 1) {
11312115Sralph 				if (size < 0)
114*16763Sralph 					frecverr("%s: Lost connection",printer);
11512115Sralph 				return(nfiles);
11612115Sralph 			}
11712115Sralph 		} while (*cp++ != '\n');
11812115Sralph 		*--cp = '\0';
11912115Sralph 		cp = line;
12012115Sralph 		switch (*cp++) {
12112115Sralph 		case '\1':	/* cleanup because data sent was bad */
122*16763Sralph 			rcleanup();
12312115Sralph 			continue;
12412115Sralph 
12512115Sralph 		case '\2':	/* read cf file */
12612115Sralph 			size = 0;
12712115Sralph 			while (*cp >= '0' && *cp <= '9')
12812115Sralph 				size = size * 10 + (*cp++ - '0');
12912115Sralph 			if (*cp++ != ' ')
13012115Sralph 				break;
13112115Sralph 			strcpy(tfname, cp);
13212115Sralph 			tfname[0] = 't';
133*16763Sralph 			if (!chksize(size)) {
134*16763Sralph 				(void) write(1, "\2", 1);
135*16763Sralph 				continue;
136*16763Sralph 			}
13712115Sralph 			if (!readfile(tfname, size)) {
138*16763Sralph 				rcleanup();
13912115Sralph 				continue;
14012115Sralph 			}
14112115Sralph 			if (link(tfname, cp) < 0)
142*16763Sralph 				frecverr("%s: %m", tfname);
14312115Sralph 			(void) unlink(tfname);
14412115Sralph 			tfname[0] = '\0';
14512115Sralph 			nfiles++;
14612115Sralph 			continue;
14712115Sralph 
14812115Sralph 		case '\3':	/* read df file */
14912115Sralph 			size = 0;
15012115Sralph 			while (*cp >= '0' && *cp <= '9')
15112115Sralph 				size = size * 10 + (*cp++ - '0');
15212115Sralph 			if (*cp++ != ' ')
15312115Sralph 				break;
154*16763Sralph 			if (!chksize(size)) {
155*16763Sralph 				(void) write(1, "\2", 1);
156*16763Sralph 				continue;
157*16763Sralph 			}
15812115Sralph 			(void) readfile(dfname = cp, size);
15912115Sralph 			continue;
16012115Sralph 		}
161*16763Sralph 		frecverr("protocol screwup");
16212115Sralph 	}
16312115Sralph }
16412115Sralph 
16512115Sralph /*
16612115Sralph  * Read files send by lpd and copy them to the spooling directory.
16712115Sralph  */
16812115Sralph readfile(file, size)
16912115Sralph 	char *file;
17012115Sralph 	int size;
17112115Sralph {
17212115Sralph 	register char *cp;
17312115Sralph 	char buf[BUFSIZ];
17412115Sralph 	register int i, j, amt;
17512115Sralph 	int fd, err;
17612115Sralph 
17713149Ssam 	fd = open(file, O_WRONLY|O_CREAT, FILMOD);
17812115Sralph 	if (fd < 0)
179*16763Sralph 		frecverr("%s: %m", file);
18012115Sralph 	ack();
18112115Sralph 	err = 0;
18212115Sralph 	for (i = 0; i < size; i += BUFSIZ) {
18312115Sralph 		amt = BUFSIZ;
18412115Sralph 		cp = buf;
18512115Sralph 		if (i + amt > size)
18612115Sralph 			amt = size - i;
18712115Sralph 		do {
18812115Sralph 			j = read(1, cp, amt);
18912115Sralph 			if (j <= 0)
190*16763Sralph 				frecverr("Lost connection");
19112115Sralph 			amt -= j;
19212115Sralph 			cp += j;
19312115Sralph 		} while (amt > 0);
19412115Sralph 		amt = BUFSIZ;
19512115Sralph 		if (i + amt > size)
19612115Sralph 			amt = size - i;
19713170Sralph 		if (write(fd, buf, amt) != amt) {
19812115Sralph 			err++;
19913170Sralph 			break;
20013170Sralph 		}
20112115Sralph 	}
20212115Sralph 	(void) close(fd);
20312115Sralph 	if (err)
204*16763Sralph 		frecverr("%s: write error", file);
20512115Sralph 	if (noresponse()) {		/* file sent had bad data in it */
20612115Sralph 		(void) unlink(file);
20712115Sralph 		return(0);
20812115Sralph 	}
20912115Sralph 	ack();
21012115Sralph 	return(1);
21112115Sralph }
21212115Sralph 
21312115Sralph noresponse()
21412115Sralph {
21512115Sralph 	char resp;
21612115Sralph 
21712115Sralph 	if (read(1, &resp, 1) != 1)
218*16763Sralph 		frecverr("Lost connection");
21912115Sralph 	if (resp == '\0')
22012115Sralph 		return(0);
22112115Sralph 	return(1);
22212115Sralph }
22312115Sralph 
22412115Sralph /*
225*16763Sralph  * Check to see if there is enough space on the disk for size bytes.
226*16763Sralph  * 1 == OK, 0 == Not OK.
227*16763Sralph  */
228*16763Sralph chksize(size)
229*16763Sralph 	int size;
230*16763Sralph {
231*16763Sralph 	struct stat stb;
232*16763Sralph 	register char *ddev;
233*16763Sralph 	int spacefree;
234*16763Sralph 	struct fs fs;
235*16763Sralph 
236*16763Sralph 	if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0)
237*16763Sralph 		return(1);
238*16763Sralph 	if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
239*16763Sralph 		return(1);
240*16763Sralph 	spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag +
241*16763Sralph 		fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) *
242*16763Sralph 			fs.fs_fsize / 1024;
243*16763Sralph 	size = (size + 1023) / 1024;
244*16763Sralph 	if (minfree + size > spacefree)
245*16763Sralph 		return(0);
246*16763Sralph 	return(1);
247*16763Sralph }
248*16763Sralph 
249*16763Sralph read_number(fn)
250*16763Sralph 	char *fn;
251*16763Sralph {
252*16763Sralph 	char lin[80];
253*16763Sralph 	register FILE *fp;
254*16763Sralph 
255*16763Sralph 	if ((fp = fopen(fn, "r")) == NULL)
256*16763Sralph 		return (0);
257*16763Sralph 	if (fgets(lin, 80, fp) == NULL) {
258*16763Sralph 		fclose(fp);
259*16763Sralph 		return (0);
260*16763Sralph 	}
261*16763Sralph 	fclose(fp);
262*16763Sralph 	return (atoi(lin));
263*16763Sralph }
264*16763Sralph 
265*16763Sralph /*
26612115Sralph  * Remove all the files associated with the current job being transfered.
26712115Sralph  */
268*16763Sralph rcleanup()
26912115Sralph {
27012115Sralph 	register int i;
27112115Sralph 
27212115Sralph 	if (tfname[0])
27312115Sralph 		(void) unlink(tfname);
27412115Sralph 	if (dfname)
27512115Sralph 		do {
27612115Sralph 			do
27712115Sralph 				(void) unlink(dfname);
27812115Sralph 			while (dfname[i]-- != 'A');
27912115Sralph 			dfname[i] = 'z';
28012115Sralph 		} while (dfname[i-2]-- != 'd');
28112115Sralph }
28212115Sralph 
283*16763Sralph frecverr(msg, a1, a2)
28412115Sralph 	char *msg;
28512115Sralph {
286*16763Sralph 	rcleanup();
287*16763Sralph 	syslog(LOG_ERR, msg, a1, a2);
28812115Sralph 	putchar('\1');		/* return error code */
28912115Sralph 	exit(1);
29012115Sralph }
291