122438Sdist /* 222438Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 534203Sbostic * Redistribution and use in source and binary forms are permitted 634936Sbostic * provided that the above copyright notice and this paragraph are 734936Sbostic * duplicated in all such forms and that any documentation, 834936Sbostic * advertising materials, and other materials related to such 934936Sbostic * distribution and use acknowledge that the software was developed 1034936Sbostic * by the University of California, Berkeley. The name of the 1134936Sbostic * University may not be used to endorse or promote products derived 1234936Sbostic * from this software without specific prior written permission. 1334936Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434936Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534936Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622438Sdist */ 1722438Sdist 1813955Ssam #ifndef lint 19*38493Skarels static char sccsid[] = "@(#)recvjob.c 5.9 (Berkeley) 07/28/89"; 2034203Sbostic #endif /* not lint */ 2113955Ssam 2212115Sralph /* 2312115Sralph * Receive printer jobs from the network, queue them and 2412115Sralph * start the printer daemon. 2512115Sralph */ 2612115Sralph 2712115Sralph #include "lp.h" 28*38493Skarels #include <ufs/fs.h> 2937968Sbostic #include "pathnames.h" 3012115Sralph 3116763Sralph char *sp = ""; 3216763Sralph #define ack() (void) write(1, sp, 1); 3312115Sralph 3416763Sralph char tfname[40]; /* tmp copy of cf before linking */ 3529385Smckusick char dfname[40]; /* data files */ 3616763Sralph int minfree; /* keep at least minfree blocks available */ 3716763Sralph char *ddev; /* disk device (for checking free space) */ 3816763Sralph int dfd; /* file system device descriptor */ 3916763Sralph 4016763Sralph char *find_dev(); 4116763Sralph 4212115Sralph recvjob() 4312115Sralph { 4412464Sralph struct stat stb; 4512115Sralph char *bp = pbuf; 4616763Sralph int status, rcleanup(); 4712115Sralph 4812115Sralph /* 4912115Sralph * Perform lookup for printer name or abbreviation 5012115Sralph */ 5112115Sralph if ((status = pgetent(line, printer)) < 0) 5216763Sralph frecverr("cannot open printer description file"); 5312115Sralph else if (status == 0) 5416763Sralph frecverr("unknown printer %s", printer); 5512115Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 5637968Sbostic LF = _PATH_CONSOLE; 5712115Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 5837968Sbostic SD = _PATH_DEFSPOOL; 5912464Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 6012464Sralph LO = DEFLOCK; 6112115Sralph 6225498Seric (void) close(2); /* set up log file */ 6325498Seric if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { 6425498Seric syslog(LOG_ERR, "%s: %m", LF); 6537968Sbostic (void) open(_PATH_DEVNULL, O_WRONLY); 6625498Seric } 6725498Seric 6812115Sralph if (chdir(SD) < 0) 6916763Sralph frecverr("%s: %s: %m", printer, SD); 7016763Sralph if (stat(LO, &stb) == 0) { 7116763Sralph if (stb.st_mode & 010) { 7216763Sralph /* queue is disabled */ 7316763Sralph putchar('\1'); /* return error code */ 7416763Sralph exit(1); 7516763Sralph } 7616763Sralph } else if (stat(SD, &stb) < 0) 7716763Sralph frecverr("%s: %s: %m", printer, SD); 7816763Sralph minfree = read_number("minfree"); 7916763Sralph ddev = find_dev(stb.st_dev, S_IFBLK); 8016763Sralph if ((dfd = open(ddev, O_RDONLY)) < 0) 8116763Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); 8216763Sralph signal(SIGTERM, rcleanup); 8316763Sralph signal(SIGPIPE, rcleanup); 8412115Sralph 8512115Sralph if (readjob()) 8612115Sralph printjob(); 8712115Sralph } 8812115Sralph 8916763Sralph char * 9016763Sralph find_dev(dev, type) 9116763Sralph register dev_t dev; 9216763Sralph register int type; 9316763Sralph { 9437968Sbostic register DIR *dfd = opendir(_PATH_DEV); 9516763Sralph struct direct *dir; 9616763Sralph struct stat stb; 9716763Sralph char devname[MAXNAMLEN+6]; 9816763Sralph char *dp; 9912115Sralph 10037968Sbostic strcpy(devname, _PATH_DEV); 10116763Sralph while ((dir = readdir(dfd))) { 10216763Sralph strcpy(devname + 5, dir->d_name); 10316763Sralph if (stat(devname, &stb)) 10416763Sralph continue; 10516763Sralph if ((stb.st_mode & S_IFMT) != type) 10616763Sralph continue; 10716763Sralph if (dev == stb.st_rdev) { 10816763Sralph closedir(dfd); 10916763Sralph dp = (char *)malloc(strlen(devname)+1); 11016763Sralph strcpy(dp, devname); 11116763Sralph return(dp); 11216763Sralph } 11316763Sralph } 11416763Sralph closedir(dfd); 11516763Sralph frecverr("cannot find device %d, %d", major(dev), minor(dev)); 11616763Sralph /*NOTREACHED*/ 11716763Sralph } 11816763Sralph 11912115Sralph /* 12012115Sralph * Read printer jobs sent by lpd and copy them to the spooling directory. 12112115Sralph * Return the number of jobs successfully transfered. 12212115Sralph */ 12316763Sralph readjob() 12412115Sralph { 12512115Sralph register int size, nfiles; 12612115Sralph register char *cp; 12712115Sralph 12812115Sralph ack(); 12912115Sralph nfiles = 0; 13012115Sralph for (;;) { 13112115Sralph /* 13212115Sralph * Read a command to tell us what to do 13312115Sralph */ 13412115Sralph cp = line; 13512115Sralph do { 13612115Sralph if ((size = read(1, cp, 1)) != 1) { 13712115Sralph if (size < 0) 13816763Sralph frecverr("%s: Lost connection",printer); 13912115Sralph return(nfiles); 14012115Sralph } 14112115Sralph } while (*cp++ != '\n'); 14212115Sralph *--cp = '\0'; 14312115Sralph cp = line; 14412115Sralph switch (*cp++) { 14512115Sralph case '\1': /* cleanup because data sent was bad */ 14616763Sralph rcleanup(); 14712115Sralph continue; 14812115Sralph 14912115Sralph case '\2': /* read cf file */ 15012115Sralph size = 0; 15112115Sralph while (*cp >= '0' && *cp <= '9') 15212115Sralph size = size * 10 + (*cp++ - '0'); 15312115Sralph if (*cp++ != ' ') 15412115Sralph break; 15527086Sbloom /* 15627086Sbloom * host name has been authenticated, we use our 15727086Sbloom * view of the host name since we may be passed 15827086Sbloom * something different than what gethostbyaddr() 15927086Sbloom * returns 16027086Sbloom */ 16127086Sbloom strcpy(cp + 6, from); 16212115Sralph strcpy(tfname, cp); 16312115Sralph tfname[0] = 't'; 16416763Sralph if (!chksize(size)) { 16516763Sralph (void) write(1, "\2", 1); 16616763Sralph continue; 16716763Sralph } 16812115Sralph if (!readfile(tfname, size)) { 16916763Sralph rcleanup(); 17012115Sralph continue; 17112115Sralph } 17212115Sralph if (link(tfname, cp) < 0) 17316763Sralph frecverr("%s: %m", tfname); 17412115Sralph (void) unlink(tfname); 17512115Sralph tfname[0] = '\0'; 17612115Sralph nfiles++; 17712115Sralph continue; 17812115Sralph 17912115Sralph case '\3': /* read df file */ 18012115Sralph size = 0; 18112115Sralph while (*cp >= '0' && *cp <= '9') 18212115Sralph size = size * 10 + (*cp++ - '0'); 18312115Sralph if (*cp++ != ' ') 18412115Sralph break; 18516763Sralph if (!chksize(size)) { 18616763Sralph (void) write(1, "\2", 1); 18716763Sralph continue; 18816763Sralph } 18929385Smckusick strcpy(dfname, cp); 19029385Smckusick (void) readfile(dfname, size); 19112115Sralph continue; 19212115Sralph } 19316763Sralph frecverr("protocol screwup"); 19412115Sralph } 19512115Sralph } 19612115Sralph 19712115Sralph /* 19812115Sralph * Read files send by lpd and copy them to the spooling directory. 19912115Sralph */ 20012115Sralph readfile(file, size) 20112115Sralph char *file; 20212115Sralph int size; 20312115Sralph { 20412115Sralph register char *cp; 20512115Sralph char buf[BUFSIZ]; 20612115Sralph register int i, j, amt; 20712115Sralph int fd, err; 20812115Sralph 20913149Ssam fd = open(file, O_WRONLY|O_CREAT, FILMOD); 21012115Sralph if (fd < 0) 21116763Sralph frecverr("%s: %m", file); 21212115Sralph ack(); 21312115Sralph err = 0; 21412115Sralph for (i = 0; i < size; i += BUFSIZ) { 21512115Sralph amt = BUFSIZ; 21612115Sralph cp = buf; 21712115Sralph if (i + amt > size) 21812115Sralph amt = size - i; 21912115Sralph do { 22012115Sralph j = read(1, cp, amt); 22112115Sralph if (j <= 0) 22216763Sralph frecverr("Lost connection"); 22312115Sralph amt -= j; 22412115Sralph cp += j; 22512115Sralph } while (amt > 0); 22612115Sralph amt = BUFSIZ; 22712115Sralph if (i + amt > size) 22812115Sralph amt = size - i; 22913170Sralph if (write(fd, buf, amt) != amt) { 23012115Sralph err++; 23113170Sralph break; 23213170Sralph } 23312115Sralph } 23412115Sralph (void) close(fd); 23512115Sralph if (err) 23616763Sralph frecverr("%s: write error", file); 23712115Sralph if (noresponse()) { /* file sent had bad data in it */ 23812115Sralph (void) unlink(file); 23912115Sralph return(0); 24012115Sralph } 24112115Sralph ack(); 24212115Sralph return(1); 24312115Sralph } 24412115Sralph 24512115Sralph noresponse() 24612115Sralph { 24712115Sralph char resp; 24812115Sralph 24912115Sralph if (read(1, &resp, 1) != 1) 25016763Sralph frecverr("Lost connection"); 25112115Sralph if (resp == '\0') 25212115Sralph return(0); 25312115Sralph return(1); 25412115Sralph } 25512115Sralph 25612115Sralph /* 25716763Sralph * Check to see if there is enough space on the disk for size bytes. 25816763Sralph * 1 == OK, 0 == Not OK. 25916763Sralph */ 26016763Sralph chksize(size) 26116763Sralph int size; 26216763Sralph { 26316763Sralph struct stat stb; 26416763Sralph register char *ddev; 26516763Sralph int spacefree; 26616763Sralph struct fs fs; 26716763Sralph 26830656Smckusick if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0) 26916763Sralph return(1); 27016763Sralph if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs) 27116763Sralph return(1); 27230656Smckusick spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024; 27316763Sralph size = (size + 1023) / 1024; 27416763Sralph if (minfree + size > spacefree) 27516763Sralph return(0); 27616763Sralph return(1); 27716763Sralph } 27816763Sralph 27916763Sralph read_number(fn) 28016763Sralph char *fn; 28116763Sralph { 28216763Sralph char lin[80]; 28316763Sralph register FILE *fp; 28416763Sralph 28516763Sralph if ((fp = fopen(fn, "r")) == NULL) 28616763Sralph return (0); 28716763Sralph if (fgets(lin, 80, fp) == NULL) { 28816763Sralph fclose(fp); 28916763Sralph return (0); 29016763Sralph } 29116763Sralph fclose(fp); 29216763Sralph return (atoi(lin)); 29316763Sralph } 29416763Sralph 29516763Sralph /* 29612115Sralph * Remove all the files associated with the current job being transfered. 29712115Sralph */ 29816763Sralph rcleanup() 29912115Sralph { 30012115Sralph 30112115Sralph if (tfname[0]) 30212115Sralph (void) unlink(tfname); 30329385Smckusick if (dfname[0]) 30412115Sralph do { 30512115Sralph do 30612115Sralph (void) unlink(dfname); 30716938Sralph while (dfname[2]-- != 'A'); 30816938Sralph dfname[2] = 'z'; 30916938Sralph } while (dfname[0]-- != 'd'); 31029385Smckusick dfname[0] = '\0'; 31112115Sralph } 31212115Sralph 31316763Sralph frecverr(msg, a1, a2) 31412115Sralph char *msg; 31512115Sralph { 31616763Sralph rcleanup(); 31716763Sralph syslog(LOG_ERR, msg, a1, a2); 31812115Sralph putchar('\1'); /* return error code */ 31912115Sralph exit(1); 32012115Sralph } 321