xref: /csrg-svn/usr.sbin/lpr/lpd/recvjob.c (revision 49120)
122438Sdist /*
222438Sdist  * Copyright (c) 1983 Regents of the University of California.
334203Sbostic  * All rights reserved.
434203Sbostic  *
542802Sbostic  * %sccs.include.redist.c%
622438Sdist  */
722438Sdist 
813955Ssam #ifndef lint
9*49120Smckusick static char sccsid[] = "@(#)recvjob.c	5.15 (Berkeley) 05/04/91";
1034203Sbostic #endif /* not lint */
1113955Ssam 
1212115Sralph /*
1312115Sralph  * Receive printer jobs from the network, queue them and
1412115Sralph  * start the printer daemon.
1512115Sralph  */
1612115Sralph 
1712115Sralph #include "lp.h"
1837968Sbostic #include "pathnames.h"
1948962Smckusick #include <sys/mount.h>
2012115Sralph 
2116763Sralph char	*sp = "";
2216763Sralph #define ack()	(void) write(1, sp, 1);
2312115Sralph 
2416763Sralph char    tfname[40];		/* tmp copy of cf before linking */
2529385Smckusick char    dfname[40];		/* data files */
2616763Sralph int	minfree;		/* keep at least minfree blocks available */
2716763Sralph 
2846913Sbostic void	rcleanup();
2916763Sralph 
3012115Sralph recvjob()
3112115Sralph {
3212464Sralph 	struct stat stb;
3312115Sralph 	char *bp = pbuf;
3446913Sbostic 	int status;
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)
4437968Sbostic 		LF = _PATH_CONSOLE;
4512115Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
4637968Sbostic 		SD = _PATH_DEFSPOOL;
4712464Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
4812464Sralph 		LO = DEFLOCK;
4912115Sralph 
5025498Seric 	(void) close(2);			/* set up log file */
5125498Seric 	if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
5225498Seric 		syslog(LOG_ERR, "%s: %m", LF);
5337968Sbostic 		(void) open(_PATH_DEVNULL, O_WRONLY);
5425498Seric 	}
5525498Seric 
5612115Sralph 	if (chdir(SD) < 0)
5716763Sralph 		frecverr("%s: %s: %m", printer, SD);
5816763Sralph 	if (stat(LO, &stb) == 0) {
5916763Sralph 		if (stb.st_mode & 010) {
6016763Sralph 			/* queue is disabled */
6116763Sralph 			putchar('\1');		/* return error code */
6216763Sralph 			exit(1);
6316763Sralph 		}
6416763Sralph 	} else if (stat(SD, &stb) < 0)
6516763Sralph 		frecverr("%s: %s: %m", printer, SD);
6648962Smckusick 	minfree = 2 * read_number("minfree");	/* scale KB to 512 blocks */
6716763Sralph 	signal(SIGTERM, rcleanup);
6816763Sralph 	signal(SIGPIPE, rcleanup);
6912115Sralph 
7012115Sralph 	if (readjob())
7112115Sralph 		printjob();
7212115Sralph }
7312115Sralph 
7412115Sralph /*
7512115Sralph  * Read printer jobs sent by lpd and copy them to the spooling directory.
7612115Sralph  * Return the number of jobs successfully transfered.
7712115Sralph  */
7816763Sralph readjob()
7912115Sralph {
8012115Sralph 	register int size, nfiles;
8112115Sralph 	register char *cp;
8212115Sralph 
8312115Sralph 	ack();
8412115Sralph 	nfiles = 0;
8512115Sralph 	for (;;) {
8612115Sralph 		/*
8712115Sralph 		 * Read a command to tell us what to do
8812115Sralph 		 */
8912115Sralph 		cp = line;
9012115Sralph 		do {
9112115Sralph 			if ((size = read(1, cp, 1)) != 1) {
9212115Sralph 				if (size < 0)
9316763Sralph 					frecverr("%s: Lost connection",printer);
9412115Sralph 				return(nfiles);
9512115Sralph 			}
9612115Sralph 		} while (*cp++ != '\n');
9712115Sralph 		*--cp = '\0';
9812115Sralph 		cp = line;
9912115Sralph 		switch (*cp++) {
10012115Sralph 		case '\1':	/* cleanup because data sent was bad */
10116763Sralph 			rcleanup();
10212115Sralph 			continue;
10312115Sralph 
10412115Sralph 		case '\2':	/* read cf file */
10512115Sralph 			size = 0;
10612115Sralph 			while (*cp >= '0' && *cp <= '9')
10712115Sralph 				size = size * 10 + (*cp++ - '0');
10812115Sralph 			if (*cp++ != ' ')
10912115Sralph 				break;
11027086Sbloom 			/*
11127086Sbloom 			 * host name has been authenticated, we use our
11227086Sbloom 			 * view of the host name since we may be passed
11327086Sbloom 			 * something different than what gethostbyaddr()
11427086Sbloom 			 * returns
11527086Sbloom 			 */
11627086Sbloom 			strcpy(cp + 6, from);
11712115Sralph 			strcpy(tfname, cp);
11812115Sralph 			tfname[0] = 't';
11916763Sralph 			if (!chksize(size)) {
12016763Sralph 				(void) write(1, "\2", 1);
12116763Sralph 				continue;
12216763Sralph 			}
12312115Sralph 			if (!readfile(tfname, size)) {
12416763Sralph 				rcleanup();
12512115Sralph 				continue;
12612115Sralph 			}
12712115Sralph 			if (link(tfname, cp) < 0)
12816763Sralph 				frecverr("%s: %m", tfname);
12912115Sralph 			(void) unlink(tfname);
13012115Sralph 			tfname[0] = '\0';
13112115Sralph 			nfiles++;
13212115Sralph 			continue;
13312115Sralph 
13412115Sralph 		case '\3':	/* read df file */
13512115Sralph 			size = 0;
13612115Sralph 			while (*cp >= '0' && *cp <= '9')
13712115Sralph 				size = size * 10 + (*cp++ - '0');
13812115Sralph 			if (*cp++ != ' ')
13912115Sralph 				break;
14016763Sralph 			if (!chksize(size)) {
14116763Sralph 				(void) write(1, "\2", 1);
14216763Sralph 				continue;
14316763Sralph 			}
14439220Sbostic 			(void) strcpy(dfname, cp);
14539220Sbostic 			if (index(dfname, '/'))
146*49120Smckusick 				frecverr("readjob: %s: illegal path name",
147*49120Smckusick 					dfname);
14829385Smckusick 			(void) readfile(dfname, size);
14912115Sralph 			continue;
15012115Sralph 		}
15116763Sralph 		frecverr("protocol screwup");
15212115Sralph 	}
15312115Sralph }
15412115Sralph 
15512115Sralph /*
15612115Sralph  * Read files send by lpd and copy them to the spooling directory.
15712115Sralph  */
15812115Sralph readfile(file, size)
15912115Sralph 	char *file;
16012115Sralph 	int size;
16112115Sralph {
16212115Sralph 	register char *cp;
16312115Sralph 	char buf[BUFSIZ];
16412115Sralph 	register int i, j, amt;
16512115Sralph 	int fd, err;
16612115Sralph 
16748962Smckusick 	fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
16812115Sralph 	if (fd < 0)
169*49120Smckusick 		frecverr("readfile: %s: illegal path name: %m", file);
17012115Sralph 	ack();
17112115Sralph 	err = 0;
17212115Sralph 	for (i = 0; i < size; i += BUFSIZ) {
17312115Sralph 		amt = BUFSIZ;
17412115Sralph 		cp = buf;
17512115Sralph 		if (i + amt > size)
17612115Sralph 			amt = size - i;
17712115Sralph 		do {
17812115Sralph 			j = read(1, cp, amt);
17912115Sralph 			if (j <= 0)
18016763Sralph 				frecverr("Lost connection");
18112115Sralph 			amt -= j;
18212115Sralph 			cp += j;
18312115Sralph 		} while (amt > 0);
18412115Sralph 		amt = BUFSIZ;
18512115Sralph 		if (i + amt > size)
18612115Sralph 			amt = size - i;
18713170Sralph 		if (write(fd, buf, amt) != amt) {
18812115Sralph 			err++;
18913170Sralph 			break;
19013170Sralph 		}
19112115Sralph 	}
19212115Sralph 	(void) close(fd);
19312115Sralph 	if (err)
19416763Sralph 		frecverr("%s: write error", file);
19512115Sralph 	if (noresponse()) {		/* file sent had bad data in it */
19612115Sralph 		(void) unlink(file);
19712115Sralph 		return(0);
19812115Sralph 	}
19912115Sralph 	ack();
20012115Sralph 	return(1);
20112115Sralph }
20212115Sralph 
20312115Sralph noresponse()
20412115Sralph {
20512115Sralph 	char resp;
20612115Sralph 
20712115Sralph 	if (read(1, &resp, 1) != 1)
20816763Sralph 		frecverr("Lost connection");
20912115Sralph 	if (resp == '\0')
21012115Sralph 		return(0);
21112115Sralph 	return(1);
21212115Sralph }
21312115Sralph 
21412115Sralph /*
21516763Sralph  * Check to see if there is enough space on the disk for size bytes.
21616763Sralph  * 1 == OK, 0 == Not OK.
21716763Sralph  */
21816763Sralph chksize(size)
21916763Sralph 	int size;
22016763Sralph {
22116763Sralph 	int spacefree;
22248962Smckusick 	struct statfs sfb;
22316763Sralph 
22448962Smckusick 	if (statfs(".", &sfb) < 0) {
22548962Smckusick 		syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
22648962Smckusick 		return (1);
22748962Smckusick 	}
22848962Smckusick 	spacefree = sfb.f_bavail * (sfb.f_fsize / 512);
22948962Smckusick 	size = (size + 511) / 512;
23016763Sralph 	if (minfree + size > spacefree)
23116763Sralph 		return(0);
23216763Sralph 	return(1);
23316763Sralph }
23416763Sralph 
23516763Sralph read_number(fn)
23616763Sralph 	char *fn;
23716763Sralph {
23816763Sralph 	char lin[80];
23916763Sralph 	register FILE *fp;
24016763Sralph 
24116763Sralph 	if ((fp = fopen(fn, "r")) == NULL)
24216763Sralph 		return (0);
24316763Sralph 	if (fgets(lin, 80, fp) == NULL) {
24416763Sralph 		fclose(fp);
24516763Sralph 		return (0);
24616763Sralph 	}
24716763Sralph 	fclose(fp);
24816763Sralph 	return (atoi(lin));
24916763Sralph }
25016763Sralph 
25116763Sralph /*
25212115Sralph  * Remove all the files associated with the current job being transfered.
25312115Sralph  */
25446913Sbostic void
25516763Sralph rcleanup()
25612115Sralph {
25712115Sralph 
25812115Sralph 	if (tfname[0])
25912115Sralph 		(void) unlink(tfname);
26029385Smckusick 	if (dfname[0])
26112115Sralph 		do {
26212115Sralph 			do
26312115Sralph 				(void) unlink(dfname);
26416938Sralph 			while (dfname[2]-- != 'A');
26516938Sralph 			dfname[2] = 'z';
26616938Sralph 		} while (dfname[0]-- != 'd');
26729385Smckusick 	dfname[0] = '\0';
26812115Sralph }
26912115Sralph 
27016763Sralph frecverr(msg, a1, a2)
27112115Sralph 	char *msg;
27212115Sralph {
27316763Sralph 	rcleanup();
27416763Sralph 	syslog(LOG_ERR, msg, a1, a2);
27512115Sralph 	putchar('\1');		/* return error code */
27612115Sralph 	exit(1);
27712115Sralph }
278