1*22438Sdist /* 2*22438Sdist * Copyright (c) 1983 Regents of the University of California. 3*22438Sdist * All rights reserved. The Berkeley software License Agreement 4*22438Sdist * specifies the terms and conditions for redistribution. 5*22438Sdist */ 6*22438Sdist 713955Ssam #ifndef lint 8*22438Sdist static char sccsid[] = "@(#)recvjob.c 5.1 (Berkeley) 06/06/85"; 9*22438Sdist #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 */ 2316763Sralph char *dfname; /* 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 5012115Sralph if (chdir(SD) < 0) 5116763Sralph frecverr("%s: %s: %m", printer, SD); 5216763Sralph if (stat(LO, &stb) == 0) { 5316763Sralph if (stb.st_mode & 010) { 5416763Sralph /* queue is disabled */ 5516763Sralph putchar('\1'); /* return error code */ 5616763Sralph exit(1); 5716763Sralph } 5816763Sralph } else if (stat(SD, &stb) < 0) 5916763Sralph frecverr("%s: %s: %m", printer, SD); 6016763Sralph minfree = read_number("minfree"); 6116763Sralph ddev = find_dev(stb.st_dev, S_IFBLK); 6216763Sralph if ((dfd = open(ddev, O_RDONLY)) < 0) 6316763Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); 6416763Sralph signal(SIGTERM, rcleanup); 6516763Sralph signal(SIGPIPE, rcleanup); 6612115Sralph 6712115Sralph if (readjob()) 6812115Sralph printjob(); 6912115Sralph } 7012115Sralph 7116763Sralph char * 7216763Sralph find_dev(dev, type) 7316763Sralph register dev_t dev; 7416763Sralph register int type; 7516763Sralph { 7616763Sralph register DIR *dfd = opendir("/dev"); 7716763Sralph struct direct *dir; 7816763Sralph struct stat stb; 7916763Sralph char devname[MAXNAMLEN+6]; 8016763Sralph char *dp; 8112115Sralph 8216763Sralph strcpy(devname, "/dev/"); 8316763Sralph while ((dir = readdir(dfd))) { 8416763Sralph strcpy(devname + 5, dir->d_name); 8516763Sralph if (stat(devname, &stb)) 8616763Sralph continue; 8716763Sralph if ((stb.st_mode & S_IFMT) != type) 8816763Sralph continue; 8916763Sralph if (dev == stb.st_rdev) { 9016763Sralph closedir(dfd); 9116763Sralph dp = (char *)malloc(strlen(devname)+1); 9216763Sralph strcpy(dp, devname); 9316763Sralph return(dp); 9416763Sralph } 9516763Sralph } 9616763Sralph closedir(dfd); 9716763Sralph frecverr("cannot find device %d, %d", major(dev), minor(dev)); 9816763Sralph /*NOTREACHED*/ 9916763Sralph } 10016763Sralph 10112115Sralph /* 10212115Sralph * Read printer jobs sent by lpd and copy them to the spooling directory. 10312115Sralph * Return the number of jobs successfully transfered. 10412115Sralph */ 10516763Sralph readjob() 10612115Sralph { 10712115Sralph register int size, nfiles; 10812115Sralph register char *cp; 10912115Sralph 11012115Sralph ack(); 11112115Sralph nfiles = 0; 11212115Sralph for (;;) { 11312115Sralph /* 11412115Sralph * Read a command to tell us what to do 11512115Sralph */ 11612115Sralph cp = line; 11712115Sralph do { 11812115Sralph if ((size = read(1, cp, 1)) != 1) { 11912115Sralph if (size < 0) 12016763Sralph frecverr("%s: Lost connection",printer); 12112115Sralph return(nfiles); 12212115Sralph } 12312115Sralph } while (*cp++ != '\n'); 12412115Sralph *--cp = '\0'; 12512115Sralph cp = line; 12612115Sralph switch (*cp++) { 12712115Sralph case '\1': /* cleanup because data sent was bad */ 12816763Sralph rcleanup(); 12912115Sralph continue; 13012115Sralph 13112115Sralph case '\2': /* read cf file */ 13212115Sralph size = 0; 13312115Sralph while (*cp >= '0' && *cp <= '9') 13412115Sralph size = size * 10 + (*cp++ - '0'); 13512115Sralph if (*cp++ != ' ') 13612115Sralph break; 13712115Sralph strcpy(tfname, cp); 13812115Sralph tfname[0] = 't'; 13916763Sralph if (!chksize(size)) { 14016763Sralph (void) write(1, "\2", 1); 14116763Sralph continue; 14216763Sralph } 14312115Sralph if (!readfile(tfname, size)) { 14416763Sralph rcleanup(); 14512115Sralph continue; 14612115Sralph } 14712115Sralph if (link(tfname, cp) < 0) 14816763Sralph frecverr("%s: %m", tfname); 14912115Sralph (void) unlink(tfname); 15012115Sralph tfname[0] = '\0'; 15112115Sralph nfiles++; 15212115Sralph continue; 15312115Sralph 15412115Sralph case '\3': /* read df file */ 15512115Sralph size = 0; 15612115Sralph while (*cp >= '0' && *cp <= '9') 15712115Sralph size = size * 10 + (*cp++ - '0'); 15812115Sralph if (*cp++ != ' ') 15912115Sralph break; 16016763Sralph if (!chksize(size)) { 16116763Sralph (void) write(1, "\2", 1); 16216763Sralph continue; 16316763Sralph } 16412115Sralph (void) readfile(dfname = cp, size); 16512115Sralph continue; 16612115Sralph } 16716763Sralph frecverr("protocol screwup"); 16812115Sralph } 16912115Sralph } 17012115Sralph 17112115Sralph /* 17212115Sralph * Read files send by lpd and copy them to the spooling directory. 17312115Sralph */ 17412115Sralph readfile(file, size) 17512115Sralph char *file; 17612115Sralph int size; 17712115Sralph { 17812115Sralph register char *cp; 17912115Sralph char buf[BUFSIZ]; 18012115Sralph register int i, j, amt; 18112115Sralph int fd, err; 18212115Sralph 18313149Ssam fd = open(file, O_WRONLY|O_CREAT, FILMOD); 18412115Sralph if (fd < 0) 18516763Sralph frecverr("%s: %m", file); 18612115Sralph ack(); 18712115Sralph err = 0; 18812115Sralph for (i = 0; i < size; i += BUFSIZ) { 18912115Sralph amt = BUFSIZ; 19012115Sralph cp = buf; 19112115Sralph if (i + amt > size) 19212115Sralph amt = size - i; 19312115Sralph do { 19412115Sralph j = read(1, cp, amt); 19512115Sralph if (j <= 0) 19616763Sralph frecverr("Lost connection"); 19712115Sralph amt -= j; 19812115Sralph cp += j; 19912115Sralph } while (amt > 0); 20012115Sralph amt = BUFSIZ; 20112115Sralph if (i + amt > size) 20212115Sralph amt = size - i; 20313170Sralph if (write(fd, buf, amt) != amt) { 20412115Sralph err++; 20513170Sralph break; 20613170Sralph } 20712115Sralph } 20812115Sralph (void) close(fd); 20912115Sralph if (err) 21016763Sralph frecverr("%s: write error", file); 21112115Sralph if (noresponse()) { /* file sent had bad data in it */ 21212115Sralph (void) unlink(file); 21312115Sralph return(0); 21412115Sralph } 21512115Sralph ack(); 21612115Sralph return(1); 21712115Sralph } 21812115Sralph 21912115Sralph noresponse() 22012115Sralph { 22112115Sralph char resp; 22212115Sralph 22312115Sralph if (read(1, &resp, 1) != 1) 22416763Sralph frecverr("Lost connection"); 22512115Sralph if (resp == '\0') 22612115Sralph return(0); 22712115Sralph return(1); 22812115Sralph } 22912115Sralph 23012115Sralph /* 23116763Sralph * Check to see if there is enough space on the disk for size bytes. 23216763Sralph * 1 == OK, 0 == Not OK. 23316763Sralph */ 23416763Sralph chksize(size) 23516763Sralph int size; 23616763Sralph { 23716763Sralph struct stat stb; 23816763Sralph register char *ddev; 23916763Sralph int spacefree; 24016763Sralph struct fs fs; 24116763Sralph 24216763Sralph if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0) 24316763Sralph return(1); 24416763Sralph if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs) 24516763Sralph return(1); 24616763Sralph spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag + 24716763Sralph fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) * 24816763Sralph fs.fs_fsize / 1024; 24916763Sralph size = (size + 1023) / 1024; 25016763Sralph if (minfree + size > spacefree) 25116763Sralph return(0); 25216763Sralph return(1); 25316763Sralph } 25416763Sralph 25516763Sralph read_number(fn) 25616763Sralph char *fn; 25716763Sralph { 25816763Sralph char lin[80]; 25916763Sralph register FILE *fp; 26016763Sralph 26116763Sralph if ((fp = fopen(fn, "r")) == NULL) 26216763Sralph return (0); 26316763Sralph if (fgets(lin, 80, fp) == NULL) { 26416763Sralph fclose(fp); 26516763Sralph return (0); 26616763Sralph } 26716763Sralph fclose(fp); 26816763Sralph return (atoi(lin)); 26916763Sralph } 27016763Sralph 27116763Sralph /* 27212115Sralph * Remove all the files associated with the current job being transfered. 27312115Sralph */ 27416763Sralph rcleanup() 27512115Sralph { 27612115Sralph 27712115Sralph if (tfname[0]) 27812115Sralph (void) unlink(tfname); 27912115Sralph if (dfname) 28012115Sralph do { 28112115Sralph do 28212115Sralph (void) unlink(dfname); 28316938Sralph while (dfname[2]-- != 'A'); 28416938Sralph dfname[2] = 'z'; 28516938Sralph } while (dfname[0]-- != 'd'); 28612115Sralph } 28712115Sralph 28816763Sralph frecverr(msg, a1, a2) 28912115Sralph char *msg; 29012115Sralph { 29116763Sralph rcleanup(); 29216763Sralph syslog(LOG_ERR, msg, a1, a2); 29312115Sralph putchar('\1'); /* return error code */ 29412115Sralph exit(1); 29512115Sralph } 296