xref: /csrg-svn/usr.sbin/lpr/lpd/recvjob.c (revision 34936)
122438Sdist /*
222438Sdist  * Copyright (c) 1983 Regents of the University of California.
334203Sbostic  * All rights reserved.
434203Sbostic  *
534203Sbostic  * Redistribution and use in source and binary forms are permitted
6*34936Sbostic  * provided that the above copyright notice and this paragraph are
7*34936Sbostic  * duplicated in all such forms and that any documentation,
8*34936Sbostic  * advertising materials, and other materials related to such
9*34936Sbostic  * distribution and use acknowledge that the software was developed
10*34936Sbostic  * by the University of California, Berkeley.  The name of the
11*34936Sbostic  * University may not be used to endorse or promote products derived
12*34936Sbostic  * from this software without specific prior written permission.
13*34936Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*34936Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*34936Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622438Sdist  */
1722438Sdist 
1813955Ssam #ifndef lint
19*34936Sbostic static char sccsid[] = "@(#)recvjob.c	5.7 (Berkeley) 06/30/88";
2034203Sbostic #endif /* not lint */
2113955Ssam 
2212115Sralph /*
2312115Sralph  * Receive printer jobs from the network, queue them and
2412115Sralph  * start the printer daemon.
2512115Sralph  */
2612115Sralph 
2712115Sralph #include "lp.h"
2816763Sralph #include <sys/fs.h>
2912115Sralph 
3016763Sralph char	*sp = "";
3116763Sralph #define ack()	(void) write(1, sp, 1);
3212115Sralph 
3316763Sralph char    tfname[40];		/* tmp copy of cf before linking */
3429385Smckusick char    dfname[40];		/* data files */
3516763Sralph int	minfree;		/* keep at least minfree blocks available */
3616763Sralph char	*ddev;			/* disk device (for checking free space) */
3716763Sralph int	dfd;			/* file system device descriptor */
3816763Sralph 
3916763Sralph char	*find_dev();
4016763Sralph 
4112115Sralph recvjob()
4212115Sralph {
4312464Sralph 	struct stat stb;
4412115Sralph 	char *bp = pbuf;
4516763Sralph 	int status, rcleanup();
4612115Sralph 
4712115Sralph 	/*
4812115Sralph 	 * Perform lookup for printer name or abbreviation
4912115Sralph 	 */
5012115Sralph 	if ((status = pgetent(line, printer)) < 0)
5116763Sralph 		frecverr("cannot open printer description file");
5212115Sralph 	else if (status == 0)
5316763Sralph 		frecverr("unknown printer %s", printer);
5412115Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
5512115Sralph 		LF = DEFLOGF;
5612115Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
5712115Sralph 		SD = DEFSPOOL;
5812464Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
5912464Sralph 		LO = DEFLOCK;
6012115Sralph 
6125498Seric 	(void) close(2);			/* set up log file */
6225498Seric 	if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
6325498Seric 		syslog(LOG_ERR, "%s: %m", LF);
6425498Seric 		(void) open("/dev/null", O_WRONLY);
6525498Seric 	}
6625498Seric 
6712115Sralph 	if (chdir(SD) < 0)
6816763Sralph 		frecverr("%s: %s: %m", printer, SD);
6916763Sralph 	if (stat(LO, &stb) == 0) {
7016763Sralph 		if (stb.st_mode & 010) {
7116763Sralph 			/* queue is disabled */
7216763Sralph 			putchar('\1');		/* return error code */
7316763Sralph 			exit(1);
7416763Sralph 		}
7516763Sralph 	} else if (stat(SD, &stb) < 0)
7616763Sralph 		frecverr("%s: %s: %m", printer, SD);
7716763Sralph 	minfree = read_number("minfree");
7816763Sralph 	ddev = find_dev(stb.st_dev, S_IFBLK);
7916763Sralph 	if ((dfd = open(ddev, O_RDONLY)) < 0)
8016763Sralph 		syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
8116763Sralph 	signal(SIGTERM, rcleanup);
8216763Sralph 	signal(SIGPIPE, rcleanup);
8312115Sralph 
8412115Sralph 	if (readjob())
8512115Sralph 		printjob();
8612115Sralph }
8712115Sralph 
8816763Sralph char *
8916763Sralph find_dev(dev, type)
9016763Sralph 	register dev_t dev;
9116763Sralph 	register int type;
9216763Sralph {
9316763Sralph 	register DIR *dfd = opendir("/dev");
9416763Sralph 	struct direct *dir;
9516763Sralph 	struct stat stb;
9616763Sralph 	char devname[MAXNAMLEN+6];
9716763Sralph 	char *dp;
9812115Sralph 
9916763Sralph 	strcpy(devname, "/dev/");
10016763Sralph 	while ((dir = readdir(dfd))) {
10116763Sralph 		strcpy(devname + 5, dir->d_name);
10216763Sralph 		if (stat(devname, &stb))
10316763Sralph 			continue;
10416763Sralph 		if ((stb.st_mode & S_IFMT) != type)
10516763Sralph 			continue;
10616763Sralph 		if (dev == stb.st_rdev) {
10716763Sralph 			closedir(dfd);
10816763Sralph 			dp = (char *)malloc(strlen(devname)+1);
10916763Sralph 			strcpy(dp, devname);
11016763Sralph 			return(dp);
11116763Sralph 		}
11216763Sralph 	}
11316763Sralph 	closedir(dfd);
11416763Sralph 	frecverr("cannot find device %d, %d", major(dev), minor(dev));
11516763Sralph 	/*NOTREACHED*/
11616763Sralph }
11716763Sralph 
11812115Sralph /*
11912115Sralph  * Read printer jobs sent by lpd and copy them to the spooling directory.
12012115Sralph  * Return the number of jobs successfully transfered.
12112115Sralph  */
12216763Sralph readjob()
12312115Sralph {
12412115Sralph 	register int size, nfiles;
12512115Sralph 	register char *cp;
12612115Sralph 
12712115Sralph 	ack();
12812115Sralph 	nfiles = 0;
12912115Sralph 	for (;;) {
13012115Sralph 		/*
13112115Sralph 		 * Read a command to tell us what to do
13212115Sralph 		 */
13312115Sralph 		cp = line;
13412115Sralph 		do {
13512115Sralph 			if ((size = read(1, cp, 1)) != 1) {
13612115Sralph 				if (size < 0)
13716763Sralph 					frecverr("%s: Lost connection",printer);
13812115Sralph 				return(nfiles);
13912115Sralph 			}
14012115Sralph 		} while (*cp++ != '\n');
14112115Sralph 		*--cp = '\0';
14212115Sralph 		cp = line;
14312115Sralph 		switch (*cp++) {
14412115Sralph 		case '\1':	/* cleanup because data sent was bad */
14516763Sralph 			rcleanup();
14612115Sralph 			continue;
14712115Sralph 
14812115Sralph 		case '\2':	/* read cf file */
14912115Sralph 			size = 0;
15012115Sralph 			while (*cp >= '0' && *cp <= '9')
15112115Sralph 				size = size * 10 + (*cp++ - '0');
15212115Sralph 			if (*cp++ != ' ')
15312115Sralph 				break;
15427086Sbloom 			/*
15527086Sbloom 			 * host name has been authenticated, we use our
15627086Sbloom 			 * view of the host name since we may be passed
15727086Sbloom 			 * something different than what gethostbyaddr()
15827086Sbloom 			 * returns
15927086Sbloom 			 */
16027086Sbloom 			strcpy(cp + 6, from);
16112115Sralph 			strcpy(tfname, cp);
16212115Sralph 			tfname[0] = 't';
16316763Sralph 			if (!chksize(size)) {
16416763Sralph 				(void) write(1, "\2", 1);
16516763Sralph 				continue;
16616763Sralph 			}
16712115Sralph 			if (!readfile(tfname, size)) {
16816763Sralph 				rcleanup();
16912115Sralph 				continue;
17012115Sralph 			}
17112115Sralph 			if (link(tfname, cp) < 0)
17216763Sralph 				frecverr("%s: %m", tfname);
17312115Sralph 			(void) unlink(tfname);
17412115Sralph 			tfname[0] = '\0';
17512115Sralph 			nfiles++;
17612115Sralph 			continue;
17712115Sralph 
17812115Sralph 		case '\3':	/* read df file */
17912115Sralph 			size = 0;
18012115Sralph 			while (*cp >= '0' && *cp <= '9')
18112115Sralph 				size = size * 10 + (*cp++ - '0');
18212115Sralph 			if (*cp++ != ' ')
18312115Sralph 				break;
18416763Sralph 			if (!chksize(size)) {
18516763Sralph 				(void) write(1, "\2", 1);
18616763Sralph 				continue;
18716763Sralph 			}
18829385Smckusick 			strcpy(dfname, cp);
18929385Smckusick 			(void) readfile(dfname, size);
19012115Sralph 			continue;
19112115Sralph 		}
19216763Sralph 		frecverr("protocol screwup");
19312115Sralph 	}
19412115Sralph }
19512115Sralph 
19612115Sralph /*
19712115Sralph  * Read files send by lpd and copy them to the spooling directory.
19812115Sralph  */
19912115Sralph readfile(file, size)
20012115Sralph 	char *file;
20112115Sralph 	int size;
20212115Sralph {
20312115Sralph 	register char *cp;
20412115Sralph 	char buf[BUFSIZ];
20512115Sralph 	register int i, j, amt;
20612115Sralph 	int fd, err;
20712115Sralph 
20813149Ssam 	fd = open(file, O_WRONLY|O_CREAT, FILMOD);
20912115Sralph 	if (fd < 0)
21016763Sralph 		frecverr("%s: %m", file);
21112115Sralph 	ack();
21212115Sralph 	err = 0;
21312115Sralph 	for (i = 0; i < size; i += BUFSIZ) {
21412115Sralph 		amt = BUFSIZ;
21512115Sralph 		cp = buf;
21612115Sralph 		if (i + amt > size)
21712115Sralph 			amt = size - i;
21812115Sralph 		do {
21912115Sralph 			j = read(1, cp, amt);
22012115Sralph 			if (j <= 0)
22116763Sralph 				frecverr("Lost connection");
22212115Sralph 			amt -= j;
22312115Sralph 			cp += j;
22412115Sralph 		} while (amt > 0);
22512115Sralph 		amt = BUFSIZ;
22612115Sralph 		if (i + amt > size)
22712115Sralph 			amt = size - i;
22813170Sralph 		if (write(fd, buf, amt) != amt) {
22912115Sralph 			err++;
23013170Sralph 			break;
23113170Sralph 		}
23212115Sralph 	}
23312115Sralph 	(void) close(fd);
23412115Sralph 	if (err)
23516763Sralph 		frecverr("%s: write error", file);
23612115Sralph 	if (noresponse()) {		/* file sent had bad data in it */
23712115Sralph 		(void) unlink(file);
23812115Sralph 		return(0);
23912115Sralph 	}
24012115Sralph 	ack();
24112115Sralph 	return(1);
24212115Sralph }
24312115Sralph 
24412115Sralph noresponse()
24512115Sralph {
24612115Sralph 	char resp;
24712115Sralph 
24812115Sralph 	if (read(1, &resp, 1) != 1)
24916763Sralph 		frecverr("Lost connection");
25012115Sralph 	if (resp == '\0')
25112115Sralph 		return(0);
25212115Sralph 	return(1);
25312115Sralph }
25412115Sralph 
25512115Sralph /*
25616763Sralph  * Check to see if there is enough space on the disk for size bytes.
25716763Sralph  * 1 == OK, 0 == Not OK.
25816763Sralph  */
25916763Sralph chksize(size)
26016763Sralph 	int size;
26116763Sralph {
26216763Sralph 	struct stat stb;
26316763Sralph 	register char *ddev;
26416763Sralph 	int spacefree;
26516763Sralph 	struct fs fs;
26616763Sralph 
26730656Smckusick 	if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0)
26816763Sralph 		return(1);
26916763Sralph 	if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
27016763Sralph 		return(1);
27130656Smckusick 	spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024;
27216763Sralph 	size = (size + 1023) / 1024;
27316763Sralph 	if (minfree + size > spacefree)
27416763Sralph 		return(0);
27516763Sralph 	return(1);
27616763Sralph }
27716763Sralph 
27816763Sralph read_number(fn)
27916763Sralph 	char *fn;
28016763Sralph {
28116763Sralph 	char lin[80];
28216763Sralph 	register FILE *fp;
28316763Sralph 
28416763Sralph 	if ((fp = fopen(fn, "r")) == NULL)
28516763Sralph 		return (0);
28616763Sralph 	if (fgets(lin, 80, fp) == NULL) {
28716763Sralph 		fclose(fp);
28816763Sralph 		return (0);
28916763Sralph 	}
29016763Sralph 	fclose(fp);
29116763Sralph 	return (atoi(lin));
29216763Sralph }
29316763Sralph 
29416763Sralph /*
29512115Sralph  * Remove all the files associated with the current job being transfered.
29612115Sralph  */
29716763Sralph rcleanup()
29812115Sralph {
29912115Sralph 
30012115Sralph 	if (tfname[0])
30112115Sralph 		(void) unlink(tfname);
30229385Smckusick 	if (dfname[0])
30312115Sralph 		do {
30412115Sralph 			do
30512115Sralph 				(void) unlink(dfname);
30616938Sralph 			while (dfname[2]-- != 'A');
30716938Sralph 			dfname[2] = 'z';
30816938Sralph 		} while (dfname[0]-- != 'd');
30929385Smckusick 	dfname[0] = '\0';
31012115Sralph }
31112115Sralph 
31216763Sralph frecverr(msg, a1, a2)
31312115Sralph 	char *msg;
31412115Sralph {
31516763Sralph 	rcleanup();
31616763Sralph 	syslog(LOG_ERR, msg, a1, a2);
31712115Sralph 	putchar('\1');		/* return error code */
31812115Sralph 	exit(1);
31912115Sralph }
320