Annotation of 43BSDTahoe/usr.lib/lpr/printjob.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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