122438Sdist /* 222438Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 5*42802Sbostic * %sccs.include.redist.c% 622438Sdist */ 722438Sdist 813955Ssam #ifndef lint 9*42802Sbostic static char sccsid[] = "@(#)recvjob.c 5.11 (Berkeley) 06/01/90"; 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" 1838493Skarels #include <ufs/fs.h> 1937968Sbostic #include "pathnames.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 char *ddev; /* disk device (for checking free space) */ 2816763Sralph int dfd; /* file system device descriptor */ 2916763Sralph 3016763Sralph char *find_dev(); 3116763Sralph 3212115Sralph recvjob() 3312115Sralph { 3412464Sralph struct stat stb; 3512115Sralph char *bp = pbuf; 3616763Sralph int status, rcleanup(); 3712115Sralph 3812115Sralph /* 3912115Sralph * Perform lookup for printer name or abbreviation 4012115Sralph */ 4112115Sralph if ((status = pgetent(line, printer)) < 0) 4216763Sralph frecverr("cannot open printer description file"); 4312115Sralph else if (status == 0) 4416763Sralph frecverr("unknown printer %s", printer); 4512115Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 4637968Sbostic LF = _PATH_CONSOLE; 4712115Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 4837968Sbostic SD = _PATH_DEFSPOOL; 4912464Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 5012464Sralph LO = DEFLOCK; 5112115Sralph 5225498Seric (void) close(2); /* set up log file */ 5325498Seric if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { 5425498Seric syslog(LOG_ERR, "%s: %m", LF); 5537968Sbostic (void) open(_PATH_DEVNULL, O_WRONLY); 5625498Seric } 5725498Seric 5812115Sralph if (chdir(SD) < 0) 5916763Sralph frecverr("%s: %s: %m", printer, SD); 6016763Sralph if (stat(LO, &stb) == 0) { 6116763Sralph if (stb.st_mode & 010) { 6216763Sralph /* queue is disabled */ 6316763Sralph putchar('\1'); /* return error code */ 6416763Sralph exit(1); 6516763Sralph } 6616763Sralph } else if (stat(SD, &stb) < 0) 6716763Sralph frecverr("%s: %s: %m", printer, SD); 6816763Sralph minfree = read_number("minfree"); 6916763Sralph ddev = find_dev(stb.st_dev, S_IFBLK); 7016763Sralph if ((dfd = open(ddev, O_RDONLY)) < 0) 7116763Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); 7216763Sralph signal(SIGTERM, rcleanup); 7316763Sralph signal(SIGPIPE, rcleanup); 7412115Sralph 7512115Sralph if (readjob()) 7612115Sralph printjob(); 7712115Sralph } 7812115Sralph 7916763Sralph char * 8016763Sralph find_dev(dev, type) 8116763Sralph register dev_t dev; 8216763Sralph register int type; 8316763Sralph { 8437968Sbostic register DIR *dfd = opendir(_PATH_DEV); 8516763Sralph struct direct *dir; 8616763Sralph struct stat stb; 8716763Sralph char devname[MAXNAMLEN+6]; 8816763Sralph char *dp; 8912115Sralph 9037968Sbostic strcpy(devname, _PATH_DEV); 9116763Sralph while ((dir = readdir(dfd))) { 9216763Sralph strcpy(devname + 5, dir->d_name); 9316763Sralph if (stat(devname, &stb)) 9416763Sralph continue; 9516763Sralph if ((stb.st_mode & S_IFMT) != type) 9616763Sralph continue; 9716763Sralph if (dev == stb.st_rdev) { 9816763Sralph closedir(dfd); 9916763Sralph dp = (char *)malloc(strlen(devname)+1); 10016763Sralph strcpy(dp, devname); 10116763Sralph return(dp); 10216763Sralph } 10316763Sralph } 10416763Sralph closedir(dfd); 10516763Sralph frecverr("cannot find device %d, %d", major(dev), minor(dev)); 10616763Sralph /*NOTREACHED*/ 10716763Sralph } 10816763Sralph 10912115Sralph /* 11012115Sralph * Read printer jobs sent by lpd and copy them to the spooling directory. 11112115Sralph * Return the number of jobs successfully transfered. 11212115Sralph */ 11316763Sralph readjob() 11412115Sralph { 11512115Sralph register int size, nfiles; 11612115Sralph register char *cp; 11712115Sralph 11812115Sralph ack(); 11912115Sralph nfiles = 0; 12012115Sralph for (;;) { 12112115Sralph /* 12212115Sralph * Read a command to tell us what to do 12312115Sralph */ 12412115Sralph cp = line; 12512115Sralph do { 12612115Sralph if ((size = read(1, cp, 1)) != 1) { 12712115Sralph if (size < 0) 12816763Sralph frecverr("%s: Lost connection",printer); 12912115Sralph return(nfiles); 13012115Sralph } 13112115Sralph } while (*cp++ != '\n'); 13212115Sralph *--cp = '\0'; 13312115Sralph cp = line; 13412115Sralph switch (*cp++) { 13512115Sralph case '\1': /* cleanup because data sent was bad */ 13616763Sralph rcleanup(); 13712115Sralph continue; 13812115Sralph 13912115Sralph case '\2': /* read cf file */ 14012115Sralph size = 0; 14112115Sralph while (*cp >= '0' && *cp <= '9') 14212115Sralph size = size * 10 + (*cp++ - '0'); 14312115Sralph if (*cp++ != ' ') 14412115Sralph break; 14527086Sbloom /* 14627086Sbloom * host name has been authenticated, we use our 14727086Sbloom * view of the host name since we may be passed 14827086Sbloom * something different than what gethostbyaddr() 14927086Sbloom * returns 15027086Sbloom */ 15127086Sbloom strcpy(cp + 6, from); 15212115Sralph strcpy(tfname, cp); 15312115Sralph tfname[0] = 't'; 15416763Sralph if (!chksize(size)) { 15516763Sralph (void) write(1, "\2", 1); 15616763Sralph continue; 15716763Sralph } 15812115Sralph if (!readfile(tfname, size)) { 15916763Sralph rcleanup(); 16012115Sralph continue; 16112115Sralph } 16212115Sralph if (link(tfname, cp) < 0) 16316763Sralph frecverr("%s: %m", tfname); 16412115Sralph (void) unlink(tfname); 16512115Sralph tfname[0] = '\0'; 16612115Sralph nfiles++; 16712115Sralph continue; 16812115Sralph 16912115Sralph case '\3': /* read df file */ 17012115Sralph size = 0; 17112115Sralph while (*cp >= '0' && *cp <= '9') 17212115Sralph size = size * 10 + (*cp++ - '0'); 17312115Sralph if (*cp++ != ' ') 17412115Sralph break; 17516763Sralph if (!chksize(size)) { 17616763Sralph (void) write(1, "\2", 1); 17716763Sralph continue; 17816763Sralph } 17939220Sbostic (void) strcpy(dfname, cp); 18039220Sbostic if (index(dfname, '/')) 18139220Sbostic frecverr("illegal path name"); 18229385Smckusick (void) readfile(dfname, size); 18312115Sralph continue; 18412115Sralph } 18516763Sralph frecverr("protocol screwup"); 18612115Sralph } 18712115Sralph } 18812115Sralph 18912115Sralph /* 19012115Sralph * Read files send by lpd and copy them to the spooling directory. 19112115Sralph */ 19212115Sralph readfile(file, size) 19312115Sralph char *file; 19412115Sralph int size; 19512115Sralph { 19612115Sralph register char *cp; 19712115Sralph char buf[BUFSIZ]; 19812115Sralph register int i, j, amt; 19912115Sralph int fd, err; 20012115Sralph 20113149Ssam fd = open(file, O_WRONLY|O_CREAT, FILMOD); 20212115Sralph if (fd < 0) 20316763Sralph frecverr("%s: %m", file); 20412115Sralph ack(); 20512115Sralph err = 0; 20612115Sralph for (i = 0; i < size; i += BUFSIZ) { 20712115Sralph amt = BUFSIZ; 20812115Sralph cp = buf; 20912115Sralph if (i + amt > size) 21012115Sralph amt = size - i; 21112115Sralph do { 21212115Sralph j = read(1, cp, amt); 21312115Sralph if (j <= 0) 21416763Sralph frecverr("Lost connection"); 21512115Sralph amt -= j; 21612115Sralph cp += j; 21712115Sralph } while (amt > 0); 21812115Sralph amt = BUFSIZ; 21912115Sralph if (i + amt > size) 22012115Sralph amt = size - i; 22113170Sralph if (write(fd, buf, amt) != amt) { 22212115Sralph err++; 22313170Sralph break; 22413170Sralph } 22512115Sralph } 22612115Sralph (void) close(fd); 22712115Sralph if (err) 22816763Sralph frecverr("%s: write error", file); 22912115Sralph if (noresponse()) { /* file sent had bad data in it */ 23012115Sralph (void) unlink(file); 23112115Sralph return(0); 23212115Sralph } 23312115Sralph ack(); 23412115Sralph return(1); 23512115Sralph } 23612115Sralph 23712115Sralph noresponse() 23812115Sralph { 23912115Sralph char resp; 24012115Sralph 24112115Sralph if (read(1, &resp, 1) != 1) 24216763Sralph frecverr("Lost connection"); 24312115Sralph if (resp == '\0') 24412115Sralph return(0); 24512115Sralph return(1); 24612115Sralph } 24712115Sralph 24812115Sralph /* 24916763Sralph * Check to see if there is enough space on the disk for size bytes. 25016763Sralph * 1 == OK, 0 == Not OK. 25116763Sralph */ 25216763Sralph chksize(size) 25316763Sralph int size; 25416763Sralph { 25516763Sralph int spacefree; 25616763Sralph struct fs fs; 25716763Sralph 25830656Smckusick if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0) 25916763Sralph return(1); 26016763Sralph if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs) 26116763Sralph return(1); 26230656Smckusick spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024; 26316763Sralph size = (size + 1023) / 1024; 26416763Sralph if (minfree + size > spacefree) 26516763Sralph return(0); 26616763Sralph return(1); 26716763Sralph } 26816763Sralph 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 */ 28816763Sralph rcleanup() 28912115Sralph { 29012115Sralph 29112115Sralph if (tfname[0]) 29212115Sralph (void) unlink(tfname); 29329385Smckusick if (dfname[0]) 29412115Sralph do { 29512115Sralph do 29612115Sralph (void) unlink(dfname); 29716938Sralph while (dfname[2]-- != 'A'); 29816938Sralph dfname[2] = 'z'; 29916938Sralph } while (dfname[0]-- != 'd'); 30029385Smckusick dfname[0] = '\0'; 30112115Sralph } 30212115Sralph 30316763Sralph frecverr(msg, a1, a2) 30412115Sralph char *msg; 30512115Sralph { 30616763Sralph rcleanup(); 30716763Sralph syslog(LOG_ERR, msg, a1, a2); 30812115Sralph putchar('\1'); /* return error code */ 30912115Sralph exit(1); 31012115Sralph } 311