122438Sdist /* 222438Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 5*56123Selan * Redistribution and use in source and binary forms, with or without 6*56123Selan * modification, are permitted provided that the following conditions 7*56123Selan * are met: 8*56123Selan * 1. Redistributions of source code must retain the above copyright 9*56123Selan * notice, this list of conditions and the following disclaimer. 10*56123Selan * 2. Redistributions in binary form must reproduce the above copyright 11*56123Selan * notice, this list of conditions and the following disclaimer in the 12*56123Selan * documentation and/or other materials provided with the distribution. 13*56123Selan * 3. All advertising materials mentioning features or use of this software 14*56123Selan * must display the following acknowledgement: 15*56123Selan * This product includes software developed by the University of 16*56123Selan * California, Berkeley and its contributors. 17*56123Selan * 4. Neither the name of the University nor the names of its contributors 18*56123Selan * may be used to endorse or promote products derived from this software 19*56123Selan * without specific prior written permission. 20*56123Selan * 21*56123Selan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22*56123Selan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*56123Selan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*56123Selan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25*56123Selan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26*56123Selan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27*56123Selan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*56123Selan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*56123Selan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30*56123Selan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*56123Selan * SUCH DAMAGE. 3222438Sdist */ 3322438Sdist 3413955Ssam #ifndef lint 35*56123Selan static char sccsid[] = "@(#)recvjob.c 5.18 (Berkeley) 8/6/92"; 3634203Sbostic #endif /* not lint */ 3713955Ssam 3812115Sralph /* 3912115Sralph * Receive printer jobs from the network, queue them and 4012115Sralph * start the printer daemon. 4112115Sralph */ 4255474Sbostic #include <sys/param.h> 4355474Sbostic #include <sys/mount.h> 4455474Sbostic #include <sys/stat.h> 4512115Sralph 46*56123Selan #include <unistd.h> 4755474Sbostic #include <signal.h> 4855474Sbostic #include <fcntl.h> 4955474Sbostic #include <dirent.h> 5055474Sbostic #include <syslog.h> 5155474Sbostic #include <stdio.h> 52*56123Selan #include <stdlib.h> 53*56123Selan #include <string.h> 5412115Sralph #include "lp.h" 5555474Sbostic #include "lp.local.h" 5655474Sbostic #include "extern.h" 5737968Sbostic #include "pathnames.h" 5812115Sralph 5916763Sralph #define ack() (void) write(1, sp, 1); 6012115Sralph 61*56123Selan static char dfname[40]; /* data files */ 62*56123Selan static int minfree; /* keep at least minfree blocks available */ 63*56123Selan static char *sp = ""; 64*56123Selan static char tfname[40]; /* tmp copy of cf before linking */ 6516763Sralph 6655474Sbostic static int chksize __P((int)); 6755474Sbostic static void frecverr __P((const char *, ...)); 68*56123Selan static int noresponse __P((void)); 69*56123Selan static void rcleanup __P((int)); 7055474Sbostic static int read_number __P((char *)); 71*56123Selan static int readfile __P((char *, int)); 72*56123Selan static int readjob __P((void)); 7316763Sralph 7455474Sbostic 75*56123Selan void 7612115Sralph recvjob() 7712115Sralph { 7812464Sralph struct stat stb; 7946913Sbostic int status; 8012115Sralph 8112115Sralph /* 8212115Sralph * Perform lookup for printer name or abbreviation 8312115Sralph */ 84*56123Selan if ((status = cgetent(&bp, printcapdb, printer)) == -2) 8516763Sralph frecverr("cannot open printer description file"); 86*56123Selan else if (status == -1) 8716763Sralph frecverr("unknown printer %s", printer); 88*56123Selan else if (status == -3) 89*56123Selan fatal("potential reference loop detected in printcap file"); 90*56123Selan 91*56123Selan if (cgetstr(bp, "lf", &LF) == -1) 9237968Sbostic LF = _PATH_CONSOLE; 93*56123Selan if (cgetstr(bp, "sd", &SD) == -1) 9437968Sbostic SD = _PATH_DEFSPOOL; 95*56123Selan if (cgetstr(bp, "lo", &LO) == -1) 9612464Sralph LO = DEFLOCK; 9712115Sralph 9825498Seric (void) close(2); /* set up log file */ 9925498Seric if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { 10025498Seric syslog(LOG_ERR, "%s: %m", LF); 10137968Sbostic (void) open(_PATH_DEVNULL, O_WRONLY); 10225498Seric } 10325498Seric 10412115Sralph if (chdir(SD) < 0) 10516763Sralph frecverr("%s: %s: %m", printer, SD); 10616763Sralph if (stat(LO, &stb) == 0) { 10716763Sralph if (stb.st_mode & 010) { 10816763Sralph /* queue is disabled */ 10916763Sralph putchar('\1'); /* return error code */ 11016763Sralph exit(1); 11116763Sralph } 11216763Sralph } else if (stat(SD, &stb) < 0) 11316763Sralph frecverr("%s: %s: %m", printer, SD); 11448962Smckusick minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */ 11516763Sralph signal(SIGTERM, rcleanup); 11616763Sralph signal(SIGPIPE, rcleanup); 11712115Sralph 11812115Sralph if (readjob()) 11912115Sralph printjob(); 12012115Sralph } 12112115Sralph 12212115Sralph /* 12312115Sralph * Read printer jobs sent by lpd and copy them to the spooling directory. 12412115Sralph * Return the number of jobs successfully transfered. 12512115Sralph */ 12655474Sbostic static int 12716763Sralph readjob() 12812115Sralph { 12912115Sralph register int size, nfiles; 13012115Sralph register char *cp; 13112115Sralph 13212115Sralph ack(); 13312115Sralph nfiles = 0; 13412115Sralph for (;;) { 13512115Sralph /* 13612115Sralph * Read a command to tell us what to do 13712115Sralph */ 13812115Sralph cp = line; 13912115Sralph do { 14012115Sralph if ((size = read(1, cp, 1)) != 1) { 14112115Sralph if (size < 0) 14216763Sralph frecverr("%s: Lost connection",printer); 14312115Sralph return(nfiles); 14412115Sralph } 14512115Sralph } while (*cp++ != '\n'); 14612115Sralph *--cp = '\0'; 14712115Sralph cp = line; 14812115Sralph switch (*cp++) { 14912115Sralph case '\1': /* cleanup because data sent was bad */ 15055474Sbostic rcleanup(0); 15112115Sralph continue; 15212115Sralph 15312115Sralph case '\2': /* read cf file */ 15412115Sralph size = 0; 15512115Sralph while (*cp >= '0' && *cp <= '9') 15612115Sralph size = size * 10 + (*cp++ - '0'); 15712115Sralph if (*cp++ != ' ') 15812115Sralph break; 15927086Sbloom /* 16027086Sbloom * host name has been authenticated, we use our 16127086Sbloom * view of the host name since we may be passed 16227086Sbloom * something different than what gethostbyaddr() 16327086Sbloom * returns 16427086Sbloom */ 16527086Sbloom strcpy(cp + 6, from); 16612115Sralph strcpy(tfname, cp); 16712115Sralph tfname[0] = 't'; 16816763Sralph if (!chksize(size)) { 16916763Sralph (void) write(1, "\2", 1); 17016763Sralph continue; 17116763Sralph } 17212115Sralph if (!readfile(tfname, size)) { 17355474Sbostic rcleanup(0); 17412115Sralph continue; 17512115Sralph } 17612115Sralph if (link(tfname, cp) < 0) 17716763Sralph frecverr("%s: %m", tfname); 17812115Sralph (void) unlink(tfname); 17912115Sralph tfname[0] = '\0'; 18012115Sralph nfiles++; 18112115Sralph continue; 18212115Sralph 18312115Sralph case '\3': /* read df file */ 18412115Sralph size = 0; 18512115Sralph while (*cp >= '0' && *cp <= '9') 18612115Sralph size = size * 10 + (*cp++ - '0'); 18712115Sralph if (*cp++ != ' ') 18812115Sralph break; 18916763Sralph if (!chksize(size)) { 19016763Sralph (void) write(1, "\2", 1); 19116763Sralph continue; 19216763Sralph } 19339220Sbostic (void) strcpy(dfname, cp); 19439220Sbostic if (index(dfname, '/')) 19549120Smckusick frecverr("readjob: %s: illegal path name", 19649120Smckusick dfname); 19729385Smckusick (void) readfile(dfname, size); 19812115Sralph continue; 19912115Sralph } 20016763Sralph frecverr("protocol screwup"); 20112115Sralph } 20212115Sralph } 20312115Sralph 20412115Sralph /* 20512115Sralph * Read files send by lpd and copy them to the spooling directory. 20612115Sralph */ 20755474Sbostic static int 20812115Sralph readfile(file, size) 20912115Sralph char *file; 21012115Sralph int size; 21112115Sralph { 21212115Sralph register char *cp; 21312115Sralph char buf[BUFSIZ]; 21412115Sralph register int i, j, amt; 21512115Sralph int fd, err; 21612115Sralph 21748962Smckusick fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD); 21812115Sralph if (fd < 0) 21949120Smckusick frecverr("readfile: %s: illegal path name: %m", file); 22012115Sralph ack(); 22112115Sralph err = 0; 22212115Sralph for (i = 0; i < size; i += BUFSIZ) { 22312115Sralph amt = BUFSIZ; 22412115Sralph cp = buf; 22512115Sralph if (i + amt > size) 22612115Sralph amt = size - i; 22712115Sralph do { 22812115Sralph j = read(1, cp, amt); 22912115Sralph if (j <= 0) 23016763Sralph frecverr("Lost connection"); 23112115Sralph amt -= j; 23212115Sralph cp += j; 23312115Sralph } while (amt > 0); 23412115Sralph amt = BUFSIZ; 23512115Sralph if (i + amt > size) 23612115Sralph amt = size - i; 23713170Sralph if (write(fd, buf, amt) != amt) { 23812115Sralph err++; 23913170Sralph break; 24013170Sralph } 24112115Sralph } 24212115Sralph (void) close(fd); 24312115Sralph if (err) 24416763Sralph frecverr("%s: write error", file); 24512115Sralph if (noresponse()) { /* file sent had bad data in it */ 24612115Sralph (void) unlink(file); 24712115Sralph return(0); 24812115Sralph } 24912115Sralph ack(); 25012115Sralph return(1); 25112115Sralph } 25212115Sralph 25355474Sbostic static int 25412115Sralph noresponse() 25512115Sralph { 25612115Sralph char resp; 25712115Sralph 25812115Sralph if (read(1, &resp, 1) != 1) 25916763Sralph frecverr("Lost connection"); 26012115Sralph if (resp == '\0') 26112115Sralph return(0); 26212115Sralph return(1); 26312115Sralph } 26412115Sralph 26512115Sralph /* 26616763Sralph * Check to see if there is enough space on the disk for size bytes. 26716763Sralph * 1 == OK, 0 == Not OK. 26816763Sralph */ 26955474Sbostic static int 27016763Sralph chksize(size) 27116763Sralph int size; 27216763Sralph { 27316763Sralph int spacefree; 27448962Smckusick struct statfs sfb; 27516763Sralph 27648962Smckusick if (statfs(".", &sfb) < 0) { 27748962Smckusick syslog(LOG_ERR, "%s: %m", "statfs(\".\")"); 27848962Smckusick return (1); 27948962Smckusick } 28052253Sbostic spacefree = sfb.f_bavail * (sfb.f_bsize / 512); 28148962Smckusick size = (size + 511) / 512; 28216763Sralph if (minfree + size > spacefree) 28316763Sralph return(0); 28416763Sralph return(1); 28516763Sralph } 28616763Sralph 28755474Sbostic static int 28816763Sralph read_number(fn) 28916763Sralph char *fn; 29016763Sralph { 29116763Sralph char lin[80]; 29216763Sralph register FILE *fp; 29316763Sralph 29416763Sralph if ((fp = fopen(fn, "r")) == NULL) 29516763Sralph return (0); 29616763Sralph if (fgets(lin, 80, fp) == NULL) { 29716763Sralph fclose(fp); 29816763Sralph return (0); 29916763Sralph } 30016763Sralph fclose(fp); 30116763Sralph return (atoi(lin)); 30216763Sralph } 30316763Sralph 30416763Sralph /* 30512115Sralph * Remove all the files associated with the current job being transfered. 30612115Sralph */ 30755474Sbostic static void 30855474Sbostic rcleanup(signo) 30955474Sbostic int signo; 31012115Sralph { 31112115Sralph if (tfname[0]) 31212115Sralph (void) unlink(tfname); 31329385Smckusick if (dfname[0]) 31412115Sralph do { 31512115Sralph do 31612115Sralph (void) unlink(dfname); 31716938Sralph while (dfname[2]-- != 'A'); 31816938Sralph dfname[2] = 'z'; 31916938Sralph } while (dfname[0]-- != 'd'); 32029385Smckusick dfname[0] = '\0'; 32112115Sralph } 32212115Sralph 32355474Sbostic #if __STDC__ 32455474Sbostic #include <stdarg.h> 32555474Sbostic #else 32655474Sbostic #include <varargs.h> 32755474Sbostic #endif 32855474Sbostic 32955474Sbostic static void 33055474Sbostic #if __STDC__ 33155474Sbostic frecverr(const char *msg, ...) 33255474Sbostic #else 33355474Sbostic frecverr(msg, va_alist) 33412115Sralph char *msg; 33555474Sbostic va_dcl 33655474Sbostic #endif 33712115Sralph { 33855474Sbostic va_list ap; 33955474Sbostic #if __STDC__ 34055474Sbostic va_start(ap, msg); 34155474Sbostic #else 34255474Sbostic va_start(ap); 34355474Sbostic #endif 34455474Sbostic rcleanup(0); 34555474Sbostic vsyslog(LOG_ERR, msg, ap); 34655474Sbostic va_end(ap); 34712115Sralph putchar('\1'); /* return error code */ 34812115Sralph exit(1); 34912115Sralph } 350