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