xref: /csrg-svn/usr.sbin/lpr/lpd/recvjob.c (revision 68972)
122438Sdist /*
261845Sbostic  * Copyright (c) 1983, 1993
361845Sbostic  *	The Regents of the University of California.  All rights reserved.
434203Sbostic  *
556123Selan  *
656251Selan  * %sccs.include.redist.c%
722438Sdist  */
822438Sdist 
913955Ssam #ifndef lint
1056265Selan static char copyright[] =
1161845Sbostic "@(#) Copyright (c) 1983, 1993\n\
1261845Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1334203Sbostic #endif /* not lint */
1413955Ssam 
1556251Selan #ifndef lint
16*68972Stef static char sccsid[] = "@(#)recvjob.c	8.2 (Berkeley) 04/27/95";
1756251Selan #endif /* not lint */
1856251Selan 
1912115Sralph /*
2012115Sralph  * Receive printer jobs from the network, queue them and
2112115Sralph  * start the printer daemon.
2212115Sralph  */
2355474Sbostic #include <sys/param.h>
2455474Sbostic #include <sys/mount.h>
2555474Sbostic #include <sys/stat.h>
2612115Sralph 
2756123Selan #include <unistd.h>
2855474Sbostic #include <signal.h>
2955474Sbostic #include <fcntl.h>
3055474Sbostic #include <dirent.h>
3155474Sbostic #include <syslog.h>
3255474Sbostic #include <stdio.h>
3356123Selan #include <stdlib.h>
3456123Selan #include <string.h>
3512115Sralph #include "lp.h"
3655474Sbostic #include "lp.local.h"
3755474Sbostic #include "extern.h"
3837968Sbostic #include "pathnames.h"
3912115Sralph 
4016763Sralph #define ack()	(void) write(1, sp, 1);
4112115Sralph 
4256123Selan static char	 dfname[40];	/* data files */
4356123Selan static int	 minfree;       /* keep at least minfree blocks available */
4456123Selan static char	*sp = "";
4556123Selan static char	 tfname[40];	/* tmp copy of cf before linking */
4616763Sralph 
4755474Sbostic static int        chksize __P((int));
4855474Sbostic static void       frecverr __P((const char *, ...));
4956123Selan static int        noresponse __P((void));
5056123Selan static void       rcleanup __P((int));
5155474Sbostic static int        read_number __P((char *));
5256123Selan static int        readfile __P((char *, int));
5356123Selan static int        readjob __P((void));
5416763Sralph 
5555474Sbostic 
5656123Selan void
recvjob()5712115Sralph recvjob()
5812115Sralph {
5912464Sralph 	struct stat stb;
6046913Sbostic 	int status;
6112115Sralph 
6212115Sralph 	/*
6312115Sralph 	 * Perform lookup for printer name or abbreviation
6412115Sralph 	 */
6556123Selan 	if ((status = cgetent(&bp, printcapdb, printer)) == -2)
6616763Sralph 		frecverr("cannot open printer description file");
6756123Selan 	else if (status == -1)
6816763Sralph 		frecverr("unknown printer %s", printer);
6956123Selan 	else if (status == -3)
7056123Selan 		fatal("potential reference loop detected in printcap file");
7156123Selan 
7256123Selan 	if (cgetstr(bp, "lf", &LF) == -1)
7337968Sbostic 		LF = _PATH_CONSOLE;
7456123Selan 	if (cgetstr(bp, "sd", &SD) == -1)
7537968Sbostic 		SD = _PATH_DEFSPOOL;
7656123Selan 	if (cgetstr(bp, "lo", &LO) == -1)
7712464Sralph 		LO = DEFLOCK;
7812115Sralph 
7925498Seric 	(void) close(2);			/* set up log file */
8025498Seric 	if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
8125498Seric 		syslog(LOG_ERR, "%s: %m", LF);
8237968Sbostic 		(void) open(_PATH_DEVNULL, O_WRONLY);
8325498Seric 	}
8425498Seric 
8512115Sralph 	if (chdir(SD) < 0)
8616763Sralph 		frecverr("%s: %s: %m", printer, SD);
8716763Sralph 	if (stat(LO, &stb) == 0) {
8816763Sralph 		if (stb.st_mode & 010) {
8916763Sralph 			/* queue is disabled */
9016763Sralph 			putchar('\1');		/* return error code */
9116763Sralph 			exit(1);
9216763Sralph 		}
9316763Sralph 	} else if (stat(SD, &stb) < 0)
9416763Sralph 		frecverr("%s: %s: %m", printer, SD);
9548962Smckusick 	minfree = 2 * read_number("minfree");	/* scale KB to 512 blocks */
9616763Sralph 	signal(SIGTERM, rcleanup);
9716763Sralph 	signal(SIGPIPE, rcleanup);
9812115Sralph 
9912115Sralph 	if (readjob())
10012115Sralph 		printjob();
10112115Sralph }
10212115Sralph 
10312115Sralph /*
10412115Sralph  * Read printer jobs sent by lpd and copy them to the spooling directory.
10512115Sralph  * Return the number of jobs successfully transfered.
10612115Sralph  */
10755474Sbostic static int
readjob()10816763Sralph readjob()
10912115Sralph {
11012115Sralph 	register int size, nfiles;
11112115Sralph 	register char *cp;
11212115Sralph 
11312115Sralph 	ack();
11412115Sralph 	nfiles = 0;
11512115Sralph 	for (;;) {
11612115Sralph 		/*
11712115Sralph 		 * Read a command to tell us what to do
11812115Sralph 		 */
11912115Sralph 		cp = line;
12012115Sralph 		do {
12112115Sralph 			if ((size = read(1, cp, 1)) != 1) {
12212115Sralph 				if (size < 0)
12316763Sralph 					frecverr("%s: Lost connection",printer);
12412115Sralph 				return(nfiles);
12512115Sralph 			}
12612115Sralph 		} while (*cp++ != '\n');
12712115Sralph 		*--cp = '\0';
12812115Sralph 		cp = line;
12912115Sralph 		switch (*cp++) {
13012115Sralph 		case '\1':	/* cleanup because data sent was bad */
13155474Sbostic 			rcleanup(0);
13212115Sralph 			continue;
13312115Sralph 
13412115Sralph 		case '\2':	/* read cf file */
13512115Sralph 			size = 0;
13612115Sralph 			while (*cp >= '0' && *cp <= '9')
13712115Sralph 				size = size * 10 + (*cp++ - '0');
13812115Sralph 			if (*cp++ != ' ')
13912115Sralph 				break;
14027086Sbloom 			/*
14127086Sbloom 			 * host name has been authenticated, we use our
14227086Sbloom 			 * view of the host name since we may be passed
14327086Sbloom 			 * something different than what gethostbyaddr()
14427086Sbloom 			 * returns
14527086Sbloom 			 */
14627086Sbloom 			strcpy(cp + 6, from);
14712115Sralph 			strcpy(tfname, cp);
14812115Sralph 			tfname[0] = 't';
14916763Sralph 			if (!chksize(size)) {
15016763Sralph 				(void) write(1, "\2", 1);
15116763Sralph 				continue;
15216763Sralph 			}
15312115Sralph 			if (!readfile(tfname, size)) {
15455474Sbostic 				rcleanup(0);
15512115Sralph 				continue;
15612115Sralph 			}
15712115Sralph 			if (link(tfname, cp) < 0)
15816763Sralph 				frecverr("%s: %m", tfname);
15912115Sralph 			(void) unlink(tfname);
16012115Sralph 			tfname[0] = '\0';
16112115Sralph 			nfiles++;
16212115Sralph 			continue;
16312115Sralph 
16412115Sralph 		case '\3':	/* read df file */
16512115Sralph 			size = 0;
16612115Sralph 			while (*cp >= '0' && *cp <= '9')
16712115Sralph 				size = size * 10 + (*cp++ - '0');
16812115Sralph 			if (*cp++ != ' ')
16912115Sralph 				break;
17016763Sralph 			if (!chksize(size)) {
17116763Sralph 				(void) write(1, "\2", 1);
17216763Sralph 				continue;
17316763Sralph 			}
17439220Sbostic 			(void) strcpy(dfname, cp);
17539220Sbostic 			if (index(dfname, '/'))
17649120Smckusick 				frecverr("readjob: %s: illegal path name",
17749120Smckusick 					dfname);
17829385Smckusick 			(void) readfile(dfname, size);
17912115Sralph 			continue;
18012115Sralph 		}
18156924Sbostic 		frecverr("protocol screwup: %s", line);
18212115Sralph 	}
18312115Sralph }
18412115Sralph 
18512115Sralph /*
18612115Sralph  * Read files send by lpd and copy them to the spooling directory.
18712115Sralph  */
18855474Sbostic static int
readfile(file,size)18912115Sralph readfile(file, size)
19012115Sralph 	char *file;
19112115Sralph 	int size;
19212115Sralph {
19312115Sralph 	register char *cp;
19412115Sralph 	char buf[BUFSIZ];
19512115Sralph 	register int i, j, amt;
19612115Sralph 	int fd, err;
19712115Sralph 
19848962Smckusick 	fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
19912115Sralph 	if (fd < 0)
20049120Smckusick 		frecverr("readfile: %s: illegal path name: %m", file);
20112115Sralph 	ack();
20212115Sralph 	err = 0;
20312115Sralph 	for (i = 0; i < size; i += BUFSIZ) {
20412115Sralph 		amt = BUFSIZ;
20512115Sralph 		cp = buf;
20612115Sralph 		if (i + amt > size)
20712115Sralph 			amt = size - i;
20812115Sralph 		do {
20912115Sralph 			j = read(1, cp, amt);
21012115Sralph 			if (j <= 0)
21116763Sralph 				frecverr("Lost connection");
21212115Sralph 			amt -= j;
21312115Sralph 			cp += j;
21412115Sralph 		} while (amt > 0);
21512115Sralph 		amt = BUFSIZ;
21612115Sralph 		if (i + amt > size)
21712115Sralph 			amt = size - i;
21813170Sralph 		if (write(fd, buf, amt) != amt) {
21912115Sralph 			err++;
22013170Sralph 			break;
22113170Sralph 		}
22212115Sralph 	}
22312115Sralph 	(void) close(fd);
22412115Sralph 	if (err)
22516763Sralph 		frecverr("%s: write error", file);
22612115Sralph 	if (noresponse()) {		/* file sent had bad data in it */
22712115Sralph 		(void) unlink(file);
22812115Sralph 		return(0);
22912115Sralph 	}
23012115Sralph 	ack();
23112115Sralph 	return(1);
23212115Sralph }
23312115Sralph 
23455474Sbostic static int
noresponse()23512115Sralph noresponse()
23612115Sralph {
23712115Sralph 	char resp;
23812115Sralph 
23912115Sralph 	if (read(1, &resp, 1) != 1)
24016763Sralph 		frecverr("Lost connection");
24112115Sralph 	if (resp == '\0')
24212115Sralph 		return(0);
24312115Sralph 	return(1);
24412115Sralph }
24512115Sralph 
24612115Sralph /*
24716763Sralph  * Check to see if there is enough space on the disk for size bytes.
24816763Sralph  * 1 == OK, 0 == Not OK.
24916763Sralph  */
25055474Sbostic static int
chksize(size)25116763Sralph chksize(size)
25216763Sralph 	int size;
25316763Sralph {
25416763Sralph 	int spacefree;
25548962Smckusick 	struct statfs sfb;
25616763Sralph 
25748962Smckusick 	if (statfs(".", &sfb) < 0) {
25848962Smckusick 		syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
25948962Smckusick 		return (1);
26048962Smckusick 	}
26152253Sbostic 	spacefree = sfb.f_bavail * (sfb.f_bsize / 512);
26248962Smckusick 	size = (size + 511) / 512;
26316763Sralph 	if (minfree + size > spacefree)
26416763Sralph 		return(0);
26516763Sralph 	return(1);
26616763Sralph }
26716763Sralph 
26855474Sbostic static int
read_number(fn)26916763Sralph read_number(fn)
27016763Sralph 	char *fn;
27116763Sralph {
27216763Sralph 	char lin[80];
27316763Sralph 	register FILE *fp;
27416763Sralph 
27516763Sralph 	if ((fp = fopen(fn, "r")) == NULL)
27616763Sralph 		return (0);
27716763Sralph 	if (fgets(lin, 80, fp) == NULL) {
27816763Sralph 		fclose(fp);
27916763Sralph 		return (0);
28016763Sralph 	}
28116763Sralph 	fclose(fp);
28216763Sralph 	return (atoi(lin));
28316763Sralph }
28416763Sralph 
28516763Sralph /*
28612115Sralph  * Remove all the files associated with the current job being transfered.
28712115Sralph  */
28855474Sbostic static void
rcleanup(signo)28955474Sbostic rcleanup(signo)
29055474Sbostic 	int signo;
29112115Sralph {
29212115Sralph 	if (tfname[0])
29312115Sralph 		(void) unlink(tfname);
29429385Smckusick 	if (dfname[0])
29512115Sralph 		do {
29612115Sralph 			do
29712115Sralph 				(void) unlink(dfname);
29816938Sralph 			while (dfname[2]-- != 'A');
29916938Sralph 			dfname[2] = 'z';
30016938Sralph 		} while (dfname[0]-- != 'd');
30129385Smckusick 	dfname[0] = '\0';
30212115Sralph }
30312115Sralph 
30455474Sbostic #if __STDC__
30555474Sbostic #include <stdarg.h>
30655474Sbostic #else
30755474Sbostic #include <varargs.h>
30855474Sbostic #endif
30955474Sbostic 
31055474Sbostic static void
31155474Sbostic #if __STDC__
frecverr(const char * msg,...)31255474Sbostic frecverr(const char *msg, ...)
31355474Sbostic #else
31455474Sbostic frecverr(msg, va_alist)
31512115Sralph 	char *msg;
31655474Sbostic         va_dcl
31755474Sbostic #endif
31812115Sralph {
319*68972Stef 	extern char fromb[];
32055474Sbostic 	va_list ap;
32155474Sbostic #if __STDC__
32255474Sbostic 	va_start(ap, msg);
32355474Sbostic #else
32455474Sbostic 	va_start(ap);
32555474Sbostic #endif
32655474Sbostic 	rcleanup(0);
32756924Sbostic 	syslog(LOG_ERR, "%s", fromb);
32855474Sbostic 	vsyslog(LOG_ERR, msg, ap);
32955474Sbostic 	va_end(ap);
33012115Sralph 	putchar('\1');		/* return error code */
33112115Sralph 	exit(1);
33212115Sralph }
333