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

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: }

unix.superglobalmegacorp.com

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