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