xref: /csrg-svn/usr.sbin/lpr/lpd/recvjob.c (revision 22438)
1*22438Sdist /*
2*22438Sdist  * Copyright (c) 1983 Regents of the University of California.
3*22438Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22438Sdist  * specifies the terms and conditions for redistribution.
5*22438Sdist  */
6*22438Sdist 
713955Ssam #ifndef lint
8*22438Sdist static char sccsid[] = "@(#)recvjob.c	5.1 (Berkeley) 06/06/85";
9*22438Sdist #endif not lint
1013955Ssam 
1112115Sralph /*
1212115Sralph  * Receive printer jobs from the network, queue them and
1312115Sralph  * start the printer daemon.
1412115Sralph  */
1512115Sralph 
1612115Sralph #include "lp.h"
1716763Sralph #include <sys/fs.h>
1812115Sralph 
1916763Sralph char	*sp = "";
2016763Sralph #define ack()	(void) write(1, sp, 1);
2112115Sralph 
2216763Sralph char    tfname[40];		/* tmp copy of cf before linking */
2316763Sralph char    *dfname;		/* data files */
2416763Sralph int	minfree;		/* keep at least minfree blocks available */
2516763Sralph char	*ddev;			/* disk device (for checking free space) */
2616763Sralph int	dfd;			/* file system device descriptor */
2716763Sralph 
2816763Sralph char	*find_dev();
2916763Sralph 
3012115Sralph recvjob()
3112115Sralph {
3212464Sralph 	struct stat stb;
3312115Sralph 	char *bp = pbuf;
3416763Sralph 	int status, rcleanup();
3512115Sralph 
3612115Sralph 	/*
3712115Sralph 	 * Perform lookup for printer name or abbreviation
3812115Sralph 	 */
3912115Sralph 	if ((status = pgetent(line, printer)) < 0)
4016763Sralph 		frecverr("cannot open printer description file");
4112115Sralph 	else if (status == 0)
4216763Sralph 		frecverr("unknown printer %s", printer);
4312115Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
4412115Sralph 		LF = DEFLOGF;
4512115Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
4612115Sralph 		SD = DEFSPOOL;
4712464Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
4812464Sralph 		LO = DEFLOCK;
4912115Sralph 
5012115Sralph 	if (chdir(SD) < 0)
5116763Sralph 		frecverr("%s: %s: %m", printer, SD);
5216763Sralph 	if (stat(LO, &stb) == 0) {
5316763Sralph 		if (stb.st_mode & 010) {
5416763Sralph 			/* queue is disabled */
5516763Sralph 			putchar('\1');		/* return error code */
5616763Sralph 			exit(1);
5716763Sralph 		}
5816763Sralph 	} else if (stat(SD, &stb) < 0)
5916763Sralph 		frecverr("%s: %s: %m", printer, SD);
6016763Sralph 	minfree = read_number("minfree");
6116763Sralph 	ddev = find_dev(stb.st_dev, S_IFBLK);
6216763Sralph 	if ((dfd = open(ddev, O_RDONLY)) < 0)
6316763Sralph 		syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
6416763Sralph 	signal(SIGTERM, rcleanup);
6516763Sralph 	signal(SIGPIPE, rcleanup);
6612115Sralph 
6712115Sralph 	if (readjob())
6812115Sralph 		printjob();
6912115Sralph }
7012115Sralph 
7116763Sralph char *
7216763Sralph find_dev(dev, type)
7316763Sralph 	register dev_t dev;
7416763Sralph 	register int type;
7516763Sralph {
7616763Sralph 	register DIR *dfd = opendir("/dev");
7716763Sralph 	struct direct *dir;
7816763Sralph 	struct stat stb;
7916763Sralph 	char devname[MAXNAMLEN+6];
8016763Sralph 	char *dp;
8112115Sralph 
8216763Sralph 	strcpy(devname, "/dev/");
8316763Sralph 	while ((dir = readdir(dfd))) {
8416763Sralph 		strcpy(devname + 5, dir->d_name);
8516763Sralph 		if (stat(devname, &stb))
8616763Sralph 			continue;
8716763Sralph 		if ((stb.st_mode & S_IFMT) != type)
8816763Sralph 			continue;
8916763Sralph 		if (dev == stb.st_rdev) {
9016763Sralph 			closedir(dfd);
9116763Sralph 			dp = (char *)malloc(strlen(devname)+1);
9216763Sralph 			strcpy(dp, devname);
9316763Sralph 			return(dp);
9416763Sralph 		}
9516763Sralph 	}
9616763Sralph 	closedir(dfd);
9716763Sralph 	frecverr("cannot find device %d, %d", major(dev), minor(dev));
9816763Sralph 	/*NOTREACHED*/
9916763Sralph }
10016763Sralph 
10112115Sralph /*
10212115Sralph  * Read printer jobs sent by lpd and copy them to the spooling directory.
10312115Sralph  * Return the number of jobs successfully transfered.
10412115Sralph  */
10516763Sralph readjob()
10612115Sralph {
10712115Sralph 	register int size, nfiles;
10812115Sralph 	register char *cp;
10912115Sralph 
11012115Sralph 	ack();
11112115Sralph 	nfiles = 0;
11212115Sralph 	for (;;) {
11312115Sralph 		/*
11412115Sralph 		 * Read a command to tell us what to do
11512115Sralph 		 */
11612115Sralph 		cp = line;
11712115Sralph 		do {
11812115Sralph 			if ((size = read(1, cp, 1)) != 1) {
11912115Sralph 				if (size < 0)
12016763Sralph 					frecverr("%s: Lost connection",printer);
12112115Sralph 				return(nfiles);
12212115Sralph 			}
12312115Sralph 		} while (*cp++ != '\n');
12412115Sralph 		*--cp = '\0';
12512115Sralph 		cp = line;
12612115Sralph 		switch (*cp++) {
12712115Sralph 		case '\1':	/* cleanup because data sent was bad */
12816763Sralph 			rcleanup();
12912115Sralph 			continue;
13012115Sralph 
13112115Sralph 		case '\2':	/* read cf file */
13212115Sralph 			size = 0;
13312115Sralph 			while (*cp >= '0' && *cp <= '9')
13412115Sralph 				size = size * 10 + (*cp++ - '0');
13512115Sralph 			if (*cp++ != ' ')
13612115Sralph 				break;
13712115Sralph 			strcpy(tfname, cp);
13812115Sralph 			tfname[0] = 't';
13916763Sralph 			if (!chksize(size)) {
14016763Sralph 				(void) write(1, "\2", 1);
14116763Sralph 				continue;
14216763Sralph 			}
14312115Sralph 			if (!readfile(tfname, size)) {
14416763Sralph 				rcleanup();
14512115Sralph 				continue;
14612115Sralph 			}
14712115Sralph 			if (link(tfname, cp) < 0)
14816763Sralph 				frecverr("%s: %m", tfname);
14912115Sralph 			(void) unlink(tfname);
15012115Sralph 			tfname[0] = '\0';
15112115Sralph 			nfiles++;
15212115Sralph 			continue;
15312115Sralph 
15412115Sralph 		case '\3':	/* read df file */
15512115Sralph 			size = 0;
15612115Sralph 			while (*cp >= '0' && *cp <= '9')
15712115Sralph 				size = size * 10 + (*cp++ - '0');
15812115Sralph 			if (*cp++ != ' ')
15912115Sralph 				break;
16016763Sralph 			if (!chksize(size)) {
16116763Sralph 				(void) write(1, "\2", 1);
16216763Sralph 				continue;
16316763Sralph 			}
16412115Sralph 			(void) readfile(dfname = cp, size);
16512115Sralph 			continue;
16612115Sralph 		}
16716763Sralph 		frecverr("protocol screwup");
16812115Sralph 	}
16912115Sralph }
17012115Sralph 
17112115Sralph /*
17212115Sralph  * Read files send by lpd and copy them to the spooling directory.
17312115Sralph  */
17412115Sralph readfile(file, size)
17512115Sralph 	char *file;
17612115Sralph 	int size;
17712115Sralph {
17812115Sralph 	register char *cp;
17912115Sralph 	char buf[BUFSIZ];
18012115Sralph 	register int i, j, amt;
18112115Sralph 	int fd, err;
18212115Sralph 
18313149Ssam 	fd = open(file, O_WRONLY|O_CREAT, FILMOD);
18412115Sralph 	if (fd < 0)
18516763Sralph 		frecverr("%s: %m", file);
18612115Sralph 	ack();
18712115Sralph 	err = 0;
18812115Sralph 	for (i = 0; i < size; i += BUFSIZ) {
18912115Sralph 		amt = BUFSIZ;
19012115Sralph 		cp = buf;
19112115Sralph 		if (i + amt > size)
19212115Sralph 			amt = size - i;
19312115Sralph 		do {
19412115Sralph 			j = read(1, cp, amt);
19512115Sralph 			if (j <= 0)
19616763Sralph 				frecverr("Lost connection");
19712115Sralph 			amt -= j;
19812115Sralph 			cp += j;
19912115Sralph 		} while (amt > 0);
20012115Sralph 		amt = BUFSIZ;
20112115Sralph 		if (i + amt > size)
20212115Sralph 			amt = size - i;
20313170Sralph 		if (write(fd, buf, amt) != amt) {
20412115Sralph 			err++;
20513170Sralph 			break;
20613170Sralph 		}
20712115Sralph 	}
20812115Sralph 	(void) close(fd);
20912115Sralph 	if (err)
21016763Sralph 		frecverr("%s: write error", file);
21112115Sralph 	if (noresponse()) {		/* file sent had bad data in it */
21212115Sralph 		(void) unlink(file);
21312115Sralph 		return(0);
21412115Sralph 	}
21512115Sralph 	ack();
21612115Sralph 	return(1);
21712115Sralph }
21812115Sralph 
21912115Sralph noresponse()
22012115Sralph {
22112115Sralph 	char resp;
22212115Sralph 
22312115Sralph 	if (read(1, &resp, 1) != 1)
22416763Sralph 		frecverr("Lost connection");
22512115Sralph 	if (resp == '\0')
22612115Sralph 		return(0);
22712115Sralph 	return(1);
22812115Sralph }
22912115Sralph 
23012115Sralph /*
23116763Sralph  * Check to see if there is enough space on the disk for size bytes.
23216763Sralph  * 1 == OK, 0 == Not OK.
23316763Sralph  */
23416763Sralph chksize(size)
23516763Sralph 	int size;
23616763Sralph {
23716763Sralph 	struct stat stb;
23816763Sralph 	register char *ddev;
23916763Sralph 	int spacefree;
24016763Sralph 	struct fs fs;
24116763Sralph 
24216763Sralph 	if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0)
24316763Sralph 		return(1);
24416763Sralph 	if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
24516763Sralph 		return(1);
24616763Sralph 	spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag +
24716763Sralph 		fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) *
24816763Sralph 			fs.fs_fsize / 1024;
24916763Sralph 	size = (size + 1023) / 1024;
25016763Sralph 	if (minfree + size > spacefree)
25116763Sralph 		return(0);
25216763Sralph 	return(1);
25316763Sralph }
25416763Sralph 
25516763Sralph read_number(fn)
25616763Sralph 	char *fn;
25716763Sralph {
25816763Sralph 	char lin[80];
25916763Sralph 	register FILE *fp;
26016763Sralph 
26116763Sralph 	if ((fp = fopen(fn, "r")) == NULL)
26216763Sralph 		return (0);
26316763Sralph 	if (fgets(lin, 80, fp) == NULL) {
26416763Sralph 		fclose(fp);
26516763Sralph 		return (0);
26616763Sralph 	}
26716763Sralph 	fclose(fp);
26816763Sralph 	return (atoi(lin));
26916763Sralph }
27016763Sralph 
27116763Sralph /*
27212115Sralph  * Remove all the files associated with the current job being transfered.
27312115Sralph  */
27416763Sralph rcleanup()
27512115Sralph {
27612115Sralph 
27712115Sralph 	if (tfname[0])
27812115Sralph 		(void) unlink(tfname);
27912115Sralph 	if (dfname)
28012115Sralph 		do {
28112115Sralph 			do
28212115Sralph 				(void) unlink(dfname);
28316938Sralph 			while (dfname[2]-- != 'A');
28416938Sralph 			dfname[2] = 'z';
28516938Sralph 		} while (dfname[0]-- != 'd');
28612115Sralph }
28712115Sralph 
28816763Sralph frecverr(msg, a1, a2)
28912115Sralph 	char *msg;
29012115Sralph {
29116763Sralph 	rcleanup();
29216763Sralph 	syslog(LOG_ERR, msg, a1, a2);
29312115Sralph 	putchar('\1');		/* return error code */
29412115Sralph 	exit(1);
29512115Sralph }
296