Annotation of researchv10no/cmd/lp/lpdaemon.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.