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

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

unix.superglobalmegacorp.com

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