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