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*49120Smckusick static char sccsid[] = "@(#)recvjob.c 5.15 (Berkeley) 05/04/91"; 1034203Sbostic #endif /* not lint */ 1113955Ssam 1212115Sralph /* 1312115Sralph * Receive printer jobs from the network, queue them and 1412115Sralph * start the printer daemon. 1512115Sralph */ 1612115Sralph 1712115Sralph #include "lp.h" 1837968Sbostic #include "pathnames.h" 1948962Smckusick #include <sys/mount.h> 2012115Sralph 2116763Sralph char *sp = ""; 2216763Sralph #define ack() (void) write(1, sp, 1); 2312115Sralph 2416763Sralph char tfname[40]; /* tmp copy of cf before linking */ 2529385Smckusick char dfname[40]; /* data files */ 2616763Sralph int minfree; /* keep at least minfree blocks available */ 2716763Sralph 2846913Sbostic void rcleanup(); 2916763Sralph 3012115Sralph recvjob() 3112115Sralph { 3212464Sralph struct stat stb; 3312115Sralph char *bp = pbuf; 3446913Sbostic int status; 3512115Sralph 3612115Sralph /* 3712115Sralph * Perform lookup for printer name or abbreviation 3812115Sralph */ 3912115Sralph if ((status = pgetent(line, printer)) < 0) 4016763Sralph frecverr("cannot open printer description file"); 4112115Sralph else if (status == 0) 4216763Sralph frecverr("unknown printer %s", printer); 4312115Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 4437968Sbostic LF = _PATH_CONSOLE; 4512115Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 4637968Sbostic SD = _PATH_DEFSPOOL; 4712464Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 4812464Sralph LO = DEFLOCK; 4912115Sralph 5025498Seric (void) close(2); /* set up log file */ 5125498Seric if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { 5225498Seric syslog(LOG_ERR, "%s: %m", LF); 5337968Sbostic (void) open(_PATH_DEVNULL, O_WRONLY); 5425498Seric } 5525498Seric 5612115Sralph if (chdir(SD) < 0) 5716763Sralph frecverr("%s: %s: %m", printer, SD); 5816763Sralph if (stat(LO, &stb) == 0) { 5916763Sralph if (stb.st_mode & 010) { 6016763Sralph /* queue is disabled */ 6116763Sralph putchar('\1'); /* return error code */ 6216763Sralph exit(1); 6316763Sralph } 6416763Sralph } else if (stat(SD, &stb) < 0) 6516763Sralph frecverr("%s: %s: %m", printer, SD); 6648962Smckusick minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */ 6716763Sralph signal(SIGTERM, rcleanup); 6816763Sralph signal(SIGPIPE, rcleanup); 6912115Sralph 7012115Sralph if (readjob()) 7112115Sralph printjob(); 7212115Sralph } 7312115Sralph 7412115Sralph /* 7512115Sralph * Read printer jobs sent by lpd and copy them to the spooling directory. 7612115Sralph * Return the number of jobs successfully transfered. 7712115Sralph */ 7816763Sralph readjob() 7912115Sralph { 8012115Sralph register int size, nfiles; 8112115Sralph register char *cp; 8212115Sralph 8312115Sralph ack(); 8412115Sralph nfiles = 0; 8512115Sralph for (;;) { 8612115Sralph /* 8712115Sralph * Read a command to tell us what to do 8812115Sralph */ 8912115Sralph cp = line; 9012115Sralph do { 9112115Sralph if ((size = read(1, cp, 1)) != 1) { 9212115Sralph if (size < 0) 9316763Sralph frecverr("%s: Lost connection",printer); 9412115Sralph return(nfiles); 9512115Sralph } 9612115Sralph } while (*cp++ != '\n'); 9712115Sralph *--cp = '\0'; 9812115Sralph cp = line; 9912115Sralph switch (*cp++) { 10012115Sralph case '\1': /* cleanup because data sent was bad */ 10116763Sralph rcleanup(); 10212115Sralph continue; 10312115Sralph 10412115Sralph case '\2': /* read cf file */ 10512115Sralph size = 0; 10612115Sralph while (*cp >= '0' && *cp <= '9') 10712115Sralph size = size * 10 + (*cp++ - '0'); 10812115Sralph if (*cp++ != ' ') 10912115Sralph break; 11027086Sbloom /* 11127086Sbloom * host name has been authenticated, we use our 11227086Sbloom * view of the host name since we may be passed 11327086Sbloom * something different than what gethostbyaddr() 11427086Sbloom * returns 11527086Sbloom */ 11627086Sbloom strcpy(cp + 6, from); 11712115Sralph strcpy(tfname, cp); 11812115Sralph tfname[0] = 't'; 11916763Sralph if (!chksize(size)) { 12016763Sralph (void) write(1, "\2", 1); 12116763Sralph continue; 12216763Sralph } 12312115Sralph if (!readfile(tfname, size)) { 12416763Sralph rcleanup(); 12512115Sralph continue; 12612115Sralph } 12712115Sralph if (link(tfname, cp) < 0) 12816763Sralph frecverr("%s: %m", tfname); 12912115Sralph (void) unlink(tfname); 13012115Sralph tfname[0] = '\0'; 13112115Sralph nfiles++; 13212115Sralph continue; 13312115Sralph 13412115Sralph case '\3': /* read df file */ 13512115Sralph size = 0; 13612115Sralph while (*cp >= '0' && *cp <= '9') 13712115Sralph size = size * 10 + (*cp++ - '0'); 13812115Sralph if (*cp++ != ' ') 13912115Sralph break; 14016763Sralph if (!chksize(size)) { 14116763Sralph (void) write(1, "\2", 1); 14216763Sralph continue; 14316763Sralph } 14439220Sbostic (void) strcpy(dfname, cp); 14539220Sbostic if (index(dfname, '/')) 146*49120Smckusick frecverr("readjob: %s: illegal path name", 147*49120Smckusick dfname); 14829385Smckusick (void) readfile(dfname, size); 14912115Sralph continue; 15012115Sralph } 15116763Sralph frecverr("protocol screwup"); 15212115Sralph } 15312115Sralph } 15412115Sralph 15512115Sralph /* 15612115Sralph * Read files send by lpd and copy them to the spooling directory. 15712115Sralph */ 15812115Sralph readfile(file, size) 15912115Sralph char *file; 16012115Sralph int size; 16112115Sralph { 16212115Sralph register char *cp; 16312115Sralph char buf[BUFSIZ]; 16412115Sralph register int i, j, amt; 16512115Sralph int fd, err; 16612115Sralph 16748962Smckusick fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD); 16812115Sralph if (fd < 0) 169*49120Smckusick frecverr("readfile: %s: illegal path name: %m", file); 17012115Sralph ack(); 17112115Sralph err = 0; 17212115Sralph for (i = 0; i < size; i += BUFSIZ) { 17312115Sralph amt = BUFSIZ; 17412115Sralph cp = buf; 17512115Sralph if (i + amt > size) 17612115Sralph amt = size - i; 17712115Sralph do { 17812115Sralph j = read(1, cp, amt); 17912115Sralph if (j <= 0) 18016763Sralph frecverr("Lost connection"); 18112115Sralph amt -= j; 18212115Sralph cp += j; 18312115Sralph } while (amt > 0); 18412115Sralph amt = BUFSIZ; 18512115Sralph if (i + amt > size) 18612115Sralph amt = size - i; 18713170Sralph if (write(fd, buf, amt) != amt) { 18812115Sralph err++; 18913170Sralph break; 19013170Sralph } 19112115Sralph } 19212115Sralph (void) close(fd); 19312115Sralph if (err) 19416763Sralph frecverr("%s: write error", file); 19512115Sralph if (noresponse()) { /* file sent had bad data in it */ 19612115Sralph (void) unlink(file); 19712115Sralph return(0); 19812115Sralph } 19912115Sralph ack(); 20012115Sralph return(1); 20112115Sralph } 20212115Sralph 20312115Sralph noresponse() 20412115Sralph { 20512115Sralph char resp; 20612115Sralph 20712115Sralph if (read(1, &resp, 1) != 1) 20816763Sralph frecverr("Lost connection"); 20912115Sralph if (resp == '\0') 21012115Sralph return(0); 21112115Sralph return(1); 21212115Sralph } 21312115Sralph 21412115Sralph /* 21516763Sralph * Check to see if there is enough space on the disk for size bytes. 21616763Sralph * 1 == OK, 0 == Not OK. 21716763Sralph */ 21816763Sralph chksize(size) 21916763Sralph int size; 22016763Sralph { 22116763Sralph int spacefree; 22248962Smckusick struct statfs sfb; 22316763Sralph 22448962Smckusick if (statfs(".", &sfb) < 0) { 22548962Smckusick syslog(LOG_ERR, "%s: %m", "statfs(\".\")"); 22648962Smckusick return (1); 22748962Smckusick } 22848962Smckusick spacefree = sfb.f_bavail * (sfb.f_fsize / 512); 22948962Smckusick size = (size + 511) / 512; 23016763Sralph if (minfree + size > spacefree) 23116763Sralph return(0); 23216763Sralph return(1); 23316763Sralph } 23416763Sralph 23516763Sralph read_number(fn) 23616763Sralph char *fn; 23716763Sralph { 23816763Sralph char lin[80]; 23916763Sralph register FILE *fp; 24016763Sralph 24116763Sralph if ((fp = fopen(fn, "r")) == NULL) 24216763Sralph return (0); 24316763Sralph if (fgets(lin, 80, fp) == NULL) { 24416763Sralph fclose(fp); 24516763Sralph return (0); 24616763Sralph } 24716763Sralph fclose(fp); 24816763Sralph return (atoi(lin)); 24916763Sralph } 25016763Sralph 25116763Sralph /* 25212115Sralph * Remove all the files associated with the current job being transfered. 25312115Sralph */ 25446913Sbostic void 25516763Sralph rcleanup() 25612115Sralph { 25712115Sralph 25812115Sralph if (tfname[0]) 25912115Sralph (void) unlink(tfname); 26029385Smckusick if (dfname[0]) 26112115Sralph do { 26212115Sralph do 26312115Sralph (void) unlink(dfname); 26416938Sralph while (dfname[2]-- != 'A'); 26516938Sralph dfname[2] = 'z'; 26616938Sralph } while (dfname[0]-- != 'd'); 26729385Smckusick dfname[0] = '\0'; 26812115Sralph } 26912115Sralph 27016763Sralph frecverr(msg, a1, a2) 27112115Sralph char *msg; 27212115Sralph { 27316763Sralph rcleanup(); 27416763Sralph syslog(LOG_ERR, msg, a1, a2); 27512115Sralph putchar('\1'); /* return error code */ 27612115Sralph exit(1); 27712115Sralph } 278