Annotation of coherent/d/bin/lpr/lpd1.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * lpd1.c
                      3:  * 12/13/90
                      4:  * The line printer spooler daemon.
                      5:  * This source produces both lpd and (compiled -DLASER) hpd.
                      6:  * NOTE: this command should be setuid to daemon.
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <sys/dir.h>
                     11: #include <pwd.h>
                     12: #include <sgtty.h>
                     13: #include <signal.h>
                     14: #include <errno.h>
                     15: 
                     16: #define DAEMON 1               /* Daemon's magic number */
                     17: #define        BANWID  10              /* Longest banner */
                     18: #define        MAXCOM  40              /* Longest comment line sent through mail */
                     19: #define        NCOM    512             /* Comment and control line buffer size */
                     20: #define        FF      014             /* Form feed */
                     21: #define        SMALL   037             /* Set small characters -- paper tiger */
                     22: #define        NORMAL  036             /* Set normal characters -- paper tiger */
                     23: 
                     24: #ifdef LASER
                     25: char   spooldir[] = "/usr/spool/hpd";
                     26: char   *printer = "/dev/rhp";
                     27: #else
                     28: char   spooldir[] = "/usr/spool/lpd";
                     29: char   *printer = "/dev/lp";
                     30: #endif
                     31: char   lockfile[] = "dpid";
                     32: 
                     33: char   *argv0;
                     34: char   obuf[BUFSIZ];
                     35: char   cfline[NCOM];           /* Control file line */
                     36: char   comment[NCOM];          /* Comment line */
                     37: FILE   *lp;
                     38: int    printing;               /* On while printing */
                     39: 
                     40: char   *lgets();
                     41: int    cancel();
                     42: int    restart();
                     43: 
                     44: main(argc, argv)
                     45: char *argv[];
                     46: {
                     47:        int fd;
                     48:        int pid;
                     49: 
                     50:        argv0 = argv[0];
                     51:        setuid(DAEMON);
                     52:        if (chdir(spooldir) < 0)
                     53:                lperr("spool directory botch");
                     54:        if ((fd = creat(lockfile, 0400)) < 0)
                     55:                exit(0);
                     56:        if (fork())
                     57:                exit(0);
                     58:        signal(SIGINT, SIG_IGN);
                     59:        signal(SIGHUP, SIG_IGN);
                     60:        signal(SIGTRAP, cancel);
                     61:        signal(SIGREST, restart);
                     62:        pid = getpid();
                     63:        write(fd, &pid, sizeof pid);
                     64:        close(fd);
                     65:        if (argc > 1)
                     66:                printer = argv[1];
                     67:        if ((lp = fopen(printer, "w")) == NULL)
                     68:                lperr( "%s: %s", printer, sys_errlist[errno]);
                     69:        ioctl(fileno(lp), TIOCEXCL, NULL);
                     70:        setbuf(lp, obuf);
                     71:        process();
                     72:        rmexit(0);
                     73: }
                     74: 
                     75: /*
                     76:  * Find work to do.
                     77:  * The basic algorithm is to
                     78:  * run down the current directory
                     79:  * looking for files whose names
                     80:  * begin with 'cf' and do the work
                     81:  * associated with each of them.
                     82:  */
                     83: process()
                     84: {
                     85:        FILE *dirfile;
                     86:        struct direct dir;
                     87:        char *r = "r";
                     88: 
                     89:        if ((dirfile = fopen(".", r)) != NULL) {
                     90:                while (fread(&dir, sizeof dir, 1, dirfile) == 1) {
                     91:                        if (dir.d_ino == 0
                     92:                         || dir.d_name[0] != 'c'
                     93:                         || dir.d_name[1] != 'f')
                     94:                                continue;
                     95:                        control(dir.d_name);
                     96:                        rewind(dirfile);
                     97:                }
                     98:                fclose(dirfile);
                     99:        }
                    100: }
                    101: 
                    102: /*
                    103:  * Do the action specified by the control
                    104:  * file.  Essentially, this must interpret
                    105:  * the control lines for such things as
                    106:  * mail notification, banners, etc.
                    107:  */
                    108: control(cfname)
                    109: register char *cfname;
                    110: {
                    111:        FILE *cfp;
                    112:        char mbuf[MAXCOM+40];
                    113:        char *message, *s;
                    114:        int state;      /* 0 to suppress header, 1 before first banner, 2 after */
                    115: 
                    116:        message = "%s: Listing complete: %.*s\n";
                    117:        if ((cfp = fopen(cfname, "r")) != NULL) {
                    118: again:
                    119:                printing = state = 1;
                    120:                while (lgets(cfline, sizeof cfline, cfp) != NULL) {
                    121:                        if (!printing)
                    122:                                message = "%s: Listing killed by order: %.*s\n";
                    123:                        else if (printing < 0) {
                    124:                                rewind(cfp);
                    125:                                putc(FF, lp);
                    126:                                goto again;
                    127:                        }
                    128:                        switch (cfline[0]) {
                    129:                        case 'A':
                    130:                                if (state)
                    131:                                        putc(FF, lp);   /* FF after banner */
                    132:                                if (print(cfline+1, -1)) {
                    133:                                        message = "%s: printer file error: %.*s\n";
                    134:                                        strcpy(comment, cfline+1);
                    135:                                }
                    136: #ifndef        LASER
                    137:                                putc(FF, lp);           /* FF after file */
                    138: #endif
                    139:                                break;
                    140: 
                    141:                        case 'B':
                    142:                                state = 0;              /* suppress header */
                    143:                                break;
                    144: 
                    145:                        case 'D':
                    146:                                strcpy(comment, cfline+1);
                    147:                                break;
                    148: 
                    149: #ifdef LASER
                    150:                        case 'E':                       /* unload fonts */
                    151:                                fprintf(lp, "\033*c0F");
                    152:                                break;
                    153: 
                    154:                        case 'F':                       /* download font */
                    155:                                for (s = cfline+1; *s != ' '; ++s)
                    156:                                        ;               /* scan to space */
                    157:                                *s++ = '\0';            /* terminate filename */
                    158:                                if (print(cfline+1, atoi(s))) {
                    159:                                        message = "%s: printer file error: %.*s\n";
                    160:                                        strcpy(comment, cfline+1);
                    161:                                }
                    162:                                break;
                    163: #endif
                    164: 
                    165:                        case 'L':
                    166:                                if (state == 0)
                    167:                                        break;
                    168:                                if (state == 1) {
                    169:                                        state = 2;
                    170:                                        fprintf(lp, "%s\n\n", cfname);
                    171:                                }
                    172:                                if (printing > 0) {
                    173:                                        cfline[BANWID+1] = '\0';
                    174: /* Paper tiger controls
                    175:                                        putc(SMALL, lp);
                    176:  */
                    177:                                        banner(cfline+1, lp);
                    178: /* Paper tiger controls
                    179:                                        putc(NORMAL, lp);
                    180:  */
                    181:                                }
                    182:                                break;
                    183: 
                    184:                        case 'M':
                    185:                                sprintf(mbuf, message, argv0, MAXCOM, comment);
                    186:                                notify(cfline+1, mbuf);
                    187:                                break;
                    188: 
                    189:                        case 'R':
                    190:                                /* Charge ID -- not used */
                    191:                                break;
                    192: 
                    193:                        case 'U':
                    194:                                unlink(cfline+1);
                    195:                                break;
                    196: 
                    197:                        default:
                    198:                                lperr("Bad control line '%s'", cfline);
                    199:                        }
                    200:                }
                    201:                fclose(cfp);
                    202:                printing = 0;
                    203:        }
                    204:        unlink(cfname);
                    205: }
                    206: 
                    207: /*
                    208:  * Routine to notify a user about
                    209:  * the completion of a transaction
                    210:  * Usually called by some daemon (e.g.
                    211:  * line printer daemon).
                    212:  * Return non-zero on failure.
                    213:  */
                    214: notify(name, msg)
                    215: char *name;
                    216: char *msg;
                    217: {
                    218:        register struct passwd *pwp;
                    219:        int pfd[2];
                    220:        register int pid, fd;
                    221:        int status;
                    222: 
                    223:        if (*name>='0' && *name<='9')
                    224:                if ((pwp = getpwuid(atoi(name))) == NULL)
                    225:                        name = NULL; else
                    226:                        name = pwp->pw_name;
                    227:        if (name==NULL || pipe(pfd)<0 || (pid = fork())<0)
                    228:                return (1);
                    229:        if (pid) {
                    230:                close(pfd[0]);
                    231:                write(pfd[1], msg, strlen(msg));
                    232:                close(pfd[1]);
                    233:                while (wait(&status) >= 0)
                    234:                        ;
                    235:        } else {
                    236:                close(pfd[1]);
                    237:                dup2(pfd[0], 0);
                    238:                close(pfd[0]);
                    239:                for (fd=3; fd<_NFILE; fd++)
                    240:                        close(fd);
                    241:                execlp("/bin/mail", "mail", name, NULL);
                    242:                return (1);
                    243:        }
                    244:        return (0);
                    245: }
                    246: 
                    247: /*
                    248:  * Cancel the listing that is printing
                    249:  * just now.
                    250:  */
                    251: cancel()
                    252: {
                    253:        signal(SIGTRAP, SIG_IGN);
                    254:        if (printing) {
                    255:                printing = 0;
                    256:                fprintf(lp, "\n\n\nListing cancelled by order\n");
                    257:        }
                    258:        signal(SIGTRAP, cancel);
                    259: }
                    260: 
                    261: /*
                    262:  * Restart the listing that
                    263:  * is running just now.
                    264:  */
                    265: restart()
                    266: {
                    267:        signal(SIGREST, SIG_IGN);
                    268:        if (printing) {
                    269:                printing = -1;
                    270:                fprintf(lp, "\n\n\nListing restarted by order\n");
                    271:        }
                    272:        signal(SIGREST, restart);
                    273: }
                    274: 
                    275: /*
                    276:   * Like fgets but no newline is put at the end
                    277:  * of the string.  Also the rest of an input
                    278:  * line is flushed on truncated strings.
                    279:  */
                    280: char *
                    281: lgets(as, lim, iop)
                    282: char *as;
                    283: register lim;
                    284: FILE *iop;
                    285: {
                    286:        register c;
                    287:        register char *s;
                    288: 
                    289:        s = as;
                    290:        while (--lim > 0 && (c = getc(iop)) != EOF)
                    291:                if ((*s++ = c) == '\n') {
                    292:                        s--;
                    293:                        break;
                    294:                }
                    295:        *s = 0;
                    296:        if (lim==0 && c!='\n')
                    297:                while ((c = getc(iop))!='\n' && c!=EOF)
                    298:                        ;
                    299:        return (c==EOF && s==as ? NULL : as);
                    300: }
                    301: 
                    302: /* VARARGS */
                    303: lperr(x)
                    304: {
                    305:        fprintf(stderr, "%s: %r\n", argv0, &x);
                    306:        rmexit(1);
                    307: }
                    308: 
                    309: /*
                    310:  * Remove lock file and exit.
                    311:  */
                    312: rmexit(s)
                    313: {
                    314:        unlink(lockfile);
                    315:        if (lp != NULL)
                    316:                fclose(lp);
                    317:        exit(s);
                    318: }
                    319: 
                    320: /* end of lpd1.c */

unix.superglobalmegacorp.com

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