Annotation of 43BSD/usr.lib/lpr/recvjob.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)recvjob.c  5.4 (Berkeley) 6/6/86";
                      9: #endif not lint
                     10: 
                     11: /*
                     12:  * Receive printer jobs from the network, queue them and
                     13:  * start the printer daemon.
                     14:  */
                     15: 
                     16: #include "lp.h"
                     17: #include <sys/fs.h>
                     18: 
                     19: char   *sp = "";
                     20: #define ack()  (void) write(1, sp, 1);
                     21: 
                     22: char    tfname[40];            /* tmp copy of cf before linking */
                     23: char    dfname[40];            /* data files */
                     24: int    minfree;                /* keep at least minfree blocks available */
                     25: char   *ddev;                  /* disk device (for checking free space) */
                     26: int    dfd;                    /* file system device descriptor */
                     27: 
                     28: char   *find_dev();
                     29: 
                     30: recvjob()
                     31: {
                     32:        struct stat stb;
                     33:        char *bp = pbuf;
                     34:        int status, rcleanup();
                     35: 
                     36:        /*
                     37:         * Perform lookup for printer name or abbreviation
                     38:         */
                     39:        if ((status = pgetent(line, printer)) < 0)
                     40:                frecverr("cannot open printer description file");
                     41:        else if (status == 0)
                     42:                frecverr("unknown printer %s", printer);
                     43:        if ((LF = pgetstr("lf", &bp)) == NULL)
                     44:                LF = DEFLOGF;
                     45:        if ((SD = pgetstr("sd", &bp)) == NULL)
                     46:                SD = DEFSPOOL;
                     47:        if ((LO = pgetstr("lo", &bp)) == NULL)
                     48:                LO = DEFLOCK;
                     49: 
                     50:        (void) close(2);                        /* set up log file */
                     51:        if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
                     52:                syslog(LOG_ERR, "%s: %m", LF);
                     53:                (void) open("/dev/null", O_WRONLY);
                     54:        }
                     55: 
                     56:        if (chdir(SD) < 0)
                     57:                frecverr("%s: %s: %m", printer, SD);
                     58:        if (stat(LO, &stb) == 0) {
                     59:                if (stb.st_mode & 010) {
                     60:                        /* queue is disabled */
                     61:                        putchar('\1');          /* return error code */
                     62:                        exit(1);
                     63:                }
                     64:        } else if (stat(SD, &stb) < 0)
                     65:                frecverr("%s: %s: %m", printer, SD);
                     66:        minfree = read_number("minfree");
                     67:        ddev = find_dev(stb.st_dev, S_IFBLK);
                     68:        if ((dfd = open(ddev, O_RDONLY)) < 0)
                     69:                syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
                     70:        signal(SIGTERM, rcleanup);
                     71:        signal(SIGPIPE, rcleanup);
                     72: 
                     73:        if (readjob())
                     74:                printjob();
                     75: }
                     76: 
                     77: char *
                     78: find_dev(dev, type)
                     79:        register dev_t dev;
                     80:        register int type;
                     81: {
                     82:        register DIR *dfd = opendir("/dev");
                     83:        struct direct *dir;
                     84:        struct stat stb;
                     85:        char devname[MAXNAMLEN+6];
                     86:        char *dp;
                     87: 
                     88:        strcpy(devname, "/dev/");
                     89:        while ((dir = readdir(dfd))) {
                     90:                strcpy(devname + 5, dir->d_name);
                     91:                if (stat(devname, &stb))
                     92:                        continue;
                     93:                if ((stb.st_mode & S_IFMT) != type)
                     94:                        continue;
                     95:                if (dev == stb.st_rdev) {
                     96:                        closedir(dfd);
                     97:                        dp = (char *)malloc(strlen(devname)+1);
                     98:                        strcpy(dp, devname);
                     99:                        return(dp);
                    100:                }
                    101:        }
                    102:        closedir(dfd);
                    103:        frecverr("cannot find device %d, %d", major(dev), minor(dev));
                    104:        /*NOTREACHED*/
                    105: }
                    106: 
                    107: /*
                    108:  * Read printer jobs sent by lpd and copy them to the spooling directory.
                    109:  * Return the number of jobs successfully transfered.
                    110:  */
                    111: readjob()
                    112: {
                    113:        register int size, nfiles;
                    114:        register char *cp;
                    115: 
                    116:        ack();
                    117:        nfiles = 0;
                    118:        for (;;) {
                    119:                /*
                    120:                 * Read a command to tell us what to do
                    121:                 */
                    122:                cp = line;
                    123:                do {
                    124:                        if ((size = read(1, cp, 1)) != 1) {
                    125:                                if (size < 0)
                    126:                                        frecverr("%s: Lost connection",printer);
                    127:                                return(nfiles);
                    128:                        }
                    129:                } while (*cp++ != '\n');
                    130:                *--cp = '\0';
                    131:                cp = line;
                    132:                switch (*cp++) {
                    133:                case '\1':      /* cleanup because data sent was bad */
                    134:                        rcleanup();
                    135:                        continue;
                    136: 
                    137:                case '\2':      /* read cf file */
                    138:                        size = 0;
                    139:                        while (*cp >= '0' && *cp <= '9')
                    140:                                size = size * 10 + (*cp++ - '0');
                    141:                        if (*cp++ != ' ')
                    142:                                break;
                    143:                        /*
                    144:                         * host name has been authenticated, we use our
                    145:                         * view of the host name since we may be passed
                    146:                         * something different than what gethostbyaddr()
                    147:                         * returns
                    148:                         */
                    149:                        strcpy(cp + 6, from);
                    150:                        strcpy(tfname, cp);
                    151:                        tfname[0] = 't';
                    152:                        if (!chksize(size)) {
                    153:                                (void) write(1, "\2", 1);
                    154:                                continue;
                    155:                        }
                    156:                        if (!readfile(tfname, size)) {
                    157:                                rcleanup();
                    158:                                continue;
                    159:                        }
                    160:                        if (link(tfname, cp) < 0)
                    161:                                frecverr("%s: %m", tfname);
                    162:                        (void) unlink(tfname);
                    163:                        tfname[0] = '\0';
                    164:                        nfiles++;
                    165:                        continue;
                    166: 
                    167:                case '\3':      /* read df file */
                    168:                        size = 0;
                    169:                        while (*cp >= '0' && *cp <= '9')
                    170:                                size = size * 10 + (*cp++ - '0');
                    171:                        if (*cp++ != ' ')
                    172:                                break;
                    173:                        if (!chksize(size)) {
                    174:                                (void) write(1, "\2", 1);
                    175:                                continue;
                    176:                        }
                    177:                        strcpy(dfname, cp);
                    178:                        (void) readfile(dfname, size);
                    179:                        continue;
                    180:                }
                    181:                frecverr("protocol screwup");
                    182:        }
                    183: }
                    184: 
                    185: /*
                    186:  * Read files send by lpd and copy them to the spooling directory.
                    187:  */
                    188: readfile(file, size)
                    189:        char *file;
                    190:        int size;
                    191: {
                    192:        register char *cp;
                    193:        char buf[BUFSIZ];
                    194:        register int i, j, amt;
                    195:        int fd, err;
                    196: 
                    197:        fd = open(file, O_WRONLY|O_CREAT, FILMOD);
                    198:        if (fd < 0)
                    199:                frecverr("%s: %m", file);
                    200:        ack();
                    201:        err = 0;
                    202:        for (i = 0; i < size; i += BUFSIZ) {
                    203:                amt = BUFSIZ;
                    204:                cp = buf;
                    205:                if (i + amt > size)
                    206:                        amt = size - i;
                    207:                do {
                    208:                        j = read(1, cp, amt);
                    209:                        if (j <= 0)
                    210:                                frecverr("Lost connection");
                    211:                        amt -= j;
                    212:                        cp += j;
                    213:                } while (amt > 0);
                    214:                amt = BUFSIZ;
                    215:                if (i + amt > size)
                    216:                        amt = size - i;
                    217:                if (write(fd, buf, amt) != amt) {
                    218:                        err++;
                    219:                        break;
                    220:                }
                    221:        }
                    222:        (void) close(fd);
                    223:        if (err)
                    224:                frecverr("%s: write error", file);
                    225:        if (noresponse()) {             /* file sent had bad data in it */
                    226:                (void) unlink(file);
                    227:                return(0);
                    228:        }
                    229:        ack();
                    230:        return(1);
                    231: }
                    232: 
                    233: noresponse()
                    234: {
                    235:        char resp;
                    236: 
                    237:        if (read(1, &resp, 1) != 1)
                    238:                frecverr("Lost connection");
                    239:        if (resp == '\0')
                    240:                return(0);
                    241:        return(1);
                    242: }
                    243: 
                    244: /*
                    245:  * Check to see if there is enough space on the disk for size bytes.
                    246:  * 1 == OK, 0 == Not OK.
                    247:  */
                    248: chksize(size)
                    249:        int size;
                    250: {
                    251:        struct stat stb;
                    252:        register char *ddev;
                    253:        int spacefree;
                    254:        struct fs fs;
                    255: 
                    256:        if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0)
                    257:                return(1);
                    258:        if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
                    259:                return(1);
                    260:        spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag +
                    261:                fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) *
                    262:                        fs.fs_fsize / 1024;
                    263:        size = (size + 1023) / 1024;
                    264:        if (minfree + size > spacefree)
                    265:                return(0);
                    266:        return(1);
                    267: }
                    268: 
                    269: read_number(fn)
                    270:        char *fn;
                    271: {
                    272:        char lin[80];
                    273:        register FILE *fp;
                    274: 
                    275:        if ((fp = fopen(fn, "r")) == NULL)
                    276:                return (0);
                    277:        if (fgets(lin, 80, fp) == NULL) {
                    278:                fclose(fp);
                    279:                return (0);
                    280:        }
                    281:        fclose(fp);
                    282:        return (atoi(lin));
                    283: }
                    284: 
                    285: /*
                    286:  * Remove all the files associated with the current job being transfered.
                    287:  */
                    288: rcleanup()
                    289: {
                    290: 
                    291:        if (tfname[0])
                    292:                (void) unlink(tfname);
                    293:        if (dfname[0])
                    294:                do {
                    295:                        do
                    296:                                (void) unlink(dfname);
                    297:                        while (dfname[2]-- != 'A');
                    298:                        dfname[2] = 'z';
                    299:                } while (dfname[0]-- != 'd');
                    300:        dfname[0] = '\0';
                    301: }
                    302: 
                    303: frecverr(msg, a1, a2)
                    304:        char *msg;
                    305: {
                    306:        rcleanup();
                    307:        syslog(LOG_ERR, msg, a1, a2);
                    308:        putchar('\1');          /* return error code */
                    309:        exit(1);
                    310: }

unix.superglobalmegacorp.com

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