xref: /csrg-svn/usr.sbin/lpr/lpd/recvjob.c (revision 55474)
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*55474Sbostic static char sccsid[] = "@(#)recvjob.c	5.17 (Berkeley) 07/21/92";
1034203Sbostic #endif /* not lint */
1113955Ssam 
1212115Sralph /*
1312115Sralph  * Receive printer jobs from the network, queue them and
1412115Sralph  * start the printer daemon.
1512115Sralph  */
16*55474Sbostic #include <sys/param.h>
17*55474Sbostic #include <sys/mount.h>
18*55474Sbostic #include <sys/stat.h>
1912115Sralph 
20*55474Sbostic #include <signal.h>
21*55474Sbostic #include <fcntl.h>
22*55474Sbostic #include <dirent.h>
23*55474Sbostic #include <syslog.h>
24*55474Sbostic #include <stdio.h>
2512115Sralph #include "lp.h"
26*55474Sbostic #include "lp.local.h"
27*55474Sbostic #include "extern.h"
2837968Sbostic #include "pathnames.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 
37*55474Sbostic static int        readjob __P((void));
38*55474Sbostic static int        readfile __P((char *, int));
39*55474Sbostic static int        noresponse __P((void));
40*55474Sbostic static int        chksize __P((int));
41*55474Sbostic static void       frecverr __P((const char *, ...));
42*55474Sbostic static int        read_number __P((char *));
43*55474Sbostic static void       rcleanup __P((int));
4416763Sralph 
45*55474Sbostic 
46*55474Sbostic int
4712115Sralph recvjob()
4812115Sralph {
4912464Sralph 	struct stat stb;
5012115Sralph 	char *bp = pbuf;
5146913Sbostic 	int status;
5212115Sralph 
5312115Sralph 	/*
5412115Sralph 	 * Perform lookup for printer name or abbreviation
5512115Sralph 	 */
5612115Sralph 	if ((status = pgetent(line, printer)) < 0)
5716763Sralph 		frecverr("cannot open printer description file");
5812115Sralph 	else if (status == 0)
5916763Sralph 		frecverr("unknown printer %s", printer);
6012115Sralph 	if ((LF = pgetstr("lf", &bp)) == NULL)
6137968Sbostic 		LF = _PATH_CONSOLE;
6212115Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
6337968Sbostic 		SD = _PATH_DEFSPOOL;
6412464Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
6512464Sralph 		LO = DEFLOCK;
6612115Sralph 
6725498Seric 	(void) close(2);			/* set up log file */
6825498Seric 	if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
6925498Seric 		syslog(LOG_ERR, "%s: %m", LF);
7037968Sbostic 		(void) open(_PATH_DEVNULL, O_WRONLY);
7125498Seric 	}
7225498Seric 
7312115Sralph 	if (chdir(SD) < 0)
7416763Sralph 		frecverr("%s: %s: %m", printer, SD);
7516763Sralph 	if (stat(LO, &stb) == 0) {
7616763Sralph 		if (stb.st_mode & 010) {
7716763Sralph 			/* queue is disabled */
7816763Sralph 			putchar('\1');		/* return error code */
7916763Sralph 			exit(1);
8016763Sralph 		}
8116763Sralph 	} else if (stat(SD, &stb) < 0)
8216763Sralph 		frecverr("%s: %s: %m", printer, SD);
8348962Smckusick 	minfree = 2 * read_number("minfree");	/* scale KB to 512 blocks */
8416763Sralph 	signal(SIGTERM, rcleanup);
8516763Sralph 	signal(SIGPIPE, rcleanup);
8612115Sralph 
8712115Sralph 	if (readjob())
8812115Sralph 		printjob();
8912115Sralph }
9012115Sralph 
9112115Sralph /*
9212115Sralph  * Read printer jobs sent by lpd and copy them to the spooling directory.
9312115Sralph  * Return the number of jobs successfully transfered.
9412115Sralph  */
95*55474Sbostic static int
9616763Sralph readjob()
9712115Sralph {
9812115Sralph 	register int size, nfiles;
9912115Sralph 	register char *cp;
10012115Sralph 
10112115Sralph 	ack();
10212115Sralph 	nfiles = 0;
10312115Sralph 	for (;;) {
10412115Sralph 		/*
10512115Sralph 		 * Read a command to tell us what to do
10612115Sralph 		 */
10712115Sralph 		cp = line;
10812115Sralph 		do {
10912115Sralph 			if ((size = read(1, cp, 1)) != 1) {
11012115Sralph 				if (size < 0)
11116763Sralph 					frecverr("%s: Lost connection",printer);
11212115Sralph 				return(nfiles);
11312115Sralph 			}
11412115Sralph 		} while (*cp++ != '\n');
11512115Sralph 		*--cp = '\0';
11612115Sralph 		cp = line;
11712115Sralph 		switch (*cp++) {
11812115Sralph 		case '\1':	/* cleanup because data sent was bad */
119*55474Sbostic 			rcleanup(0);
12012115Sralph 			continue;
12112115Sralph 
12212115Sralph 		case '\2':	/* read cf file */
12312115Sralph 			size = 0;
12412115Sralph 			while (*cp >= '0' && *cp <= '9')
12512115Sralph 				size = size * 10 + (*cp++ - '0');
12612115Sralph 			if (*cp++ != ' ')
12712115Sralph 				break;
12827086Sbloom 			/*
12927086Sbloom 			 * host name has been authenticated, we use our
13027086Sbloom 			 * view of the host name since we may be passed
13127086Sbloom 			 * something different than what gethostbyaddr()
13227086Sbloom 			 * returns
13327086Sbloom 			 */
13427086Sbloom 			strcpy(cp + 6, from);
13512115Sralph 			strcpy(tfname, cp);
13612115Sralph 			tfname[0] = 't';
13716763Sralph 			if (!chksize(size)) {
13816763Sralph 				(void) write(1, "\2", 1);
13916763Sralph 				continue;
14016763Sralph 			}
14112115Sralph 			if (!readfile(tfname, size)) {
142*55474Sbostic 				rcleanup(0);
14312115Sralph 				continue;
14412115Sralph 			}
14512115Sralph 			if (link(tfname, cp) < 0)
14616763Sralph 				frecverr("%s: %m", tfname);
14712115Sralph 			(void) unlink(tfname);
14812115Sralph 			tfname[0] = '\0';
14912115Sralph 			nfiles++;
15012115Sralph 			continue;
15112115Sralph 
15212115Sralph 		case '\3':	/* read df file */
15312115Sralph 			size = 0;
15412115Sralph 			while (*cp >= '0' && *cp <= '9')
15512115Sralph 				size = size * 10 + (*cp++ - '0');
15612115Sralph 			if (*cp++ != ' ')
15712115Sralph 				break;
15816763Sralph 			if (!chksize(size)) {
15916763Sralph 				(void) write(1, "\2", 1);
16016763Sralph 				continue;
16116763Sralph 			}
16239220Sbostic 			(void) strcpy(dfname, cp);
16339220Sbostic 			if (index(dfname, '/'))
16449120Smckusick 				frecverr("readjob: %s: illegal path name",
16549120Smckusick 					dfname);
16629385Smckusick 			(void) readfile(dfname, size);
16712115Sralph 			continue;
16812115Sralph 		}
16916763Sralph 		frecverr("protocol screwup");
17012115Sralph 	}
17112115Sralph }
17212115Sralph 
17312115Sralph /*
17412115Sralph  * Read files send by lpd and copy them to the spooling directory.
17512115Sralph  */
176*55474Sbostic static int
17712115Sralph readfile(file, size)
17812115Sralph 	char *file;
17912115Sralph 	int size;
18012115Sralph {
18112115Sralph 	register char *cp;
18212115Sralph 	char buf[BUFSIZ];
18312115Sralph 	register int i, j, amt;
18412115Sralph 	int fd, err;
18512115Sralph 
18648962Smckusick 	fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
18712115Sralph 	if (fd < 0)
18849120Smckusick 		frecverr("readfile: %s: illegal path name: %m", file);
18912115Sralph 	ack();
19012115Sralph 	err = 0;
19112115Sralph 	for (i = 0; i < size; i += BUFSIZ) {
19212115Sralph 		amt = BUFSIZ;
19312115Sralph 		cp = buf;
19412115Sralph 		if (i + amt > size)
19512115Sralph 			amt = size - i;
19612115Sralph 		do {
19712115Sralph 			j = read(1, cp, amt);
19812115Sralph 			if (j <= 0)
19916763Sralph 				frecverr("Lost connection");
20012115Sralph 			amt -= j;
20112115Sralph 			cp += j;
20212115Sralph 		} while (amt > 0);
20312115Sralph 		amt = BUFSIZ;
20412115Sralph 		if (i + amt > size)
20512115Sralph 			amt = size - i;
20613170Sralph 		if (write(fd, buf, amt) != amt) {
20712115Sralph 			err++;
20813170Sralph 			break;
20913170Sralph 		}
21012115Sralph 	}
21112115Sralph 	(void) close(fd);
21212115Sralph 	if (err)
21316763Sralph 		frecverr("%s: write error", file);
21412115Sralph 	if (noresponse()) {		/* file sent had bad data in it */
21512115Sralph 		(void) unlink(file);
21612115Sralph 		return(0);
21712115Sralph 	}
21812115Sralph 	ack();
21912115Sralph 	return(1);
22012115Sralph }
22112115Sralph 
222*55474Sbostic static int
22312115Sralph noresponse()
22412115Sralph {
22512115Sralph 	char resp;
22612115Sralph 
22712115Sralph 	if (read(1, &resp, 1) != 1)
22816763Sralph 		frecverr("Lost connection");
22912115Sralph 	if (resp == '\0')
23012115Sralph 		return(0);
23112115Sralph 	return(1);
23212115Sralph }
23312115Sralph 
23412115Sralph /*
23516763Sralph  * Check to see if there is enough space on the disk for size bytes.
23616763Sralph  * 1 == OK, 0 == Not OK.
23716763Sralph  */
238*55474Sbostic static int
23916763Sralph chksize(size)
24016763Sralph 	int size;
24116763Sralph {
24216763Sralph 	int spacefree;
24348962Smckusick 	struct statfs sfb;
24416763Sralph 
24548962Smckusick 	if (statfs(".", &sfb) < 0) {
24648962Smckusick 		syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
24748962Smckusick 		return (1);
24848962Smckusick 	}
24952253Sbostic 	spacefree = sfb.f_bavail * (sfb.f_bsize / 512);
25048962Smckusick 	size = (size + 511) / 512;
25116763Sralph 	if (minfree + size > spacefree)
25216763Sralph 		return(0);
25316763Sralph 	return(1);
25416763Sralph }
25516763Sralph 
256*55474Sbostic static int
25716763Sralph read_number(fn)
25816763Sralph 	char *fn;
25916763Sralph {
26016763Sralph 	char lin[80];
26116763Sralph 	register FILE *fp;
26216763Sralph 
26316763Sralph 	if ((fp = fopen(fn, "r")) == NULL)
26416763Sralph 		return (0);
26516763Sralph 	if (fgets(lin, 80, fp) == NULL) {
26616763Sralph 		fclose(fp);
26716763Sralph 		return (0);
26816763Sralph 	}
26916763Sralph 	fclose(fp);
27016763Sralph 	return (atoi(lin));
27116763Sralph }
27216763Sralph 
27316763Sralph /*
27412115Sralph  * Remove all the files associated with the current job being transfered.
27512115Sralph  */
276*55474Sbostic static void
277*55474Sbostic rcleanup(signo)
278*55474Sbostic 	int signo;
27912115Sralph {
28012115Sralph 	if (tfname[0])
28112115Sralph 		(void) unlink(tfname);
28229385Smckusick 	if (dfname[0])
28312115Sralph 		do {
28412115Sralph 			do
28512115Sralph 				(void) unlink(dfname);
28616938Sralph 			while (dfname[2]-- != 'A');
28716938Sralph 			dfname[2] = 'z';
28816938Sralph 		} while (dfname[0]-- != 'd');
28929385Smckusick 	dfname[0] = '\0';
29012115Sralph }
29112115Sralph 
292*55474Sbostic #if __STDC__
293*55474Sbostic #include <stdarg.h>
294*55474Sbostic #else
295*55474Sbostic #include <varargs.h>
296*55474Sbostic #endif
297*55474Sbostic 
298*55474Sbostic static void
299*55474Sbostic #if __STDC__
300*55474Sbostic frecverr(const char *msg, ...)
301*55474Sbostic #else
302*55474Sbostic frecverr(msg, va_alist)
30312115Sralph 	char *msg;
304*55474Sbostic         va_dcl
305*55474Sbostic #endif
30612115Sralph {
307*55474Sbostic 	va_list ap;
308*55474Sbostic #if __STDC__
309*55474Sbostic 	va_start(ap, msg);
310*55474Sbostic #else
311*55474Sbostic 	va_start(ap);
312*55474Sbostic #endif
313*55474Sbostic 	rcleanup(0);
314*55474Sbostic 	vsyslog(LOG_ERR, msg, ap);
315*55474Sbostic 	va_end(ap);
31612115Sralph 	putchar('\1');		/* return error code */
31712115Sralph 	exit(1);
31812115Sralph }
319