113955Ssam #ifndef lint 2*16763Sralph static char sccsid[] = "@(#)recvjob.c 4.7 (Berkeley) 07/25/84"; 313955Ssam #endif 413955Ssam 512115Sralph /* 612115Sralph * Receive printer jobs from the network, queue them and 712115Sralph * start the printer daemon. 812115Sralph */ 912115Sralph 1012115Sralph #include "lp.h" 11*16763Sralph #include <sys/fs.h> 1212115Sralph 13*16763Sralph char *sp = ""; 14*16763Sralph #define ack() (void) write(1, sp, 1); 1512115Sralph 16*16763Sralph char tfname[40]; /* tmp copy of cf before linking */ 17*16763Sralph char *dfname; /* data files */ 18*16763Sralph int minfree; /* keep at least minfree blocks available */ 19*16763Sralph char *ddev; /* disk device (for checking free space) */ 20*16763Sralph int dfd; /* file system device descriptor */ 21*16763Sralph 22*16763Sralph char *find_dev(); 23*16763Sralph 2412115Sralph recvjob() 2512115Sralph { 2612464Sralph struct stat stb; 2712115Sralph char *bp = pbuf; 28*16763Sralph int status, rcleanup(); 2912115Sralph 3012115Sralph /* 3112115Sralph * Perform lookup for printer name or abbreviation 3212115Sralph */ 3312115Sralph if ((status = pgetent(line, printer)) < 0) 34*16763Sralph frecverr("cannot open printer description file"); 3512115Sralph else if (status == 0) 36*16763Sralph frecverr("unknown printer %s", printer); 3712115Sralph if ((LF = pgetstr("lf", &bp)) == NULL) 3812115Sralph LF = DEFLOGF; 3912115Sralph if ((SD = pgetstr("sd", &bp)) == NULL) 4012115Sralph SD = DEFSPOOL; 4112464Sralph if ((LO = pgetstr("lo", &bp)) == NULL) 4212464Sralph LO = DEFLOCK; 4312115Sralph 4412115Sralph if (chdir(SD) < 0) 45*16763Sralph frecverr("%s: %s: %m", printer, SD); 46*16763Sralph if (stat(LO, &stb) == 0) { 47*16763Sralph if (stb.st_mode & 010) { 48*16763Sralph /* queue is disabled */ 49*16763Sralph putchar('\1'); /* return error code */ 50*16763Sralph exit(1); 51*16763Sralph } 52*16763Sralph } else if (stat(SD, &stb) < 0) 53*16763Sralph frecverr("%s: %s: %m", printer, SD); 54*16763Sralph minfree = read_number("minfree"); 55*16763Sralph ddev = find_dev(stb.st_dev, S_IFBLK); 56*16763Sralph if ((dfd = open(ddev, O_RDONLY)) < 0) 57*16763Sralph syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); 58*16763Sralph signal(SIGTERM, rcleanup); 59*16763Sralph signal(SIGPIPE, rcleanup); 6012115Sralph 6112115Sralph if (readjob()) 6212115Sralph printjob(); 6312115Sralph } 6412115Sralph 65*16763Sralph char * 66*16763Sralph find_dev(dev, type) 67*16763Sralph register dev_t dev; 68*16763Sralph register int type; 69*16763Sralph { 70*16763Sralph register DIR *dfd = opendir("/dev"); 71*16763Sralph struct direct *dir; 72*16763Sralph struct stat stb; 73*16763Sralph char devname[MAXNAMLEN+6]; 74*16763Sralph char *dp; 7512115Sralph 76*16763Sralph strcpy(devname, "/dev/"); 77*16763Sralph while ((dir = readdir(dfd))) { 78*16763Sralph strcpy(devname + 5, dir->d_name); 79*16763Sralph if (stat(devname, &stb)) 80*16763Sralph continue; 81*16763Sralph if ((stb.st_mode & S_IFMT) != type) 82*16763Sralph continue; 83*16763Sralph if (dev == stb.st_rdev) { 84*16763Sralph closedir(dfd); 85*16763Sralph dp = (char *)malloc(strlen(devname)+1); 86*16763Sralph strcpy(dp, devname); 87*16763Sralph return(dp); 88*16763Sralph } 89*16763Sralph } 90*16763Sralph closedir(dfd); 91*16763Sralph frecverr("cannot find device %d, %d", major(dev), minor(dev)); 92*16763Sralph /*NOTREACHED*/ 93*16763Sralph } 94*16763Sralph 9512115Sralph /* 9612115Sralph * Read printer jobs sent by lpd and copy them to the spooling directory. 9712115Sralph * Return the number of jobs successfully transfered. 9812115Sralph */ 99*16763Sralph readjob() 10012115Sralph { 10112115Sralph register int size, nfiles; 10212115Sralph register char *cp; 10312115Sralph 10412115Sralph ack(); 10512115Sralph nfiles = 0; 10612115Sralph for (;;) { 10712115Sralph /* 10812115Sralph * Read a command to tell us what to do 10912115Sralph */ 11012115Sralph cp = line; 11112115Sralph do { 11212115Sralph if ((size = read(1, cp, 1)) != 1) { 11312115Sralph if (size < 0) 114*16763Sralph frecverr("%s: Lost connection",printer); 11512115Sralph return(nfiles); 11612115Sralph } 11712115Sralph } while (*cp++ != '\n'); 11812115Sralph *--cp = '\0'; 11912115Sralph cp = line; 12012115Sralph switch (*cp++) { 12112115Sralph case '\1': /* cleanup because data sent was bad */ 122*16763Sralph rcleanup(); 12312115Sralph continue; 12412115Sralph 12512115Sralph case '\2': /* read cf file */ 12612115Sralph size = 0; 12712115Sralph while (*cp >= '0' && *cp <= '9') 12812115Sralph size = size * 10 + (*cp++ - '0'); 12912115Sralph if (*cp++ != ' ') 13012115Sralph break; 13112115Sralph strcpy(tfname, cp); 13212115Sralph tfname[0] = 't'; 133*16763Sralph if (!chksize(size)) { 134*16763Sralph (void) write(1, "\2", 1); 135*16763Sralph continue; 136*16763Sralph } 13712115Sralph if (!readfile(tfname, size)) { 138*16763Sralph rcleanup(); 13912115Sralph continue; 14012115Sralph } 14112115Sralph if (link(tfname, cp) < 0) 142*16763Sralph frecverr("%s: %m", tfname); 14312115Sralph (void) unlink(tfname); 14412115Sralph tfname[0] = '\0'; 14512115Sralph nfiles++; 14612115Sralph continue; 14712115Sralph 14812115Sralph case '\3': /* read df file */ 14912115Sralph size = 0; 15012115Sralph while (*cp >= '0' && *cp <= '9') 15112115Sralph size = size * 10 + (*cp++ - '0'); 15212115Sralph if (*cp++ != ' ') 15312115Sralph break; 154*16763Sralph if (!chksize(size)) { 155*16763Sralph (void) write(1, "\2", 1); 156*16763Sralph continue; 157*16763Sralph } 15812115Sralph (void) readfile(dfname = cp, size); 15912115Sralph continue; 16012115Sralph } 161*16763Sralph frecverr("protocol screwup"); 16212115Sralph } 16312115Sralph } 16412115Sralph 16512115Sralph /* 16612115Sralph * Read files send by lpd and copy them to the spooling directory. 16712115Sralph */ 16812115Sralph readfile(file, size) 16912115Sralph char *file; 17012115Sralph int size; 17112115Sralph { 17212115Sralph register char *cp; 17312115Sralph char buf[BUFSIZ]; 17412115Sralph register int i, j, amt; 17512115Sralph int fd, err; 17612115Sralph 17713149Ssam fd = open(file, O_WRONLY|O_CREAT, FILMOD); 17812115Sralph if (fd < 0) 179*16763Sralph frecverr("%s: %m", file); 18012115Sralph ack(); 18112115Sralph err = 0; 18212115Sralph for (i = 0; i < size; i += BUFSIZ) { 18312115Sralph amt = BUFSIZ; 18412115Sralph cp = buf; 18512115Sralph if (i + amt > size) 18612115Sralph amt = size - i; 18712115Sralph do { 18812115Sralph j = read(1, cp, amt); 18912115Sralph if (j <= 0) 190*16763Sralph frecverr("Lost connection"); 19112115Sralph amt -= j; 19212115Sralph cp += j; 19312115Sralph } while (amt > 0); 19412115Sralph amt = BUFSIZ; 19512115Sralph if (i + amt > size) 19612115Sralph amt = size - i; 19713170Sralph if (write(fd, buf, amt) != amt) { 19812115Sralph err++; 19913170Sralph break; 20013170Sralph } 20112115Sralph } 20212115Sralph (void) close(fd); 20312115Sralph if (err) 204*16763Sralph frecverr("%s: write error", file); 20512115Sralph if (noresponse()) { /* file sent had bad data in it */ 20612115Sralph (void) unlink(file); 20712115Sralph return(0); 20812115Sralph } 20912115Sralph ack(); 21012115Sralph return(1); 21112115Sralph } 21212115Sralph 21312115Sralph noresponse() 21412115Sralph { 21512115Sralph char resp; 21612115Sralph 21712115Sralph if (read(1, &resp, 1) != 1) 218*16763Sralph frecverr("Lost connection"); 21912115Sralph if (resp == '\0') 22012115Sralph return(0); 22112115Sralph return(1); 22212115Sralph } 22312115Sralph 22412115Sralph /* 225*16763Sralph * Check to see if there is enough space on the disk for size bytes. 226*16763Sralph * 1 == OK, 0 == Not OK. 227*16763Sralph */ 228*16763Sralph chksize(size) 229*16763Sralph int size; 230*16763Sralph { 231*16763Sralph struct stat stb; 232*16763Sralph register char *ddev; 233*16763Sralph int spacefree; 234*16763Sralph struct fs fs; 235*16763Sralph 236*16763Sralph if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0) 237*16763Sralph return(1); 238*16763Sralph if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs) 239*16763Sralph return(1); 240*16763Sralph spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag + 241*16763Sralph fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) * 242*16763Sralph fs.fs_fsize / 1024; 243*16763Sralph size = (size + 1023) / 1024; 244*16763Sralph if (minfree + size > spacefree) 245*16763Sralph return(0); 246*16763Sralph return(1); 247*16763Sralph } 248*16763Sralph 249*16763Sralph read_number(fn) 250*16763Sralph char *fn; 251*16763Sralph { 252*16763Sralph char lin[80]; 253*16763Sralph register FILE *fp; 254*16763Sralph 255*16763Sralph if ((fp = fopen(fn, "r")) == NULL) 256*16763Sralph return (0); 257*16763Sralph if (fgets(lin, 80, fp) == NULL) { 258*16763Sralph fclose(fp); 259*16763Sralph return (0); 260*16763Sralph } 261*16763Sralph fclose(fp); 262*16763Sralph return (atoi(lin)); 263*16763Sralph } 264*16763Sralph 265*16763Sralph /* 26612115Sralph * Remove all the files associated with the current job being transfered. 26712115Sralph */ 268*16763Sralph rcleanup() 26912115Sralph { 27012115Sralph register int i; 27112115Sralph 27212115Sralph if (tfname[0]) 27312115Sralph (void) unlink(tfname); 27412115Sralph if (dfname) 27512115Sralph do { 27612115Sralph do 27712115Sralph (void) unlink(dfname); 27812115Sralph while (dfname[i]-- != 'A'); 27912115Sralph dfname[i] = 'z'; 28012115Sralph } while (dfname[i-2]-- != 'd'); 28112115Sralph } 28212115Sralph 283*16763Sralph frecverr(msg, a1, a2) 28412115Sralph char *msg; 28512115Sralph { 286*16763Sralph rcleanup(); 287*16763Sralph syslog(LOG_ERR, msg, a1, a2); 28812115Sralph putchar('\1'); /* return error code */ 28912115Sralph exit(1); 29012115Sralph } 291