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