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