122438Sdist /* 222438Sdist * Copyright (c) 1983 Regents of the University of California. 3*34203Sbostic * All rights reserved. 4*34203Sbostic * 5*34203Sbostic * Redistribution and use in source and binary forms are permitted 6*34203Sbostic * provided that this notice is preserved and that due credit is given 7*34203Sbostic * to the University of California at Berkeley. The name of the University 8*34203Sbostic * may not be used to endorse or promote products derived from this 9*34203Sbostic * software without specific prior written permission. This software 10*34203Sbostic * is provided ``as is'' without express or implied warranty. 1122438Sdist */ 1222438Sdist 1313955Ssam #ifndef lint 14*34203Sbostic static char sccsid[] = "@(#)recvjob.c 5.6 (Berkeley) 05/05/88"; 15*34203Sbostic #endif /* not lint */ 1613955Ssam 1712115Sralph /* 1812115Sralph * Receive printer jobs from the network, queue them and 1912115Sralph * start the printer daemon. 2012115Sralph */ 2112115Sralph 2212115Sralph #include "lp.h" 2316763Sralph #include <sys/fs.h> 2412115Sralph 2516763Sralph char *sp = ""; 2616763Sralph #define ack() (void) write(1, sp, 1); 2712115Sralph 2816763Sralph char tfname[40]; /* tmp copy of cf before linking */ 2929385Smckusick char dfname[40]; /* data files */ 3016763Sralph int minfree; /* keep at least minfree blocks available */ 3116763Sralph char *ddev; /* disk device (for checking free space) */ 3216763Sralph int dfd; /* file system device descriptor */ 3316763Sralph 3416763Sralph char *find_dev(); 3516763Sralph 3612115Sralph recvjob() 3712115Sralph { 3812464Sralph struct stat stb; 3912115Sralph char *bp = pbuf; 4016763Sralph int status, rcleanup(); 4112115Sralph 4212115Sralph /* 4312115Sralph * Perform lookup for printer name or abbreviation 4412115Sralph */ 4512115Sralph if ((status = pgetent(line, printer)) < 0) 4616763Sralph frecverr("cannot open printer description file"); 4712115Sralph else if (status == 0) 4816763Sralph frecverr("unknown printer %s", printer); 4912115Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 5012115Sralph LF = DEFLOGF; 5112115Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 5212115Sralph SD = DEFSPOOL; 5312464Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 5412464Sralph LO = DEFLOCK; 5512115Sralph 5625498Seric (void) close(2); /* set up log file */ 5725498Seric if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { 5825498Seric syslog(LOG_ERR, "%s: %m", LF); 5925498Seric (void) open("/dev/null", O_WRONLY); 6025498Seric } 6125498Seric 6212115Sralph if (chdir(SD) < 0) 6316763Sralph frecverr("%s: %s: %m", printer, SD); 6416763Sralph if (stat(LO, &stb) == 0) { 6516763Sralph if (stb.st_mode & 010) { 6616763Sralph /* queue is disabled */ 6716763Sralph putchar('\1'); /* return error code */ 6816763Sralph exit(1); 6916763Sralph } 7016763Sralph } else if (stat(SD, &stb) < 0) 7116763Sralph frecverr("%s: %s: %m", printer, SD); 7216763Sralph minfree = read_number("minfree"); 7316763Sralph ddev = find_dev(stb.st_dev, S_IFBLK); 7416763Sralph if ((dfd = open(ddev, O_RDONLY)) < 0) 7516763Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); 7616763Sralph signal(SIGTERM, rcleanup); 7716763Sralph signal(SIGPIPE, rcleanup); 7812115Sralph 7912115Sralph if (readjob()) 8012115Sralph printjob(); 8112115Sralph } 8212115Sralph 8316763Sralph char * 8416763Sralph find_dev(dev, type) 8516763Sralph register dev_t dev; 8616763Sralph register int type; 8716763Sralph { 8816763Sralph register DIR *dfd = opendir("/dev"); 8916763Sralph struct direct *dir; 9016763Sralph struct stat stb; 9116763Sralph char devname[MAXNAMLEN+6]; 9216763Sralph char *dp; 9312115Sralph 9416763Sralph strcpy(devname, "/dev/"); 9516763Sralph while ((dir = readdir(dfd))) { 9616763Sralph strcpy(devname + 5, dir->d_name); 9716763Sralph if (stat(devname, &stb)) 9816763Sralph continue; 9916763Sralph if ((stb.st_mode & S_IFMT) != type) 10016763Sralph continue; 10116763Sralph if (dev == stb.st_rdev) { 10216763Sralph closedir(dfd); 10316763Sralph dp = (char *)malloc(strlen(devname)+1); 10416763Sralph strcpy(dp, devname); 10516763Sralph return(dp); 10616763Sralph } 10716763Sralph } 10816763Sralph closedir(dfd); 10916763Sralph frecverr("cannot find device %d, %d", major(dev), minor(dev)); 11016763Sralph /*NOTREACHED*/ 11116763Sralph } 11216763Sralph 11312115Sralph /* 11412115Sralph * Read printer jobs sent by lpd and copy them to the spooling directory. 11512115Sralph * Return the number of jobs successfully transfered. 11612115Sralph */ 11716763Sralph readjob() 11812115Sralph { 11912115Sralph register int size, nfiles; 12012115Sralph register char *cp; 12112115Sralph 12212115Sralph ack(); 12312115Sralph nfiles = 0; 12412115Sralph for (;;) { 12512115Sralph /* 12612115Sralph * Read a command to tell us what to do 12712115Sralph */ 12812115Sralph cp = line; 12912115Sralph do { 13012115Sralph if ((size = read(1, cp, 1)) != 1) { 13112115Sralph if (size < 0) 13216763Sralph frecverr("%s: Lost connection",printer); 13312115Sralph return(nfiles); 13412115Sralph } 13512115Sralph } while (*cp++ != '\n'); 13612115Sralph *--cp = '\0'; 13712115Sralph cp = line; 13812115Sralph switch (*cp++) { 13912115Sralph case '\1': /* cleanup because data sent was bad */ 14016763Sralph rcleanup(); 14112115Sralph continue; 14212115Sralph 14312115Sralph case '\2': /* read cf file */ 14412115Sralph size = 0; 14512115Sralph while (*cp >= '0' && *cp <= '9') 14612115Sralph size = size * 10 + (*cp++ - '0'); 14712115Sralph if (*cp++ != ' ') 14812115Sralph break; 14927086Sbloom /* 15027086Sbloom * host name has been authenticated, we use our 15127086Sbloom * view of the host name since we may be passed 15227086Sbloom * something different than what gethostbyaddr() 15327086Sbloom * returns 15427086Sbloom */ 15527086Sbloom strcpy(cp + 6, from); 15612115Sralph strcpy(tfname, cp); 15712115Sralph tfname[0] = 't'; 15816763Sralph if (!chksize(size)) { 15916763Sralph (void) write(1, "\2", 1); 16016763Sralph continue; 16116763Sralph } 16212115Sralph if (!readfile(tfname, size)) { 16316763Sralph rcleanup(); 16412115Sralph continue; 16512115Sralph } 16612115Sralph if (link(tfname, cp) < 0) 16716763Sralph frecverr("%s: %m", tfname); 16812115Sralph (void) unlink(tfname); 16912115Sralph tfname[0] = '\0'; 17012115Sralph nfiles++; 17112115Sralph continue; 17212115Sralph 17312115Sralph case '\3': /* read df file */ 17412115Sralph size = 0; 17512115Sralph while (*cp >= '0' && *cp <= '9') 17612115Sralph size = size * 10 + (*cp++ - '0'); 17712115Sralph if (*cp++ != ' ') 17812115Sralph break; 17916763Sralph if (!chksize(size)) { 18016763Sralph (void) write(1, "\2", 1); 18116763Sralph continue; 18216763Sralph } 18329385Smckusick strcpy(dfname, cp); 18429385Smckusick (void) readfile(dfname, size); 18512115Sralph continue; 18612115Sralph } 18716763Sralph frecverr("protocol screwup"); 18812115Sralph } 18912115Sralph } 19012115Sralph 19112115Sralph /* 19212115Sralph * Read files send by lpd and copy them to the spooling directory. 19312115Sralph */ 19412115Sralph readfile(file, size) 19512115Sralph char *file; 19612115Sralph int size; 19712115Sralph { 19812115Sralph register char *cp; 19912115Sralph char buf[BUFSIZ]; 20012115Sralph register int i, j, amt; 20112115Sralph int fd, err; 20212115Sralph 20313149Ssam fd = open(file, O_WRONLY|O_CREAT, FILMOD); 20412115Sralph if (fd < 0) 20516763Sralph frecverr("%s: %m", file); 20612115Sralph ack(); 20712115Sralph err = 0; 20812115Sralph for (i = 0; i < size; i += BUFSIZ) { 20912115Sralph amt = BUFSIZ; 21012115Sralph cp = buf; 21112115Sralph if (i + amt > size) 21212115Sralph amt = size - i; 21312115Sralph do { 21412115Sralph j = read(1, cp, amt); 21512115Sralph if (j <= 0) 21616763Sralph frecverr("Lost connection"); 21712115Sralph amt -= j; 21812115Sralph cp += j; 21912115Sralph } while (amt > 0); 22012115Sralph amt = BUFSIZ; 22112115Sralph if (i + amt > size) 22212115Sralph amt = size - i; 22313170Sralph if (write(fd, buf, amt) != amt) { 22412115Sralph err++; 22513170Sralph break; 22613170Sralph } 22712115Sralph } 22812115Sralph (void) close(fd); 22912115Sralph if (err) 23016763Sralph frecverr("%s: write error", file); 23112115Sralph if (noresponse()) { /* file sent had bad data in it */ 23212115Sralph (void) unlink(file); 23312115Sralph return(0); 23412115Sralph } 23512115Sralph ack(); 23612115Sralph return(1); 23712115Sralph } 23812115Sralph 23912115Sralph noresponse() 24012115Sralph { 24112115Sralph char resp; 24212115Sralph 24312115Sralph if (read(1, &resp, 1) != 1) 24416763Sralph frecverr("Lost connection"); 24512115Sralph if (resp == '\0') 24612115Sralph return(0); 24712115Sralph return(1); 24812115Sralph } 24912115Sralph 25012115Sralph /* 25116763Sralph * Check to see if there is enough space on the disk for size bytes. 25216763Sralph * 1 == OK, 0 == Not OK. 25316763Sralph */ 25416763Sralph chksize(size) 25516763Sralph int size; 25616763Sralph { 25716763Sralph struct stat stb; 25816763Sralph register char *ddev; 25916763Sralph int spacefree; 26016763Sralph struct fs fs; 26116763Sralph 26230656Smckusick if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0) 26316763Sralph return(1); 26416763Sralph if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs) 26516763Sralph return(1); 26630656Smckusick spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024; 26716763Sralph size = (size + 1023) / 1024; 26816763Sralph if (minfree + size > spacefree) 26916763Sralph return(0); 27016763Sralph return(1); 27116763Sralph } 27216763Sralph 27316763Sralph read_number(fn) 27416763Sralph char *fn; 27516763Sralph { 27616763Sralph char lin[80]; 27716763Sralph register FILE *fp; 27816763Sralph 27916763Sralph if ((fp = fopen(fn, "r")) == NULL) 28016763Sralph return (0); 28116763Sralph if (fgets(lin, 80, fp) == NULL) { 28216763Sralph fclose(fp); 28316763Sralph return (0); 28416763Sralph } 28516763Sralph fclose(fp); 28616763Sralph return (atoi(lin)); 28716763Sralph } 28816763Sralph 28916763Sralph /* 29012115Sralph * Remove all the files associated with the current job being transfered. 29112115Sralph */ 29216763Sralph rcleanup() 29312115Sralph { 29412115Sralph 29512115Sralph if (tfname[0]) 29612115Sralph (void) unlink(tfname); 29729385Smckusick if (dfname[0]) 29812115Sralph do { 29912115Sralph do 30012115Sralph (void) unlink(dfname); 30116938Sralph while (dfname[2]-- != 'A'); 30216938Sralph dfname[2] = 'z'; 30316938Sralph } while (dfname[0]-- != 'd'); 30429385Smckusick dfname[0] = '\0'; 30512115Sralph } 30612115Sralph 30716763Sralph frecverr(msg, a1, a2) 30812115Sralph char *msg; 30912115Sralph { 31016763Sralph rcleanup(); 31116763Sralph syslog(LOG_ERR, msg, a1, a2); 31212115Sralph putchar('\1'); /* return error code */ 31312115Sralph exit(1); 31412115Sralph } 315