|
|
1.1 ! root 1: #include <stddef.h> ! 2: #include <stdarg.h> ! 3: #include <signal.h> ! 4: #include <fio.h> ! 5: #include <errno.h> ! 6: #include <time.h> ! 7: ! 8: /* for Tenth Edition systems */ ! 9: #define LP "/usr/bin/lp" ! 10: /* for System V or BSD systems */ ! 11: /* #define LP "/v/bin/lp" */ ! 12: ! 13: #define LPDAEMONLOG "/tmp/lpdaemonl" ! 14: ! 15: #define ARGSIZ 4096 ! 16: #define NAMELEN 11 ! 17: ! 18: char argvstr[ARGSIZ]; /* arguments after parsing */ ! 19: char *argvals[ARGSIZ/2+1]; /* pointers to arguments after parsing */ ! 20: int ascnt = 0, argcnt = 0; /* number of arguments parsed */ ! 21: /* for 'stuff' gleened from lpr cntrl file */ ! 22: struct jobinfo { ! 23: char user[NAMELEN+1]; ! 24: char host[NAMELEN+1]; ! 25: } *getjobinfo(); ! 26: ! 27: #define MIN(a,b) ((a<b)?a:b) ! 28: ! 29: #define CPYFIELD(src, dst) { while (*(src)!=' ' && *(src)!='\t' && *(src)!='\r' && *(src)!='\n' && *(src)!='\0') *(dst)++ = *(src)++; } ! 30: ! 31: #define ACK() write(1, "", 1) ! 32: #define NAK() write(1, "\001", 1) ! 33: ! 34: #define LNBFSZ 4096 ! 35: char lnbuf[LNBFSZ]; ! 36: int readline(); ! 37: ! 38: #define RDSIZE 512 ! 39: char jobbuf[RDSIZE]; ! 40: ! 41: int datafd[400], cntrlfd; ! 42: ! 43: void ! 44: error(int level, char *s1, ...) ! 45: { ! 46: int fd; ! 47: long thetime; ! 48: char *chartime; ! 49: va_list ap; ! 50: char *args[8]; ! 51: int argno = 0; ! 52: ! 53: if((fd=open(LPDAEMONLOG, 1))<0) { ! 54: if(errno==ENOENT) { ! 55: if((fd=creat(LPDAEMONLOG, 0664))<0) { ! 56: return; /* hopeless, just go away mad */ ! 57: } ! 58: } else return; ! 59: } ! 60: ! 61: lseek(fd, 0, 2); ! 62: if (level == 0) { ! 63: time(&thetime); ! 64: chartime = ctime(&thetime); ! 65: fprint(fd, "%.15s ", &(chartime[4])); ! 66: } ! 67: va_start(ap, s1); ! 68: while(args[argno++] = va_arg(ap, char*)); ! 69: va_end(ap); ! 70: fprint(fd, s1, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); ! 71: close(fd); ! 72: return; ! 73: } ! 74: ! 75: void ! 76: forklp(int inputfd) ! 77: { ! 78: int i, cpid; ! 79: char *bp, *cp; ! 80: char logent[LNBFSZ]; ! 81: ! 82: /* log this call to lp */ ! 83: cp = logent; ! 84: for (i=1; i<argcnt; i++) { ! 85: bp = argvals[i]; ! 86: if (cp+strlen(bp)+1 < logent+LNBFSZ-1) { ! 87: CPYFIELD(bp, cp); ! 88: *cp++ = ' '; ! 89: } ! 90: } ! 91: *--cp = '\n'; ! 92: *++cp = '\0'; ! 93: error(0, logent); ! 94: switch((cpid=fork())){ ! 95: case -1: ! 96: error(0, "fork error\n"); ! 97: exit(2); ! 98: case 0: ! 99: if (inputfd != 0) ! 100: dup2(inputfd, 0); ! 101: dup2(1, 2); ! 102: lseek(0, 0L, 0); ! 103: execvp(LP, argvals); ! 104: error(0, "exec failed\n"); ! 105: exit(3); ! 106: default: ! 107: while(wait((int *)0) != cpid); ! 108: } ! 109: } ! 110: ! 111: int ! 112: getfiles(void) ! 113: { ! 114: char *ap; ! 115: int filecnt, bsize, rv; ! 116: ! 117: filecnt = 0; ! 118: /* get a line, hopefully containing a ctrl char, size, and name */ ! 119: for(;;) { ! 120: ap = lnbuf; ! 121: do { ! 122: if ((rv = read(1, ap, 1)) != 1) { ! 123: if (rv < 0) { ! 124: error(0, "Lost connection\n"); ! 125: NAK(); ! 126: } ! 127: return(filecnt); ! 128: } ! 129: } while (*ap != '\n' && (ap++ - lnbuf < LNBFSZ - 1)); ! 130: *ap = '\0'; ! 131: ap = lnbuf; ! 132: switch(*ap++) { ! 133: case '\1': /* cleanup - data sent was bad (whatever that means) */ ! 134: break; ! 135: case '\2': /* read control file */ ! 136: bsize = atoi(ap); ! 137: cntrlfd = tmpfile(); ! 138: if (readfile(cntrlfd, bsize) < 0) { ! 139: close(cntrlfd); ! 140: NAK(); ! 141: return(0); ! 142: } ! 143: return(filecnt); ! 144: case '\3': /* read data file */ ! 145: bsize = atoi(ap); ! 146: datafd[filecnt] = tmpfile(); ! 147: readfile(datafd[filecnt++], bsize); ! 148: break; ! 149: default: ! 150: error(0, "protocol error <%d>\n", *(ap-1)); ! 151: NAK(); ! 152: } ! 153: } ! 154: } ! 155: ! 156: int ! 157: readfile(int outfd, int bsize) ! 158: { ! 159: int bcnt, rv; ! 160: ! 161: ACK(); ! 162: for(bcnt=bsize ; bcnt > 0; bcnt -= rv) { ! 163: if((rv=read(0, jobbuf, MIN(bcnt,RDSIZE))) < 0) { ! 164: error(0, "error reading input\n"); ! 165: exit(4); ! 166: } else if((write(outfd, jobbuf, rv)) != rv) { ! 167: error(0, "error writing temp file\n"); ! 168: exit(5); ! 169: } ! 170: } ! 171: if (((rv=read(0, jobbuf, 1))==1) && (*jobbuf=='\0')) { ! 172: ACK(); ! 173: return(outfd); ! 174: } ! 175: error(0, "received bad status <%d> from sender ", *jobbuf); ! 176: error(1, "rv=%d\n", rv); ! 177: NAK(); ! 178: return(-1); ! 179: } ! 180: ! 181: struct jobinfo * ! 182: getjobinfo(int fd) ! 183: { ! 184: register char *ap; ! 185: int rv; ! 186: static struct jobinfo info; ! 187: ! 188: if (lseek(fd, 0L, 0) < 0) { ! 189: error(0, "error seeking in temp file\n"); ! 190: exit(7); ! 191: } ! 192: /* the following strings should be < NAMELEN or else they will not ! 193: * be null terminated. ! 194: */ ! 195: strncpy(info.user, "daemon", NAMELEN); ! 196: strncpy(info.host, "nowhere", NAMELEN); ! 197: /* there may be a space after the name and host. It will be filtered out ! 198: * by CPYFIELD. ! 199: */ ! 200: while ((rv=readline(fd)) != 0) { ! 201: ap = lnbuf; ! 202: ap[rv-1] = '\0'; /* remove newline from string */ ! 203: switch (*ap) { ! 204: case 'H': ! 205: strncpy(info.host, &ap[1], NAMELEN); ! 206: break; ! 207: case 'P': ! 208: strncpy(info.user, &ap[1], NAMELEN); ! 209: break; ! 210: } ! 211: } ! 212: return(&info); ! 213: } ! 214: ! 215: int ! 216: tmpfile(void) ! 217: { ! 218: static tindx = 0; ! 219: char tmpf[20]; ! 220: int crtfd, tmpfd; ! 221: ! 222: sprint(tmpf, "/tmp/lp%d.%d", getpid(), tindx++); ! 223: if((crtfd=creat(tmpf, 0666)) < 0) { ! 224: error(0, "cannot create temp file %s\n", tmpf); ! 225: NAK(); ! 226: exit(3); ! 227: } ! 228: if((tmpfd=open(tmpf, 2)) < 0) { ! 229: error(0, "cannot open temp file %s\n", tmpf); ! 230: NAK(); ! 231: exit(3); ! 232: } ! 233: close(crtfd); ! 234: /* unlink(tmpf); /* comment out for debugging */ ! 235: return(tmpfd); ! 236: } ! 237: ! 238: int ! 239: readline(int inpfd) ! 240: { ! 241: register char *ap; ! 242: register int i; ! 243: ! 244: ap = lnbuf; ! 245: i = 0; ! 246: do { ! 247: if (read(inpfd, ap, 1) != 1) { ! 248: error(0, "read error\n"); ! 249: break; ! 250: } ! 251: i++; ! 252: } while (*ap++ != '\n' && (i < LNBFSZ - 2)); ! 253: if (*(ap-1) != '\n') { ! 254: *(ap-1) = '\n'; ! 255: i++; ! 256: } ! 257: *ap = '\0'; ! 258: return(i); ! 259: } ! 260: ! 261: main() ! 262: { ! 263: char *ap, *bp, *cp, *savbufpnt; ! 264: int i, rv, saveflg, savargcnt; ! 265: struct jobinfo *jinfop; ! 266: ! 267: signal(1, SIG_IGN); ! 268: cp = argvstr; ! 269: /* setup argv[0] for exec */ ! 270: argvals[argcnt++] = cp; ! 271: for (bp = LP, i = 0; (*bp != '\0') && (i < ARGSIZ-1); *cp++ = *bp++, i++); ! 272: *cp++ = '\0'; ! 273: /* get the first line sent and parse it as arguments for lp */ ! 274: ap = lnbuf; ! 275: i = 0; ! 276: do { ! 277: if ((rv = read(0, ap, 1)) != 1) { ! 278: if (rv < 0) { ! 279: error(0, "Lost connection\n"); ! 280: } ! 281: exit(1); ! 282: } ! 283: i++; ! 284: } while (*ap++ != '\n' && (i < LNBFSZ - 2)); ! 285: if (*(ap-1) != '\n') { ! 286: *(ap-1) = '\n'; ! 287: i++; ! 288: } ! 289: *ap = '\0'; ! 290: ap = lnbuf; ! 291: if (ap == (char *)0) { ! 292: error(0, "cannot read arg line\n"); ! 293: NAK(); ! 294: exit(1); ! 295: } ! 296: bp = ap; ! 297: /* setup the remaining arguments */ ! 298: /* check for BSD style request */ ! 299: /* ^A, ^B, ^C, ^D, ^E (for BSD lpr) */ ! 300: switch (*bp) { ! 301: case '\001': ! 302: case '\003': ! 303: case '\004': ! 304: bp++; /* drop the ctrl character from the input */ ! 305: argvals[argcnt++] = cp; ! 306: *cp++ = '-'; *cp++ = 'q'; *cp++ = '\0'; /* -q */ ! 307: argvals[argcnt++] = cp; ! 308: *cp++ = '-'; *cp++ = 'd'; /* -d */ ! 309: CPYFIELD(bp, cp); /* printer */ ! 310: *cp++ = '\0'; ! 311: break; ! 312: case '\002': ! 313: bp++; /* drop the ctrl character from the input */ ! 314: argvals[argcnt++] = cp; ! 315: *cp++ = '-'; *cp++ = 'd'; /* -d */ ! 316: CPYFIELD(bp, cp); /* printer */ ! 317: *cp++ = '\0'; ! 318: ACK(); ! 319: savargcnt = argcnt; ! 320: savbufpnt = cp; ! 321: while ((rv=getfiles())) { ! 322: jinfop = getjobinfo(cntrlfd); ! 323: close(cntrlfd); ! 324: argcnt = savargcnt; ! 325: cp = savbufpnt; ! 326: argvals[argcnt++] = cp; ! 327: *cp++ = '-'; *cp++ = 'M'; /* -M */ ! 328: bp = jinfop->host; ! 329: CPYFIELD(bp, cp); /* host name */ ! 330: *cp++ = '\0'; ! 331: argvals[argcnt++] = cp; ! 332: *cp++ = '-'; *cp++ = 'u'; /* -u */ ! 333: bp = jinfop->user; ! 334: CPYFIELD(bp, cp); /* user name */ ! 335: *cp++ = '\0'; ! 336: for(i=0;i<rv;i++) ! 337: forklp(datafd[i]); ! 338: } ! 339: exit(0); ! 340: case '\005': ! 341: bp++; /* drop the ctrl character from the input */ ! 342: argvals[argcnt++] = cp; ! 343: *cp++ = '-'; *cp++ = 'k'; *cp++ = '\0'; /* -k */ ! 344: argvals[argcnt++] = cp; ! 345: *cp++ = '-'; *cp++ = 'd'; /* -d */ ! 346: CPYFIELD(bp, cp); /* printer */ ! 347: *cp++ = '\0'; ! 348: argvals[argcnt++] = cp; ! 349: *cp++ = '-'; *cp++ = 'u'; /* -u */ ! 350: CPYFIELD(bp, cp); /* username */ ! 351: *cp++ = '\0'; ! 352: datafd[0] = tmpfile(); ! 353: fprint(datafd[0], "%s\n", bp); ! 354: break; ! 355: default: ! 356: /* otherwise get my lp arguments */ ! 357: do { ! 358: /* move to next non-white space */ ! 359: while (*bp==' '||*bp=='\t') ! 360: ++bp; ! 361: if (*bp=='\n') continue; ! 362: /* only accept arguments beginning with - ! 363: * this is done to prevent the printing of ! 364: * local files from the destination host ! 365: */ ! 366: if (*bp=='-') { ! 367: argvals[argcnt++] = cp; ! 368: saveflg = 1; ! 369: } else ! 370: saveflg = 0; ! 371: /* move to next white space copying text to argument buffer */ ! 372: while (*bp!=' ' && *bp!='\t' && *bp!='\n' ! 373: && *bp!='\0') { ! 374: *cp = *bp++; ! 375: cp += saveflg; ! 376: } ! 377: *cp = '\0'; ! 378: cp += saveflg; ! 379: } while (*bp!='\n'); ! 380: readline(0); ! 381: datafd[0] = tmpfile(); ! 382: error(0, "reading in %d bytes <%s>\n", atoi(lnbuf), lnbuf); ! 383: if(readfile(datafd[0], atoi(lnbuf)) < 0) { ! 384: error(0, "readfile failed\n"); ! 385: exit(7); ! 386: } ! 387: } ! 388: forklp(datafd[0]); ! 389: exit(0); ! 390: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.