1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #if defined(DOSCCS) && !defined(lint) 8: static char sccsid[] = "@(#)recvjob.c 5.4.1 (2.11BSD GTE) 1/1/94"; 9: #endif 10: 11: /* 12: * Receive printer jobs from the network, queue them and 13: * start the printer daemon. 14: */ 15: 16: #include "lp.h" 17: #include <sys/fs.h> 18: 19: char *sp = ""; 20: #define ack() (void) write(1, sp, 1); 21: 22: char tfname[40]; /* tmp copy of cf before linking */ 23: char dfname[40]; /* data files */ 24: long minfree; /* keep at least minfree blocks available */ 25: char *ddev; /* disk device (for checking free space) */ 26: int dfd; /* file system device descriptor */ 27: 28: char *find_dev(); 29: long read_number(), atol(); 30: 31: recvjob() 32: { 33: struct stat stb; 34: char *bp = pbuf; 35: int status, rcleanup(); 36: 37: /* 38: * Perform lookup for printer name or abbreviation 39: */ 40: if ((status = pgetent(line, printer)) < 0) 41: frecverr("cannot open printer description file"); 42: else if (status == 0) 43: frecverr("unknown printer %s", printer); 44: if ((LF = pgetstr("lf", &bp)) == NULL) 45: LF = DEFLOGF; 46: if ((SD = pgetstr("sd", &bp)) == NULL) 47: SD = DEFSPOOL; 48: if ((LO = pgetstr("lo", &bp)) == NULL) 49: LO = DEFLOCK; 50: 51: (void) close(2); /* set up log file */ 52: if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { 53: syslog(LOG_ERR, "%s: %m", LF); 54: (void) open("/dev/null", O_WRONLY); 55: } 56: 57: if (chdir(SD) < 0) 58: frecverr("%s: %s: %m", printer, SD); 59: if (stat(LO, &stb) == 0) { 60: if (stb.st_mode & 010) { 61: /* queue is disabled */ 62: putchar('\1'); /* return error code */ 63: exit(1); 64: } 65: } else if (stat(SD, &stb) < 0) 66: frecverr("%s: %s: %m", printer, SD); 67: minfree = read_number("minfree"); 68: ddev = find_dev(stb.st_dev, S_IFBLK); 69: if ((dfd = open(ddev, O_RDONLY)) < 0) 70: syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); 71: signal(SIGTERM, rcleanup); 72: signal(SIGPIPE, rcleanup); 73: 74: if (readjob()) 75: printjob(); 76: } 77: 78: char * 79: find_dev(dev, type) 80: register dev_t dev; 81: register int type; 82: { 83: register DIR *dfd = opendir("/dev"); 84: struct direct *dir; 85: struct stat stb; 86: char devname[MAXNAMLEN+6]; 87: char *dp; 88: 89: strcpy(devname, "/dev/"); 90: while ((dir = readdir(dfd))) { 91: strcpy(devname + 5, dir->d_name); 92: if (stat(devname, &stb)) 93: continue; 94: if ((stb.st_mode & S_IFMT) != type) 95: continue; 96: if (dev == stb.st_rdev) { 97: closedir(dfd); 98: dp = (char *)malloc(strlen(devname)+1); 99: strcpy(dp, devname); 100: return(dp); 101: } 102: } 103: closedir(dfd); 104: frecverr("cannot find device %d, %d", major(dev), minor(dev)); 105: /*NOTREACHED*/ 106: } 107: 108: /* 109: * Read printer jobs sent by lpd and copy them to the spooling directory. 110: * Return the number of jobs successfully transfered. 111: */ 112: readjob() 113: { 114: register nfiles; 115: long size; 116: register char *cp; 117: 118: ack(); 119: nfiles = 0; 120: for (;;) { 121: /* 122: * Read a command to tell us what to do 123: */ 124: cp = line; 125: do { 126: if ((size = read(1, cp, 1)) != 1) { 127: if (size < 0) 128: frecverr("%s: Lost connection",printer); 129: return(nfiles); 130: } 131: } while (*cp++ != '\n'); 132: *--cp = '\0'; 133: cp = line; 134: switch (*cp++) { 135: case '\1': /* cleanup because data sent was bad */ 136: rcleanup(); 137: continue; 138: 139: case '\2': /* read cf file */ 140: size = 0; 141: while (*cp >= '0' && *cp <= '9') 142: size = size * 10 + (*cp++ - '0'); 143: if (*cp++ != ' ') 144: break; 145: /* 146: * host name has been authenticated, we use our 147: * view of the host name since we may be passed 148: * something different than what gethostbyaddr() 149: * returns 150: */ 151: strcpy(cp + 6, from); 152: strcpy(tfname, cp); 153: tfname[0] = 't'; 154: if (!chksize(size)) { 155: (void) write(1, "\2", 1); 156: continue; 157: } 158: if (!readfile(tfname, size)) { 159: rcleanup(); 160: continue; 161: } 162: if (link(tfname, cp) < 0) 163: frecverr("%s: %m", tfname); 164: (void) unlink(tfname); 165: tfname[0] = '\0'; 166: nfiles++; 167: continue; 168: 169: case '\3': /* read df file */ 170: size = 0; 171: while (*cp >= '0' && *cp <= '9') 172: size = size * 10 + (*cp++ - '0'); 173: if (*cp++ != ' ') 174: break; 175: if (!chksize(size)) { 176: (void) write(1, "\2", 1); 177: continue; 178: } 179: strcpy(dfname, cp); 180: (void) readfile(dfname, size); 181: continue; 182: } 183: frecverr("protocol screwup"); 184: } 185: } 186: 187: /* 188: * Read files send by lpd and copy them to the spooling directory. 189: */ 190: readfile(file, size) 191: char *file; 192: long size; 193: { 194: register char *cp; 195: char buf[BUFSIZ]; 196: register int j, amt; 197: long i; 198: int fd, err; 199: 200: fd = open(file, O_WRONLY|O_CREAT, FILMOD); 201: if (fd < 0) 202: frecverr("%s: %m", file); 203: ack(); 204: err = 0; 205: for (i = 0; i < size; i += BUFSIZ) { 206: amt = BUFSIZ; 207: cp = buf; 208: if (i + amt > size) 209: amt = size - i; 210: do { 211: j = read(1, cp, amt); 212: if (j <= 0) 213: frecverr("Lost connection"); 214: amt -= j; 215: cp += j; 216: } while (amt > 0); 217: amt = BUFSIZ; 218: if (i + amt > size) 219: amt = size - i; 220: if (write(fd, buf, amt) != amt) { 221: err++; 222: break; 223: } 224: } 225: (void) close(fd); 226: if (err) 227: frecverr("%s: write error", file); 228: if (noresponse()) { /* file sent had bad data in it */ 229: (void) unlink(file); 230: return(0); 231: } 232: ack(); 233: return(1); 234: } 235: 236: noresponse() 237: { 238: char resp; 239: 240: if (read(1, &resp, 1) != 1) 241: frecverr("Lost connection"); 242: if (resp == '\0') 243: return(0); 244: return(1); 245: } 246: 247: /* 248: * Check to see if there is enough space on the disk for size bytes. 249: * 1 == OK, 0 == Not OK. 250: */ 251: chksize(size) 252: long size; 253: { 254: struct stat stb; 255: register char *ddev; 256: long spacefree; 257: struct fs fs; 258: 259: if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0) 260: return(1); 261: if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs) 262: return(1); 263: #ifdef pdp11 264: spacefree = fs.fs_tfree; 265: #else 266: spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag + 267: fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) * 268: fs.fs_fsize / 1024; 269: #endif 270: size = (size + 1023) / 1024; 271: if (minfree + size > spacefree) 272: return(0); 273: return(1); 274: } 275: 276: long 277: read_number(fn) 278: char *fn; 279: { 280: char lin[80]; 281: register FILE *fp; 282: 283: if ((fp = fopen(fn, "r")) == NULL) 284: return (0); 285: if (fgets(lin, 80, fp) == NULL) { 286: fclose(fp); 287: return (0); 288: } 289: fclose(fp); 290: return (atol(lin)); 291: } 292: 293: /* 294: * Remove all the files associated with the current job being transfered. 295: */ 296: rcleanup() 297: { 298: 299: if (tfname[0]) 300: (void) unlink(tfname); 301: if (dfname[0]) 302: do { 303: do 304: (void) unlink(dfname); 305: while (dfname[2]-- != 'A'); 306: dfname[2] = 'z'; 307: } while (dfname[0]-- != 'd'); 308: dfname[0] = '\0'; 309: } 310: 311: frecverr(msg, a1, a2) 312: char *msg; 313: { 314: rcleanup(); 315: syslog(LOG_ERR, msg, a1, a2); 316: putchar('\1'); /* return error code */ 317: exit(1); 318: }