Annotation of 43BSDTahoe/usr.lib/lpr/printjob.c, revision 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.