122438Sdist /* 222438Sdist * Copyright (c) 1983 Regents of the University of California. 322438Sdist * All rights reserved. The Berkeley software License Agreement 422438Sdist * specifies the terms and conditions for redistribution. 522438Sdist */ 622438Sdist 713955Ssam #ifndef lint 8*30656Smckusick static char sccsid[] = "@(#)recvjob.c 5.5 (Berkeley) 03/19/87"; 922438Sdist #endif not lint 1013955Ssam 1112115Sralph /* 1212115Sralph * Receive printer jobs from the network, queue them and 1312115Sralph * start the printer daemon. 1412115Sralph */ 1512115Sralph 1612115Sralph #include "lp.h" 1716763Sralph #include <sys/fs.h> 1812115Sralph 1916763Sralph char *sp = ""; 2016763Sralph #define ack() (void) write(1, sp, 1); 2112115Sralph 2216763Sralph char tfname[40]; /* tmp copy of cf before linking */ 2329385Smckusick char dfname[40]; /* data files */ 2416763Sralph int minfree; /* keep at least minfree blocks available */ 2516763Sralph char *ddev; /* disk device (for checking free space) */ 2616763Sralph int dfd; /* file system device descriptor */ 2716763Sralph 2816763Sralph char *find_dev(); 2916763Sralph 3012115Sralph recvjob() 3112115Sralph { 3212464Sralph struct stat stb; 3312115Sralph char *bp = pbuf; 3416763Sralph int status, rcleanup(); 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) 4412115Sralph LF = DEFLOGF; 4512115Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 4612115Sralph SD = 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); 5325498Seric (void) open("/dev/null", 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); 6616763Sralph minfree = read_number("minfree"); 6716763Sralph ddev = find_dev(stb.st_dev, S_IFBLK); 6816763Sralph if ((dfd = open(ddev, O_RDONLY)) < 0) 6916763Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); 7016763Sralph signal(SIGTERM, rcleanup); 7116763Sralph signal(SIGPIPE, rcleanup); 7212115Sralph 7312115Sralph if (readjob()) 7412115Sralph printjob(); 7512115Sralph } 7612115Sralph 7716763Sralph char * 7816763Sralph find_dev(dev, type) 7916763Sralph register dev_t dev; 8016763Sralph register int type; 8116763Sralph { 8216763Sralph register DIR *dfd = opendir("/dev"); 8316763Sralph struct direct *dir; 8416763Sralph struct stat stb; 8516763Sralph char devname[MAXNAMLEN+6]; 8616763Sralph char *dp; 8712115Sralph 8816763Sralph strcpy(devname, "/dev/"); 8916763Sralph while ((dir = readdir(dfd))) { 9016763Sralph strcpy(devname + 5, dir->d_name); 9116763Sralph if (stat(devname, &stb)) 9216763Sralph continue; 9316763Sralph if ((stb.st_mode & S_IFMT) != type) 9416763Sralph continue; 9516763Sralph if (dev == stb.st_rdev) { 9616763Sralph closedir(dfd); 9716763Sralph dp = (char *)malloc(strlen(devname)+1); 9816763Sralph strcpy(dp, devname); 9916763Sralph return(dp); 10016763Sralph } 10116763Sralph } 10216763Sralph closedir(dfd); 10316763Sralph frecverr("cannot find device %d, %d", major(dev), minor(dev)); 10416763Sralph /*NOTREACHED*/ 10516763Sralph } 10616763Sralph 10712115Sralph /* 10812115Sralph * Read printer jobs sent by lpd and copy them to the spooling directory. 10912115Sralph * Return the number of jobs successfully transfered. 11012115Sralph */ 11116763Sralph readjob() 11212115Sralph { 11312115Sralph register int size, nfiles; 11412115Sralph register char *cp; 11512115Sralph 11612115Sralph ack(); 11712115Sralph nfiles = 0; 11812115Sralph for (;;) { 11912115Sralph /* 12012115Sralph * Read a command to tell us what to do 12112115Sralph */ 12212115Sralph cp = line; 12312115Sralph do { 12412115Sralph if ((size = read(1, cp, 1)) != 1) { 12512115Sralph if (size < 0) 12616763Sralph frecverr("%s: Lost connection",printer); 12712115Sralph return(nfiles); 12812115Sralph } 12912115Sralph } while (*cp++ != '\n'); 13012115Sralph *--cp = '\0'; 13112115Sralph cp = line; 13212115Sralph switch (*cp++) { 13312115Sralph case '\1': /* cleanup because data sent was bad */ 13416763Sralph rcleanup(); 13512115Sralph continue; 13612115Sralph 13712115Sralph case '\2': /* read cf file */ 13812115Sralph size = 0; 13912115Sralph while (*cp >= '0' && *cp <= '9') 14012115Sralph size = size * 10 + (*cp++ - '0'); 14112115Sralph if (*cp++ != ' ') 14212115Sralph break; 14327086Sbloom /* 14427086Sbloom * host name has been authenticated, we use our 14527086Sbloom * view of the host name since we may be passed 14627086Sbloom * something different than what gethostbyaddr() 14727086Sbloom * returns 14827086Sbloom */ 14927086Sbloom strcpy(cp + 6, from); 15012115Sralph strcpy(tfname, cp); 15112115Sralph tfname[0] = 't'; 15216763Sralph if (!chksize(size)) { 15316763Sralph (void) write(1, "\2", 1); 15416763Sralph continue; 15516763Sralph } 15612115Sralph if (!readfile(tfname, size)) { 15716763Sralph rcleanup(); 15812115Sralph continue; 15912115Sralph } 16012115Sralph if (link(tfname, cp) < 0) 16116763Sralph frecverr("%s: %m", tfname); 16212115Sralph (void) unlink(tfname); 16312115Sralph tfname[0] = '\0'; 16412115Sralph nfiles++; 16512115Sralph continue; 16612115Sralph 16712115Sralph case '\3': /* read df file */ 16812115Sralph size = 0; 16912115Sralph while (*cp >= '0' && *cp <= '9') 17012115Sralph size = size * 10 + (*cp++ - '0'); 17112115Sralph if (*cp++ != ' ') 17212115Sralph break; 17316763Sralph if (!chksize(size)) { 17416763Sralph (void) write(1, "\2", 1); 17516763Sralph continue; 17616763Sralph } 17729385Smckusick strcpy(dfname, cp); 17829385Smckusick (void) readfile(dfname, size); 17912115Sralph continue; 18012115Sralph } 18116763Sralph frecverr("protocol screwup"); 18212115Sralph } 18312115Sralph } 18412115Sralph 18512115Sralph /* 18612115Sralph * Read files send by lpd and copy them to the spooling directory. 18712115Sralph */ 18812115Sralph readfile(file, size) 18912115Sralph char *file; 19012115Sralph int size; 19112115Sralph { 19212115Sralph register char *cp; 19312115Sralph char buf[BUFSIZ]; 19412115Sralph register int i, j, amt; 19512115Sralph int fd, err; 19612115Sralph 19713149Ssam fd = open(file, O_WRONLY|O_CREAT, FILMOD); 19812115Sralph if (fd < 0) 19916763Sralph frecverr("%s: %m", file); 20012115Sralph ack(); 20112115Sralph err = 0; 20212115Sralph for (i = 0; i < size; i += BUFSIZ) { 20312115Sralph amt = BUFSIZ; 20412115Sralph cp = buf; 20512115Sralph if (i + amt > size) 20612115Sralph amt = size - i; 20712115Sralph do { 20812115Sralph j = read(1, cp, amt); 20912115Sralph if (j <= 0) 21016763Sralph frecverr("Lost connection"); 21112115Sralph amt -= j; 21212115Sralph cp += j; 21312115Sralph } while (amt > 0); 21412115Sralph amt = BUFSIZ; 21512115Sralph if (i + amt > size) 21612115Sralph amt = size - i; 21713170Sralph if (write(fd, buf, amt) != amt) { 21812115Sralph err++; 21913170Sralph break; 22013170Sralph } 22112115Sralph } 22212115Sralph (void) close(fd); 22312115Sralph if (err) 22416763Sralph frecverr("%s: write error", file); 22512115Sralph if (noresponse()) { /* file sent had bad data in it */ 22612115Sralph (void) unlink(file); 22712115Sralph return(0); 22812115Sralph } 22912115Sralph ack(); 23012115Sralph return(1); 23112115Sralph } 23212115Sralph 23312115Sralph noresponse() 23412115Sralph { 23512115Sralph char resp; 23612115Sralph 23712115Sralph if (read(1, &resp, 1) != 1) 23816763Sralph frecverr("Lost connection"); 23912115Sralph if (resp == '\0') 24012115Sralph return(0); 24112115Sralph return(1); 24212115Sralph } 24312115Sralph 24412115Sralph /* 24516763Sralph * Check to see if there is enough space on the disk for size bytes. 24616763Sralph * 1 == OK, 0 == Not OK. 24716763Sralph */ 24816763Sralph chksize(size) 24916763Sralph int size; 25016763Sralph { 25116763Sralph struct stat stb; 25216763Sralph register char *ddev; 25316763Sralph int spacefree; 25416763Sralph struct fs fs; 25516763Sralph 256*30656Smckusick if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0) 25716763Sralph return(1); 25816763Sralph if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs) 25916763Sralph return(1); 260*30656Smckusick spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024; 26116763Sralph size = (size + 1023) / 1024; 26216763Sralph if (minfree + size > spacefree) 26316763Sralph return(0); 26416763Sralph return(1); 26516763Sralph } 26616763Sralph 26716763Sralph read_number(fn) 26816763Sralph char *fn; 26916763Sralph { 27016763Sralph char lin[80]; 27116763Sralph register FILE *fp; 27216763Sralph 27316763Sralph if ((fp = fopen(fn, "r")) == NULL) 27416763Sralph return (0); 27516763Sralph if (fgets(lin, 80, fp) == NULL) { 27616763Sralph fclose(fp); 27716763Sralph return (0); 27816763Sralph } 27916763Sralph fclose(fp); 28016763Sralph return (atoi(lin)); 28116763Sralph } 28216763Sralph 28316763Sralph /* 28412115Sralph * Remove all the files associated with the current job being transfered. 28512115Sralph */ 28616763Sralph rcleanup() 28712115Sralph { 28812115Sralph 28912115Sralph if (tfname[0]) 29012115Sralph (void) unlink(tfname); 29129385Smckusick if (dfname[0]) 29212115Sralph do { 29312115Sralph do 29412115Sralph (void) unlink(dfname); 29516938Sralph while (dfname[2]-- != 'A'); 29616938Sralph dfname[2] = 'z'; 29716938Sralph } while (dfname[0]-- != 'd'); 29829385Smckusick dfname[0] = '\0'; 29912115Sralph } 30012115Sralph 30116763Sralph frecverr(msg, a1, a2) 30212115Sralph char *msg; 30312115Sralph { 30416763Sralph rcleanup(); 30516763Sralph syslog(LOG_ERR, msg, a1, a2); 30612115Sralph putchar('\1'); /* return error code */ 30712115Sralph exit(1); 30812115Sralph } 309