Annotation of 42BSD/usr.lib/lpr/printjob.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)printjob.c 4.14 (Berkeley) 8/18/83";
                      3: #endif
                      4: 
                      5: /*
                      6:  * printjob -- print jobs in the queue.
                      7:  *
                      8:  *     NOTE: the lock file is used to pass information to lpq and lprm.
                      9:  *     it does not need to be removed because file locks are dynamic.
                     10:  */
                     11: 
                     12: #include "lp.h"
                     13: 
                     14: #define DORETURN       0               /* absorb fork error */
                     15: #define DOABORT                1               /* abort if dofork fails */
                     16: 
                     17: static char    title[80];              /* ``pr'' title */
                     18: static FILE    *cfp;                   /* control file */
                     19: static int     pfd;                    /* printer file descriptor */
                     20: static int     ofd;                    /* output filter file descriptor */
                     21: static int     lfd;                    /* lock file descriptor */
                     22: static int     pid;                    /* pid of lpd process */
                     23: static int     prchild;                /* id of pr process */
                     24: static int     child;                  /* id of any filters */
                     25: static int     ofilter;                /* id of output filter, if any */
                     26: static int     tof;                    /* true if at top of form */
                     27: static int     count;                  /* Number of files actually printed */
                     28: static int     remote;                 /* true if sending files to remote */
                     29: 
                     30: static char    fromhost[32];           /* user's host machine */
                     31: static char    logname[32];            /* user's login name */
                     32: static char    jobname[32];            /* job or file name */
                     33: static char    class[32];              /* classification field */
                     34: static char    width[10] = "-w";       /* page width in characters */
                     35: static char    length[10] = "-l";      /* page length in lines */
                     36: static char    pxwidth[10] = "-x";     /* page width in pixels */
                     37: static char    pxlength[10] = "-y";    /* page length in pixels */
                     38: static char    indent[10] = "-i0";     /* indentation size in characters */
                     39: 
                     40: printjob()
                     41: {
                     42:        struct stat stb;
                     43:        register struct queue *q, **qp;
                     44:        struct queue **queue;
                     45:        register int i, nitems;
                     46:        long pidoff;
                     47:        extern int onintr();
                     48: 
                     49:        init();                                 /* set up capabilities */
                     50:        (void) write(1, "", 1);                 /* ack that daemon is started */
                     51:        (void) close(1);                        /* set up log file */
                     52:        (void) close(2);
                     53:        if (open(LF, O_WRONLY|O_APPEND) < 0)
                     54:                (void) open("/dev/null", O_WRONLY);
                     55:        dup(1);
                     56:        pid = getpid();                         /* for use with lprm */
                     57:        setpgrp(0, pid);
                     58:        signal(SIGHUP, onintr);
                     59:        signal(SIGINT, onintr);
                     60:        signal(SIGQUIT, onintr);
                     61:        signal(SIGTERM, onintr);
                     62: 
                     63:        /*
                     64:         * uses short form file names
                     65:         */
                     66:        if (chdir(SD) < 0) {
                     67:                log("cannot chdir to %s", SD);
                     68:                exit(1);
                     69:        }
                     70:        if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
                     71:                exit(0);                /* printing disabled */
                     72:        lfd = open(LO, O_WRONLY|O_CREAT, 0644);
                     73:        if (lfd < 0) {
                     74:                log("cannot create %s", LO);
                     75:                exit(1);
                     76:        }
                     77:        if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
                     78:                if (errno == EWOULDBLOCK)       /* active deamon present */
                     79:                        exit(0);
                     80:                log("cannot lock %s", LO);
                     81:                exit(1);
                     82:        }
                     83:        ftruncate(lfd, 0);
                     84:        /*
                     85:         * write process id for others to know
                     86:         */
                     87:        sprintf(line, "%u\n", pid);
                     88:        pidoff = i = strlen(line);
                     89:        if (write(lfd, line, i) != i) {
                     90:                log("cannot write daemon pid");
                     91:                exit(1);
                     92:        }
                     93:        /*
                     94:         * search the spool directory for work and sort by queue order.
                     95:         */
                     96:        if ((nitems = getq(&queue)) < 0) {
                     97:                log("can't scan spool directory %s", SD);
                     98:                exit(1);
                     99:        }
                    100:        if (nitems == 0)                /* no work to do */
                    101:                exit(0);
                    102:        if (stb.st_mode & 01) {         /* reset queue flag */
                    103:                if (fchmod(lfd, stb.st_mode & 0776) < 0)
                    104:                        log("cannot chmod %s", LO);
                    105:        }
                    106:        openpr();                       /* open printer or remote */
                    107: again:
                    108:        /*
                    109:         * we found something to do now do it --
                    110:         *    write the name of the current control file into the lock file
                    111:         *    so the spool queue program can tell what we're working on
                    112:         */
                    113:        for (qp = queue; nitems--; free((char *) q)) {
                    114:                q = *qp++;
                    115:                if (stat(q->q_name, &stb) < 0)
                    116:                        continue;
                    117:        restart:
                    118:                (void) lseek(lfd, pidoff, 0);
                    119:                (void) sprintf(line, "%s\n", q->q_name);
                    120:                i = strlen(line);
                    121:                if (write(lfd, line, i) != i)
                    122:                        log("can't write (%d) control file name", errno);
                    123:                if (!remote)
                    124:                        i = printit(q->q_name);
                    125:                else
                    126:                        i = sendit(q->q_name);
                    127:                /*
                    128:                 * Check to see if we are supposed to stop printing or
                    129:                 * if we are to rebuild the queue.
                    130:                 */
                    131:                if (fstat(lfd, &stb) == 0) {
                    132:                        if (stb.st_mode & 0100)
                    133:                                goto done;
                    134:                        if (stb.st_mode & 01) {
                    135:                                for (free((char *) q); nitems--; free((char *) q))
                    136:                                        q = *qp++;
                    137:                                if (fchmod(lfd, stb.st_mode & 0776) < 0)
                    138:                                        log("cannot chmod %s", LO);
                    139:                                break;
                    140:                        }
                    141:                }
                    142:                if (i == 0)             /* file ok and printed */
                    143:                        count++;
                    144:                else if (i > 0) {       /* try reprinting the job */
                    145:                        log("restarting");
                    146:                        if (ofilter > 0) {
                    147:                                kill(ofilter, SIGCONT); /* to be sure */
                    148:                                (void) close(ofd);
                    149:                                while ((i = wait(0)) > 0 && i != ofilter)
                    150:                                        ;
                    151:                                ofilter = 0;
                    152:                        }
                    153:                        (void) close(pfd);      /* close printer */
                    154:                        (void) lseek(lfd, pidoff, 0);
                    155:                        if (write(lfd, "\n", 1) != 1)
                    156:                                log("can't write (%d) control file name", errno);
                    157:                        openpr();               /* try to reopen printer */
                    158:                        goto restart;
                    159:                }
                    160:        }
                    161:        free((char *) queue);
                    162:        /*
                    163:         * search the spool directory for more work.
                    164:         */
                    165:        if ((nitems = getq(&queue)) < 0) {
                    166:                log("can't scan spool directory %s", SD);
                    167:                exit(1);
                    168:        }
                    169:        if (nitems == 0) {              /* no more work to do */
                    170:        done:
                    171:                if (count > 0) {        /* Files actually printed */
                    172:                        if (!SF && !tof)
                    173:                                (void) write(ofd, FF, strlen(FF));
                    174:                        if (TR != NULL)         /* output trailer */
                    175:                                (void) write(ofd, TR, strlen(TR));
                    176:                }
                    177:                exit(0);
                    178:        }
                    179:        goto again;
                    180: }
                    181: 
                    182: char   fonts[4][50];   /* fonts for troff */
                    183: 
                    184: static char ifonts[4][18] = {
                    185:        "/usr/lib/vfont/R",
                    186:        "/usr/lib/vfont/I",
                    187:        "/usr/lib/vfont/B",
                    188:        "/usr/lib/vfont/S"
                    189: };
                    190: 
                    191: /*
                    192:  * The remaining part is the reading of the control file (cf)
                    193:  * and performing the various actions.
                    194:  * Returns 0 if everthing was OK, 1 if we should try to reprint the job and
                    195:  * -1 if a non-recoverable error occured.
                    196:  */
                    197: static
                    198: printit(file)
                    199:        char *file;
                    200: {
                    201:        register int i;
                    202:        int bombed = 0;
                    203: 
                    204:        /*
                    205:         * open control file
                    206:         */
                    207:        if ((cfp = fopen(file, "r")) == NULL) {
                    208:                log("control file (%s) open failure <errno = %d>", file, errno);
                    209:                return(0);
                    210:        }
                    211:        /*
                    212:         * Reset troff fonts.
                    213:         */
                    214:        for (i = 0; i < 4; i++)
                    215:                strcpy(fonts[i], ifonts[i]);
                    216: 
                    217:        /*
                    218:         *      read the control file for work to do
                    219:         *
                    220:         *      file format -- first character in the line is a command
                    221:         *      rest of the line is the argument.
                    222:         *      valid commands are:
                    223:         *
                    224:         *              J -- "job name" on banner page
                    225:         *              C -- "class name" on banner page
                    226:         *              L -- "literal" user's name to print on banner
                    227:         *              T -- "title" for pr
                    228:         *              H -- "host name" of machine where lpr was done
                    229:         *              P -- "person" user's login name
                    230:         *              I -- "indent" amount to indent output
                    231:         *              f -- "file name" name of text file to print
                    232:         *              l -- "file name" text file with control chars
                    233:         *              p -- "file name" text file to print with pr(1)
                    234:         *              t -- "file name" troff(1) file to print
                    235:         *              n -- "file name" ditroff(1) file to print
                    236:         *              d -- "file name" dvi file to print
                    237:         *              g -- "file name" plot(1G) file to print
                    238:         *              v -- "file name" plain raster file to print
                    239:         *              c -- "file name" cifplot file to print
                    240:         *              1 -- "R font file" for troff
                    241:         *              2 -- "I font file" for troff
                    242:         *              3 -- "B font file" for troff
                    243:         *              4 -- "S font file" for troff
                    244:         *              N -- "name" of file (used by lpq)
                    245:         *              U -- "unlink" name of file to remove
                    246:         *                    (after we print it. (Pass 2 only)).
                    247:         *              M -- "mail" to user when done printing
                    248:         *
                    249:         *      getline reads a line and expands tabs to blanks
                    250:         */
                    251: 
                    252:        /* pass 1 */
                    253: 
                    254:        while (getline(cfp))
                    255:                switch (line[0]) {
                    256:                case 'H':
                    257:                        strcpy(fromhost, line+1);
                    258:                        if (class[0] == '\0')
                    259:                                strcpy(class, line+1);
                    260:                        continue;
                    261: 
                    262:                case 'P':
                    263:                        strcpy(logname, line+1);
                    264:                        if (RS) {                       /* restricted */
                    265:                                if (getpwnam(logname) == (struct passwd *)0) {
                    266:                                        bombed = 2;
                    267:                                        sendmail(bombed);
                    268:                                        goto pass2;
                    269:                                }
                    270:                        }
                    271:                        continue;
                    272: 
                    273:                case 'J':
                    274:                        if (line[1] != '\0')
                    275:                                strcpy(jobname, line+1);
                    276:                        else
                    277:                                strcpy(jobname, " ");
                    278:                        continue;
                    279: 
                    280:                case 'C':
                    281:                        if (line[1] != '\0')
                    282:                                strcpy(class, line+1);
                    283:                        else if (class[0] == '\0')
                    284:                                gethostname(class, sizeof (class));
                    285:                        continue;
                    286: 
                    287:                case 'T':       /* header title for pr */
                    288:                        strcpy(title, line+1);
                    289:                        continue;
                    290: 
                    291:                case 'L':       /* identification line */
                    292:                        if (!SH)
                    293:                                banner(line+1, jobname);
                    294:                        continue;
                    295: 
                    296:                case '1':       /* troff fonts */
                    297:                case '2':
                    298:                case '3':
                    299:                case '4':
                    300:                        if (line[1] != '\0')
                    301:                                strcpy(fonts[line[0]-'1'], line+1);
                    302:                        continue;
                    303: 
                    304:                case 'W':       /* page width */
                    305:                        strcpy(width+2, line+1);
                    306:                        continue;
                    307: 
                    308:                case 'I':       /* indent amount */
                    309:                        strcpy(indent+2, line+1);
                    310:                        continue;
                    311: 
                    312:                default:        /* some file to print */
                    313:                        if ((i = print(line[0], line+1)) > 0) {
                    314:                                (void) fclose(cfp);
                    315:                                return(1);
                    316:                        } else if (i < 0)
                    317:                                bombed = 1;
                    318:                        title[0] = '\0';
                    319:                        continue;
                    320: 
                    321:                case 'N':
                    322:                case 'U':
                    323:                case 'M':
                    324:                        continue;
                    325:                }
                    326: 
                    327:        /* pass 2 */
                    328: 
                    329: pass2:
                    330:        fseek(cfp, 0L, 0);
                    331:        while (getline(cfp))
                    332:                switch (line[0]) {
                    333:                case 'M':
                    334:                        if (bombed != 2)                /* already sent if 2 */
                    335:                                sendmail(bombed);
                    336:                        continue;
                    337: 
                    338:                case 'U':
                    339:                        (void) unlink(line+1);
                    340:                }
                    341:        /*
                    342:         * clean-up incase another control file exists
                    343:         */
                    344:        (void) fclose(cfp);
                    345:        (void) unlink(file);
                    346:        return(bombed ? -1 : 0);
                    347: }
                    348: 
                    349: /*
                    350:  * Print a file.
                    351:  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
                    352:  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
                    353:  * 0 if all is well.
                    354:  * Note: all filters take stdin as the file, stdout as the printer,
                    355:  * stderr as the log file, and must not ignore SIGINT.
                    356:  */
                    357: static
                    358: print(format, file)
                    359:        int format;
                    360:        char *file;
                    361: {
                    362:        register int n, fi, fo;
                    363:        register char *prog;
                    364:        char *av[15], buf[BUFSIZ];
                    365:        int pid, p[2], stopped = 0;
                    366:        union wait status;
                    367: 
                    368:        if ((fi = open(file, O_RDONLY)) < 0) {
                    369:                log("%s: open failure <errno = %d>", file, errno);
                    370:                return(-1);
                    371:        }
                    372:        if (!SF && !tof) {              /* start on a fresh page */
                    373:                (void) write(ofd, FF, strlen(FF));
                    374:                tof = 1;
                    375:        }
                    376:        if (IF == NULL && (format == 'f' || format == 'l')) {
                    377:                tof = 0;
                    378:                while ((n = read(fi, buf, BUFSIZ)) > 0)
                    379:                        if (write(ofd, buf, n) != n) {
                    380:                                (void) close(fi);
                    381:                                return(1);
                    382:                        }
                    383:                (void) close(fi);
                    384:                return(0);
                    385:        }
                    386:        switch (format) {
                    387:        case 'p':       /* print file using 'pr' */
                    388:                if (IF == NULL) {       /* use output filter */
                    389:                        prog = PR;
                    390:                        av[0] = "pr";
                    391:                        av[1] = width;
                    392:                        av[2] = length;
                    393:                        av[3] = "-h";
                    394:                        av[4] = *title ? title : " ";
                    395:                        av[5] = 0;
                    396:                        fo = ofd;
                    397:                        goto start;
                    398:                }
                    399:                pipe(p);
                    400:                if ((prchild = dofork(DORETURN)) == 0) {        /* child */
                    401:                        dup2(fi, 0);            /* file is stdin */
                    402:                        dup2(p[1], 1);          /* pipe is stdout */
                    403:                        for (n = 3; n < NOFILE; n++)
                    404:                                (void) close(n);
                    405:                        execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
                    406:                        log("cannot execl %s", PR);
                    407:                        exit(2);
                    408:                }
                    409:                (void) close(p[1]);             /* close output side */
                    410:                (void) close(fi);
                    411:                if (prchild < 0) {
                    412:                        prchild = 0;
                    413:                        (void) close(p[0]);
                    414:                        return(-1);
                    415:                }
                    416:                fi = p[0];                      /* use pipe for input */
                    417:        case 'f':       /* print plain text file */
                    418:                prog = IF;
                    419:                av[1] = width;
                    420:                av[2] = length;
                    421:                av[3] = indent;
                    422:                n = 4;
                    423:                break;
                    424:        case 'l':       /* like 'f' but pass control characters */
                    425:                prog = IF;
                    426:                av[1] = "-c";
                    427:                av[2] = width;
                    428:                av[3] = length;
                    429:                av[4] = indent;
                    430:                n = 5;
                    431:                break;
                    432:        case 'r':       /* print a fortran text file */
                    433:                prog = RF;
                    434:                av[1] = width;
                    435:                av[2] = length;
                    436:                n = 3;
                    437:                break;
                    438:        case 't':       /* print troff output */
                    439:        case 'n':       /* print ditroff output */
                    440:        case 'd':       /* print tex output */
                    441:                (void) unlink(".railmag");
                    442:                if ((fo = creat(".railmag", FILMOD)) < 0) {
                    443:                        log("cannot create .railmag");
                    444:                        (void) unlink(".railmag");
                    445:                } else {
                    446:                        for (n = 0; n < 4; n++) {
                    447:                                if (fonts[n][0] != '/')
                    448:                                        (void) write(fo, "/usr/lib/vfont/", 15);
                    449:                                (void) write(fo, fonts[n], strlen(fonts[n]));
                    450:                                (void) write(fo, "\n", 1);
                    451:                        }
                    452:                        (void) close(fo);
                    453:                }
                    454:                prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
                    455:                av[1] = pxwidth;
                    456:                av[2] = pxlength;
                    457:                n = 3;
                    458:                break;
                    459:        case 'c':       /* print cifplot output */
                    460:                prog = CF;
                    461:                av[1] = pxwidth;
                    462:                av[2] = pxlength;
                    463:                n = 3;
                    464:                break;
                    465:        case 'g':       /* print plot(1G) output */
                    466:                prog = GF;
                    467:                av[1] = pxwidth;
                    468:                av[2] = pxlength;
                    469:                n = 3;
                    470:                break;
                    471:        case 'v':       /* print raster output */
                    472:                prog = VF;
                    473:                av[1] = pxwidth;
                    474:                av[2] = pxlength;
                    475:                n = 3;
                    476:                break;
                    477:        default:
                    478:                (void) close(fi);
                    479:                log("illegal format character '%c'", format);
                    480:                return(-1);
                    481:        }
                    482:        if ((av[0] = rindex(prog, '/')) != NULL)
                    483:                av[0]++;
                    484:        else
                    485:                av[0] = prog;
                    486:        av[n++] = "-n";
                    487:        av[n++] = logname;
                    488:        av[n++] = "-h";
                    489:        av[n++] = fromhost;
                    490:        av[n++] = AF;
                    491:        av[n] = 0;
                    492:        fo = pfd;
                    493:        if (ofilter > 0) {              /* stop output filter */
                    494:                write(ofd, "\031\1", 2);
                    495:                while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
                    496:                        ;
                    497:                if (status.w_stopval != WSTOPPED) {
                    498:                        (void) close(fi);
                    499:                        log("output filter died (%d)", status.w_retcode);
                    500:                        return(1);
                    501:                }
                    502:                stopped++;
                    503:        }
                    504: start:
                    505:        if ((child = dofork(DORETURN)) == 0) {  /* child */
                    506:                dup2(fi, 0);
                    507:                dup2(fo, 1);
                    508:                for (n = 3; n < NOFILE; n++)
                    509:                        (void) close(n);
                    510:                execv(prog, av);
                    511:                log("cannot execl %s", prog);
                    512:                exit(2);
                    513:        }
                    514:        (void) close(fi);
                    515:        if (child < 0)
                    516:                status.w_retcode = 100;
                    517:        else
                    518:                while ((pid = wait(&status)) > 0 && pid != child)
                    519:                        ;
                    520:        child = 0;
                    521:        prchild = 0;
                    522:        if (stopped) {          /* restart output filter */
                    523:                if (kill(ofilter, SIGCONT) < 0) {
                    524:                        log("cannot restart output filter");
                    525:                        exit(1);
                    526:                }
                    527:        }
                    528:        tof = 0;
                    529:        if (!WIFEXITED(status) || status.w_retcode > 1) {
                    530:                log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode);
                    531:                return(-1);
                    532:        } else if (status.w_retcode == 1)
                    533:                return(1);
                    534:        tof = 1;
                    535:        return(0);
                    536: }
                    537: 
                    538: /*
                    539:  * Send the daemon control file (cf) and any data files.
                    540:  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
                    541:  * 0 if all is well.
                    542:  */
                    543: static
                    544: sendit(file)
                    545:        char *file;
                    546: {
                    547:        register int linelen, err = 0;
                    548:        char last[132];
                    549: 
                    550:        /*
                    551:         * open control file
                    552:         */
                    553:        if ((cfp = fopen(file, "r")) == NULL) {
                    554:                log("control file (%s) open failure <errno = %d>", file, errno);
                    555:                return(0);
                    556:        }
                    557:        /*
                    558:         *      read the control file for work to do
                    559:         *
                    560:         *      file format -- first character in the line is a command
                    561:         *      rest of the line is the argument.
                    562:         *      commands of interest are:
                    563:         *
                    564:         *            a-z -- "file name" name of file to print
                    565:         *              U -- "unlink" name of file to remove
                    566:         *                    (after we print it. (Pass 2 only)).
                    567:         */
                    568: 
                    569:        /*
                    570:         * pass 1
                    571:         */
                    572:        while (getline(cfp)) {
                    573:        again:
                    574:                if (line[0] >= 'a' && line[0] <= 'z') {
                    575:                        strcpy(last, line);
                    576:                        while (linelen = getline(cfp))
                    577:                                if (strcmp(last, line))
                    578:                                        break;
                    579:                        if ((err = sendfile('\3', last+1)) > 0) {
                    580:                                (void) fclose(cfp);
                    581:                                return(1);
                    582:                        } else if (err)
                    583:                                break;
                    584:                        if (linelen)
                    585:                                goto again;
                    586:                        break;
                    587:                }
                    588:        }
                    589:        if (!err && sendfile('\2', file) > 0) {
                    590:                (void) fclose(cfp);
                    591:                return(1);
                    592:        }
                    593:        /*
                    594:         * pass 2
                    595:         */
                    596:        fseek(cfp, 0L, 0);
                    597:        while (getline(cfp))
                    598:                if (line[0] == 'U')
                    599:                        (void) unlink(line+1);
                    600:        /*
                    601:         * clean-up incase another control file exists
                    602:         */
                    603:        (void) fclose(cfp);
                    604:        (void) unlink(file);
                    605:        return(0);
                    606: }
                    607: 
                    608: /*
                    609:  * Send a data file to the remote machine and spool it.
                    610:  * Return positive if we should try resending.
                    611:  */
                    612: static
                    613: sendfile(type, file)
                    614:        char type, *file;
                    615: {
                    616:        register int f, i, amt;
                    617:        struct stat stb;
                    618:        char buf[BUFSIZ];
                    619:        int sizerr;
                    620: 
                    621:        if ((f = open(file, O_RDONLY)) < 0 || fstat(f, &stb) < 0) {
                    622:                log("file (%s) open failure <errno = %d>", file, errno);
                    623:                return(-1);
                    624:        }
                    625:        (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
                    626:        amt = strlen(buf);
                    627:        if (write(pfd, buf, amt) != amt) {
                    628:                (void) close(f);
                    629:                return(1);
                    630:        }
                    631:        if (noresponse()) {
                    632:                (void) close(f);
                    633:                return(1);
                    634:        }
                    635:        sizerr = 0;
                    636:        for (i = 0; i < stb.st_size; i += BUFSIZ) {
                    637:                amt = BUFSIZ;
                    638:                if (i + amt > stb.st_size)
                    639:                        amt = stb.st_size - i;
                    640:                if (sizerr == 0 && read(f, buf, amt) != amt)
                    641:                        sizerr = 1;
                    642:                if (write(pfd, buf, amt) != amt) {
                    643:                        (void) close(f);
                    644:                        return(1);
                    645:                }
                    646:        }
                    647:        (void) close(f);
                    648:        if (sizerr) {
                    649:                log("%s: changed size", file);
                    650:                (void) write(pfd, "\1", 1);  /* tell recvjob to ignore this file */
                    651:                return(-1);
                    652:        }
                    653:        if (write(pfd, "", 1) != 1)
                    654:                return(1);
                    655:        if (noresponse())
                    656:                return(1);
                    657:        return(0);
                    658: }
                    659: 
                    660: /*
                    661:  * Check to make sure there have been no errors and that both programs
                    662:  * are in sync with eachother.
                    663:  * Return non-zero if the connection was lost.
                    664:  */
                    665: static
                    666: noresponse()
                    667: {
                    668:        char resp;
                    669: 
                    670:        if (read(pfd, &resp, 1) != 1 || resp != '\0') {
                    671:                log("lost connection or error in recvjob");
                    672:                return(1);
                    673:        }
                    674:        return(0);
                    675: }
                    676: 
                    677: /*
                    678:  * Banner printing stuff
                    679:  */
                    680: static
                    681: banner(name1, name2)
                    682:        char *name1, *name2;
                    683: {
                    684:        time_t tvec;
                    685:        extern char *ctime();
                    686: 
                    687:        time(&tvec);
                    688:        if (!SF && !tof)
                    689:                (void) write(ofd, FF, strlen(FF));
                    690:        if (SB) {       /* short banner only */
                    691:                if (class[0]) {
                    692:                        (void) write(ofd, class, strlen(class));
                    693:                        (void) write(ofd, ":", 1);
                    694:                }
                    695:                (void) write(ofd, name1, strlen(name1));
                    696:                (void) write(ofd, "  Job: ", 7);
                    697:                (void) write(ofd, name2, strlen(name2));
                    698:                (void) write(ofd, "  Date: ", 8);
                    699:                (void) write(ofd, ctime(&tvec), 24);
                    700:                (void) write(ofd, "\n", 1);
                    701:        } else {        /* normal banner */
                    702:                (void) write(ofd, "\n\n\n", 3);
                    703:                scan_out(ofd, name1, '\0');
                    704:                (void) write(ofd, "\n\n", 2);
                    705:                scan_out(ofd, name2, '\0');
                    706:                if (class[0]) {
                    707:                        (void) write(ofd,"\n\n\n",3);
                    708:                        scan_out(ofd, class, '\0');
                    709:                }
                    710:                (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
                    711:                (void) write(ofd, name2, strlen(name2));
                    712:                (void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
                    713:                (void) write(ofd, ctime(&tvec), 24);
                    714:                (void) write(ofd, "\n", 1);
                    715:        }
                    716:        if (!SF)
                    717:                (void) write(ofd, FF, strlen(FF));
                    718:        tof = 1;
                    719: }
                    720: 
                    721: static char *
                    722: scnline(key, p, c)
                    723:        register char key, *p;
                    724:        char c;
                    725: {
                    726:        register scnwidth;
                    727: 
                    728:        for (scnwidth = WIDTH; --scnwidth;) {
                    729:                key <<= 1;
                    730:                *p++ = key & 0200 ? c : BACKGND;
                    731:        }
                    732:        return (p);
                    733: }
                    734: 
                    735: #define TRC(q) (((q)-' ')&0177)
                    736: 
                    737: static
                    738: scan_out(scfd, scsp, dlm)
                    739:        int scfd;
                    740:        char *scsp, dlm;
                    741: {
                    742:        register char *strp;
                    743:        register nchrs, j;
                    744:        char outbuf[LINELEN+1], *sp, c, cc;
                    745:        int d, scnhgt;
                    746:        extern char scnkey[][HEIGHT];   /* in lpdchar.c */
                    747: 
                    748:        for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
                    749:                strp = &outbuf[0];
                    750:                sp = scsp;
                    751:                for (nchrs = 0; ; ) {
                    752:                        d = dropit(c = TRC(cc = *sp++));
                    753:                        if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
                    754:                                for (j = WIDTH; --j;)
                    755:                                        *strp++ = BACKGND;
                    756:                        else
                    757:                                strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
                    758:                        if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
                    759:                                break;
                    760:                        *strp++ = BACKGND;
                    761:                        *strp++ = BACKGND;
                    762:                }
                    763:                while (*--strp == BACKGND && strp >= outbuf)
                    764:                        ;
                    765:                strp++;
                    766:                *strp++ = '\n'; 
                    767:                (void) write(scfd, outbuf, strp-outbuf);
                    768:        }
                    769: }
                    770: 
                    771: static
                    772: dropit(c)
                    773:        char c;
                    774: {
                    775:        switch(c) {
                    776: 
                    777:        case TRC('_'):
                    778:        case TRC(';'):
                    779:        case TRC(','):
                    780:        case TRC('g'):
                    781:        case TRC('j'):
                    782:        case TRC('p'):
                    783:        case TRC('q'):
                    784:        case TRC('y'):
                    785:                return (DROP);
                    786: 
                    787:        default:
                    788:                return (0);
                    789:        }
                    790: }
                    791: 
                    792: /*
                    793:  * sendmail ---
                    794:  *   tell people about job completion
                    795:  */
                    796: static
                    797: sendmail(bombed)
                    798:        int bombed;
                    799: {
                    800:        static int p[2];
                    801:        register int i;
                    802:        int stat;
                    803:        register char *cp;
                    804:        char buf[100];
                    805: 
                    806:        pipe(p);
                    807:        if ((stat = dofork(DORETURN)) == 0) {           /* child */
                    808:                dup2(p[0], 0);
                    809:                for (i = 3; i < NOFILE; i++)
                    810:                        (void) close(i);
                    811:                if ((cp = rindex(MAIL, '/')) != NULL)
                    812:                        cp++;
                    813:                else
                    814:                        cp = MAIL;
                    815:                sprintf(buf, "%s@%s", line+1, fromhost);
                    816:                execl(MAIL, cp, buf, 0);
                    817:                exit(0);
                    818:        } else if (stat > 0) {                          /* parent */
                    819:                dup2(p[1], 1);
                    820:                printf("To: %s@%s\n", line+1, fromhost);
                    821:                printf("Subject: printer job\n\n");
                    822:                printf("Your printer job ");
                    823:                if (*jobname)
                    824:                        printf("(%s) ", jobname);
                    825:                switch (bombed) {
                    826:                case 0:
                    827:                        printf("\ncompleted successfully\n");
                    828:                        break;
                    829:                default:
                    830:                case 1:
                    831:                        printf("\ncould not be printed\n");
                    832:                        break;
                    833:                case 2:
                    834:                        printf("\ncould not be printed without an account on %s\n", host);
                    835:                        break;
                    836:                }
                    837:                fflush(stdout);
                    838:                (void) close(1);
                    839:        }
                    840:        (void) close(p[0]);
                    841:        (void) close(p[1]);
                    842:        wait(&stat);
                    843: }
                    844: 
                    845: /*
                    846:  * dofork - fork with retries on failure
                    847:  */
                    848: static
                    849: dofork(action)
                    850:        int action;
                    851: {
                    852:        register int i, pid;
                    853: 
                    854:        for (i = 0; i < 20; i++) {
                    855:                if ((pid = fork()) < 0) {
                    856:                        sleep((unsigned)(i*i));
                    857:                        continue;
                    858:                }
                    859:                /*
                    860:                 * Child should run as daemon instead of root
                    861:                 */
                    862:                if (pid == 0)
                    863:                        setuid(DU);
                    864:                return(pid);
                    865:        }
                    866:        log("can't fork");
                    867: 
                    868:        switch (action) {
                    869:        case DORETURN:
                    870:                return (-1);
                    871:        default:
                    872:                log("bad action (%d) to dofork", action);
                    873:                /*FALL THRU*/
                    874:        case DOABORT:
                    875:                exit(1);
                    876:        }
                    877:        /*NOTREACHED*/
                    878: }
                    879: 
                    880: /*
                    881:  * Cleanup child processes when a signal is caught.
                    882:  */
                    883: static
                    884: onintr()
                    885: {
                    886:        kill(0, SIGINT);
                    887:        if (ofilter > 0)
                    888:                kill(ofilter, SIGCONT);
                    889:        while (wait(0) > 0)
                    890:                ;
                    891:        exit(0);
                    892: }
                    893: 
                    894: static
                    895: init()
                    896: {
                    897:        int status;
                    898: 
                    899:        if ((status = pgetent(line, printer)) < 0)
                    900:                fatal("can't open printer description file");
                    901:        else if (status == 0)
                    902:                fatal("unknown printer");
                    903:        if ((LP = pgetstr("lp", &bp)) == NULL)
                    904:                LP = DEFDEVLP;
                    905:        if ((RP = pgetstr("rp", &bp)) == NULL)
                    906:                RP = DEFLP;
                    907:        if ((LO = pgetstr("lo", &bp)) == NULL)
                    908:                LO = DEFLOCK;
                    909:        if ((ST = pgetstr("st", &bp)) == NULL)
                    910:                ST = DEFSTAT;
                    911:        if ((LF = pgetstr("lf", &bp)) == NULL)
                    912:                LF = DEFLOGF;
                    913:        if ((SD = pgetstr("sd", &bp)) == NULL)
                    914:                SD = DEFSPOOL;
                    915:        if ((DU = pgetnum("du")) < 0)
                    916:                DU = DEFUID;
                    917:        if ((FF = pgetstr("ff", &bp)) == NULL)
                    918:                FF = DEFFF;
                    919:        if ((PW = pgetnum("pw")) < 0)
                    920:                PW = DEFWIDTH;
                    921:        sprintf(&width[2], "%d", PW);
                    922:        if ((PL = pgetnum("pl")) < 0)
                    923:                PL = DEFLENGTH;
                    924:        sprintf(&length[2], "%d", PL);
                    925:        if ((PX = pgetnum("px")) < 0)
                    926:                PX = 0;
                    927:        sprintf(&pxwidth[2], "%d", PX);
                    928:        if ((PY = pgetnum("py")) < 0)
                    929:                PY = 0;
                    930:        sprintf(&pxlength[2], "%d", PY);
                    931:        RM = pgetstr("rm", &bp);
                    932:        AF = pgetstr("af", &bp);
                    933:        OF = pgetstr("of", &bp);
                    934:        IF = pgetstr("if", &bp);
                    935:        RF = pgetstr("rf", &bp);
                    936:        TF = pgetstr("tf", &bp);
                    937:        NF = pgetstr("nf", &bp);
                    938:        DF = pgetstr("df", &bp);
                    939:        GF = pgetstr("gf", &bp);
                    940:        VF = pgetstr("vf", &bp);
                    941:        CF = pgetstr("cf", &bp);
                    942:        TR = pgetstr("tr", &bp);
                    943:        RS = pgetflag("rs");
                    944:        SF = pgetflag("sf");
                    945:        SH = pgetflag("sh");
                    946:        SB = pgetflag("sb");
                    947:        RW = pgetflag("rw");
                    948:        BR = pgetnum("br");
                    949:        if ((FC = pgetnum("fc")) < 0)
                    950:                FC = 0;
                    951:        if ((FS = pgetnum("fs")) < 0)
                    952:                FS = 0;
                    953:        if ((XC = pgetnum("xc")) < 0)
                    954:                XC = 0;
                    955:        if ((XS = pgetnum("xs")) < 0)
                    956:                XS = 0;
                    957:        tof = !pgetflag("fo");
                    958: }
                    959: 
                    960: /*
                    961:  * Acquire line printer or remote connection.
                    962:  */
                    963: static
                    964: openpr()
                    965: {
                    966:        register int i, n;
                    967: 
                    968:        if (*LP) {
                    969:                for (i = 1; ; i = i < 32 ? i << 1 : i) {
                    970:                        pfd = open(LP, RW ? O_RDWR : O_WRONLY);
                    971:                        if (pfd >= 0)
                    972:                                break;
                    973:                        if (errno == ENOENT) {
                    974:                                log("cannot open %s", LP);
                    975:                                exit(1);
                    976:                        }
                    977:                        if (i == 1)
                    978:                                status("waiting for %s to become ready (offline ?)", printer);
                    979:                        sleep(i);
                    980:                }
                    981:                if (isatty(pfd))
                    982:                        setty();
                    983:                status("%s is ready and printing", printer);
                    984:        } else if (RM != NULL) {
                    985:                for (i = 1; ; i = i < 512 ? i << 1 : i) {
                    986:                        pfd = getport(RM);
                    987:                        if (pfd >= 0) {
                    988:                                (void) sprintf(line, "\2%s\n", RP);
                    989:                                n = strlen(line);
                    990:                                if (write(pfd, line, n) != n)
                    991:                                        break;
                    992:                                if (noresponse())
                    993:                                        (void) close(pfd);
                    994:                                else
                    995:                                        break;
                    996:                        }
                    997:                        if (i == 1)
                    998:                                status("waiting for %s to come up", RM);
                    999:                        sleep(i);
                   1000:                }
                   1001:                status("sending to %s", RM);
                   1002:                remote = 1;
                   1003:        } else {
                   1004:                log("no line printer device or remote machine name");
                   1005:                exit(1);
                   1006:        }
                   1007:        /*
                   1008:         * Start up an output filter, if needed.
                   1009:         */
                   1010:        if (OF) {
                   1011:                int p[2];
                   1012:                char *cp;
                   1013: 
                   1014:                pipe(p);
                   1015:                if ((ofilter = dofork(DOABORT)) == 0) { /* child */
                   1016:                        dup2(p[0], 0);          /* pipe is std in */
                   1017:                        dup2(pfd, 1);           /* printer is std out */
                   1018:                        for (i = 3; i < NOFILE; i++)
                   1019:                                (void) close(i);
                   1020:                        if ((cp = rindex(OF, '/')) == NULL)
                   1021:                                cp = OF;
                   1022:                        else
                   1023:                                cp++;
                   1024:                        execl(OF, cp, width, length, 0);
                   1025:                        log("can't execl output filter %s", OF);
                   1026:                        exit(1);
                   1027:                }
                   1028:                (void) close(p[0]);             /* close input side */
                   1029:                ofd = p[1];                     /* use pipe for output */
                   1030:        } else {
                   1031:                ofd = pfd;
                   1032:                ofilter = 0;
                   1033:        }
                   1034: }
                   1035: 
                   1036: struct bauds {
                   1037:        int     baud;
                   1038:        int     speed;
                   1039: } bauds[] = {
                   1040:        50,     B50,
                   1041:        75,     B75,
                   1042:        110,    B110,
                   1043:        134,    B134,
                   1044:        150,    B150,
                   1045:        200,    B200,
                   1046:        300,    B300,
                   1047:        600,    B600,
                   1048:        1200,   B1200,
                   1049:        1800,   B1800,
                   1050:        2400,   B2400,
                   1051:        4800,   B4800,
                   1052:        9600,   B9600,
                   1053:        19200,  EXTA,
                   1054:        38400,  EXTB,
                   1055:        0,      0
                   1056: };
                   1057: 
                   1058: /*
                   1059:  * setup tty lines.
                   1060:  */
                   1061: static
                   1062: setty()
                   1063: {
                   1064:        struct sgttyb ttybuf;
                   1065:        register struct bauds *bp;
                   1066: 
                   1067:        if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
                   1068:                log("cannot set exclusive-use");
                   1069:                exit(1);
                   1070:        }
                   1071:        if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
                   1072:                log("cannot get tty parameters");
                   1073:                exit(1);
                   1074:        }
                   1075:        if (BR > 0) {
                   1076:                for (bp = bauds; bp->baud; bp++)
                   1077:                        if (BR == bp->baud)
                   1078:                                break;
                   1079:                if (!bp->baud) {
                   1080:                        log("illegal baud rate %d", BR);
                   1081:                        exit(1);
                   1082:                }
                   1083:                ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
                   1084:        }
                   1085:        ttybuf.sg_flags &= ~FC;
                   1086:        ttybuf.sg_flags |= FS;
                   1087:        if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
                   1088:                log("cannot set tty parameters");
                   1089:                exit(1);
                   1090:        }
                   1091:        if (XC) {
                   1092:                if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
                   1093:                        log("cannot set local tty parameters");
                   1094:                        exit(1);
                   1095:                }
                   1096:        }
                   1097:        if (XS) {
                   1098:                if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
                   1099:                        log("cannot set local tty parameters");
                   1100:                        exit(1);
                   1101:                }
                   1102:        }
                   1103: }
                   1104: 
                   1105: /*VARARGS1*/
                   1106: static
                   1107: status(msg, a1, a2, a3)
                   1108:        char *msg;
                   1109: {
                   1110:        register int fd;
                   1111:        char buf[BUFSIZ];
                   1112: 
                   1113:        umask(0);
                   1114:        fd = open(ST, O_WRONLY|O_CREAT, 0664);
                   1115:        if (fd < 0 || flock(fd, LOCK_EX) < 0)
                   1116:                fatal("cannot create status file");
                   1117:        ftruncate(fd, 0);
                   1118:        sprintf(buf, msg, a1, a2, a3);
                   1119:        strcat(buf, "\n");
                   1120:        (void) write(fd, buf, strlen(buf));
                   1121:        (void) close(fd);
                   1122: }

unix.superglobalmegacorp.com

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