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: }

Defined functions

chksize defined in line 248; used 2 times
find_dev defined in line 77; used 2 times
frecverr defined in line 303; used 12 times
noresponse defined in line 233; used 1 times
rcleanup defined in line 288; used 6 times
read_number defined in line 269; used 1 times
  • in line 66
readfile defined in line 188; used 2 times
readjob defined in line 111; used 1 times
  • in line 73
recvjob defined in line 30; used 1 times

Defined variables

ddev defined in line 25; used 4 times
dfd defined in line 26; used 8 times
dfname defined in line 23; used 8 times
minfree defined in line 24; used 2 times
sccsid defined in line 8; never used
tfname defined in line 22; used 9 times

Defined macros

ack defined in line 20; used 3 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1603
Valid CSS Valid XHTML 1.0 Strict