122438Sdist /* 256251Selan * Copyright (c) 1983 The Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 556123Selan * 656251Selan * %sccs.include.redist.c% 722438Sdist */ 822438Sdist 913955Ssam #ifndef lint 10*56265Selan static char copyright[] = 1156251Selan "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 1256251Selan All rights reserved.\n"; 1334203Sbostic #endif /* not lint */ 1413955Ssam 1556251Selan #ifndef lint 16*56265Selan static char sccsid[] = "@(#)recvjob.c 5.20 (Berkeley) 09/16/92"; 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 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 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 } 18116763Sralph frecverr("protocol screwup"); 18212115Sralph } 18312115Sralph } 18412115Sralph 18512115Sralph /* 18612115Sralph * Read files send by lpd and copy them to the spooling directory. 18712115Sralph */ 18855474Sbostic static int 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 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 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 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 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__ 31255474Sbostic frecverr(const char *msg, ...) 31355474Sbostic #else 31455474Sbostic frecverr(msg, va_alist) 31512115Sralph char *msg; 31655474Sbostic va_dcl 31755474Sbostic #endif 31812115Sralph { 31955474Sbostic va_list ap; 32055474Sbostic #if __STDC__ 32155474Sbostic va_start(ap, msg); 32255474Sbostic #else 32355474Sbostic va_start(ap); 32455474Sbostic #endif 32555474Sbostic rcleanup(0); 32655474Sbostic vsyslog(LOG_ERR, msg, ap); 32755474Sbostic va_end(ap); 32812115Sralph putchar('\1'); /* return error code */ 32912115Sralph exit(1); 33012115Sralph } 331