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 | static char *rcsid_recvjob_c = "$Id: recvjob.c,v 1.20 1998-07-20 16:04:07 danw Exp $"; |
---|
10 | #endif |
---|
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 <limits.h> |
---|
19 | |
---|
20 | #ifdef _AUX_SOURCE |
---|
21 | #include <sys/sysmacros.h> |
---|
22 | #include <ufs/ufsparam.h> |
---|
23 | #endif |
---|
24 | |
---|
25 | #if defined(SYSV) |
---|
26 | #define USE_USTAT |
---|
27 | #include <ustat.h> |
---|
28 | #else |
---|
29 | #ifdef __NetBSD__ |
---|
30 | #include <ufs/ufs/dinode.h> |
---|
31 | #include <ufs/ffs/fs.h> |
---|
32 | #else |
---|
33 | #include <ufs/fs.h> |
---|
34 | #endif |
---|
35 | #endif |
---|
36 | |
---|
37 | #ifdef PQUOTA |
---|
38 | #include "quota.h" |
---|
39 | #include <time.h> |
---|
40 | #include <sys/time.h> |
---|
41 | #endif |
---|
42 | |
---|
43 | #ifdef _IBMR2 |
---|
44 | #include <sys/select.h> |
---|
45 | #endif |
---|
46 | |
---|
47 | #if BUFSIZ != 1024 |
---|
48 | #undef BUFSIZ |
---|
49 | #define BUFSIZ 1024 |
---|
50 | #endif |
---|
51 | |
---|
52 | char *sp = ""; |
---|
53 | #define ack() (void) write(1, sp, 1); |
---|
54 | |
---|
55 | int lflag; /* should we log a trace? */ |
---|
56 | char tfname[40]; /* tmp copy of cf before linking */ |
---|
57 | char dfname[40]; /* data files */ |
---|
58 | char cfname[40]; /* control fle - fix compiler bug */ |
---|
59 | int minfree; /* keep at least minfree blocks available */ |
---|
60 | |
---|
61 | #ifdef USE_USTAT |
---|
62 | dev_t ddev; /* disk device (for checking free space) */ |
---|
63 | #else |
---|
64 | char *ddev; /* disk device (for checking free space) */ |
---|
65 | int dfd; /* file system device descriptor */ |
---|
66 | #endif |
---|
67 | |
---|
68 | #ifdef KERBEROS |
---|
69 | char tempfile[40]; /* Same size as used for cfname and tfname */ |
---|
70 | extern int kflag; |
---|
71 | #endif |
---|
72 | |
---|
73 | #ifdef _AUX_SOURCE |
---|
74 | /* They defined fds_bits correctly, but lose by not defining this */ |
---|
75 | #define FD_ZERO(p) ((p)->fds_bits[0] = 0) |
---|
76 | #define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n))) |
---|
77 | #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n))) |
---|
78 | #endif |
---|
79 | |
---|
80 | char *find_dev(); |
---|
81 | |
---|
82 | recvjob() |
---|
83 | { |
---|
84 | struct stat stb; |
---|
85 | char *bp = pbuf; |
---|
86 | int status, rcleanup(); |
---|
87 | void *old_term, *old_pipe; |
---|
88 | |
---|
89 | /* |
---|
90 | * Perform lookup for printer name or abbreviation |
---|
91 | */ |
---|
92 | if(lflag) syslog(LOG_INFO, "in recvjob"); |
---|
93 | #ifdef HESIOD |
---|
94 | if ((status = pgetent(line, printer)) <= 0) { |
---|
95 | if (pralias(alibuf, printer)) |
---|
96 | printer = alibuf; |
---|
97 | if ((status = hpgetent(line, printer)) < 1) |
---|
98 | frecverr("unknown printer %s", printer); |
---|
99 | } |
---|
100 | #else |
---|
101 | if ((status = pgetent(line, printer)) < 0) { |
---|
102 | frecverr("cannot open printer description file"); |
---|
103 | } |
---|
104 | else if (status == 0) |
---|
105 | frecverr("unknown printer %s", printer); |
---|
106 | #endif |
---|
107 | if ((LF = pgetstr("lf", &bp)) == NULL) |
---|
108 | LF = DEFLOGF; |
---|
109 | if ((SD = pgetstr("sd", &bp)) == NULL) |
---|
110 | SD = DEFSPOOL; |
---|
111 | if ((LO = pgetstr("lo", &bp)) == NULL) |
---|
112 | LO = DEFLOCK; |
---|
113 | |
---|
114 | if (((RM = pgetstr("rm", &bp)) != NULL) && strcasecmp(RM, host)) { |
---|
115 | #ifdef KERBEROS |
---|
116 | if (require_kerberos(printer) > 0) |
---|
117 | /* They are not for you */ |
---|
118 | frecverr("%s: cannot forward to kerberized spooler", |
---|
119 | printer); |
---|
120 | #endif KERBEROS |
---|
121 | SD = DEFSPOOL; |
---|
122 | } |
---|
123 | |
---|
124 | #ifdef PQUOTA |
---|
125 | RQ = pgetstr("rq", &bp); |
---|
126 | QS = pgetstr("qs", &bp); |
---|
127 | #endif |
---|
128 | #ifdef LACL |
---|
129 | AC = pgetstr("ac", &bp); |
---|
130 | PA = pgetflag("pa"); |
---|
131 | RA = pgetflag("ra"); |
---|
132 | #endif |
---|
133 | |
---|
134 | (void) close(2); /* set up log file */ |
---|
135 | if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { |
---|
136 | syslog(LOG_ERR, "%s: %m", LF); |
---|
137 | (void) open("/dev/null", O_WRONLY); |
---|
138 | } |
---|
139 | |
---|
140 | if (chdir(SD) < 0) |
---|
141 | frecverr("%s: %s: %m", printer, SD); |
---|
142 | if (stat(LO, &stb) == 0) { |
---|
143 | if (stb.st_mode & 010) { |
---|
144 | /* queue is disabled */ |
---|
145 | putchar('\1'); /* return error code */ |
---|
146 | exit(1); |
---|
147 | } |
---|
148 | } else if (stat(SD, &stb) < 0) |
---|
149 | frecverr("%s: %s: %m", printer, SD); |
---|
150 | minfree = read_number("minfree"); |
---|
151 | |
---|
152 | #ifdef USE_USTAT |
---|
153 | ddev = stb.st_dev; |
---|
154 | #else |
---|
155 | ddev = find_dev(stb.st_dev, S_IFBLK); |
---|
156 | if ((dfd = open(ddev, O_RDONLY)) < 0) |
---|
157 | syslog(LOG_WARNING, "%s: %s: %m", printer, ddev); |
---|
158 | #endif |
---|
159 | |
---|
160 | |
---|
161 | old_term = signal(SIGTERM, rcleanup); |
---|
162 | old_pipe = signal(SIGPIPE, rcleanup); |
---|
163 | |
---|
164 | if(lflag) syslog(LOG_INFO, "Reading job"); |
---|
165 | |
---|
166 | if (readjob()) |
---|
167 | { |
---|
168 | signal(SIGTERM, old_term); |
---|
169 | signal(SIGPIPE, old_pipe); |
---|
170 | |
---|
171 | if (lflag) syslog(LOG_INFO, "Printing job.."); |
---|
172 | |
---|
173 | printjob(); |
---|
174 | } |
---|
175 | |
---|
176 | } |
---|
177 | |
---|
178 | #ifndef USE_USTAT |
---|
179 | char * |
---|
180 | find_dev(dev, type) |
---|
181 | register dev_t dev; |
---|
182 | register int type; |
---|
183 | { |
---|
184 | register DIR *dfd = opendir("/dev"); |
---|
185 | #ifdef POSIX |
---|
186 | struct dirent *dir; |
---|
187 | #else |
---|
188 | struct direct *dir; |
---|
189 | #endif |
---|
190 | struct stat stb; |
---|
191 | char devname[MAXNAMLEN+6]; |
---|
192 | char *dp; |
---|
193 | |
---|
194 | strcpy(devname, "/dev/"); |
---|
195 | while ((dir = readdir(dfd))) { |
---|
196 | strcpy(devname + 5, dir->d_name); |
---|
197 | if (stat(devname, &stb)) |
---|
198 | continue; |
---|
199 | if ((stb.st_mode & S_IFMT) != type) |
---|
200 | continue; |
---|
201 | if (dev == stb.st_rdev) { |
---|
202 | closedir(dfd); |
---|
203 | dp = (char *)malloc(strlen(devname)+1); |
---|
204 | if (!dp) |
---|
205 | frecverr("out of memory while finding device %d, %d", major(dev), minor(dev)); |
---|
206 | strcpy(dp, devname); |
---|
207 | return(dp); |
---|
208 | } |
---|
209 | } |
---|
210 | closedir(dfd); |
---|
211 | frecverr("cannot find device %d, %d", major(dev), minor(dev)); |
---|
212 | /*NOTREACHED*/ |
---|
213 | } |
---|
214 | #endif /* USE_USTAT */ |
---|
215 | |
---|
216 | /* Compute the next job number */ |
---|
217 | jobnum() |
---|
218 | { |
---|
219 | FILE *jfp; |
---|
220 | int job = 0; |
---|
221 | |
---|
222 | jfp = fopen(".seq", "r"); |
---|
223 | if (jfp) { |
---|
224 | fscanf(jfp, "%d", &job); |
---|
225 | job = (job+1) % 1000; |
---|
226 | fclose(jfp); |
---|
227 | } |
---|
228 | |
---|
229 | jfp = fopen(".seq", "w"); |
---|
230 | if (jfp) { |
---|
231 | fprintf(jfp, "%d\n", job); |
---|
232 | fclose(jfp); |
---|
233 | } |
---|
234 | return job; |
---|
235 | } |
---|
236 | |
---|
237 | /* |
---|
238 | * Read printer jobs sent by lpd and copy them to the spooling directory. |
---|
239 | * Return the number of jobs successfully transfered. |
---|
240 | */ |
---|
241 | readjob() |
---|
242 | { |
---|
243 | register int size, nfiles; |
---|
244 | int n, toobig; |
---|
245 | register char *cp; |
---|
246 | #if defined(PQUOTA) || defined(LACL) |
---|
247 | char *cret; |
---|
248 | #endif |
---|
249 | #ifdef PQUOTA |
---|
250 | char *check_quota(); |
---|
251 | #endif |
---|
252 | #ifdef LACL |
---|
253 | char *check_lacl(), *check_remhost(); |
---|
254 | #endif |
---|
255 | |
---|
256 | if (lflag) syslog(LOG_INFO, "In readjob"); |
---|
257 | |
---|
258 | ack(); |
---|
259 | nfiles = 0; |
---|
260 | for (;;) { |
---|
261 | /* |
---|
262 | * Read a command to tell us what to do |
---|
263 | */ |
---|
264 | cp = line; |
---|
265 | n = 0; |
---|
266 | toobig = 0; |
---|
267 | do { |
---|
268 | if (++n >= sizeof(line)) { |
---|
269 | frecverr("%s: line too long", printer); |
---|
270 | return(nfiles); |
---|
271 | } |
---|
272 | if ((size = read(1, cp, 1)) != 1) { |
---|
273 | if (size < 0) |
---|
274 | frecverr("%s: Lost connection",printer); |
---|
275 | if (lflag) syslog(LOG_INFO, "Returning from readjobs"); |
---|
276 | return(nfiles); |
---|
277 | } |
---|
278 | } while (*cp++ != '\n'); |
---|
279 | *--cp = '\0'; |
---|
280 | cp = line; |
---|
281 | switch (*cp++) { |
---|
282 | case '\1': /* cleanup because data sent was bad */ |
---|
283 | rcleanup(); |
---|
284 | continue; |
---|
285 | |
---|
286 | case '\2': /* read cf file */ |
---|
287 | size = 0; |
---|
288 | while (*cp >= '0' && *cp <= '9') { |
---|
289 | if (size > INT_MAX/10) |
---|
290 | toobig = 1; |
---|
291 | size = size * 10 + (*cp++ - '0'); |
---|
292 | } |
---|
293 | if (*cp++ != ' ' || toobig) |
---|
294 | break; |
---|
295 | |
---|
296 | if (!isalnum(cp[0]) || !isalnum(cp[1]) || |
---|
297 | !isalnum(cp[2]) || !isalnum(cp[3]) || |
---|
298 | !isalnum(cp[4]) || !isalnum(cp[5])) { |
---|
299 | syslog(LOG_ERR, |
---|
300 | "unexpected job character in cf %d.%d.%d.%d.%d.%d", |
---|
301 | cp[0], cp[1], cp[2], cp[3], |
---|
302 | cp[4], cp[5]); |
---|
303 | break; |
---|
304 | } |
---|
305 | if (cp[0] != 'c' || cp[1] != 'f' || |
---|
306 | cp[2] != 'A' || !isxdigit(cp[3]) || |
---|
307 | !isxdigit(cp[4]) || !isxdigit(cp[5])) { |
---|
308 | syslog(LOG_NOTICE, |
---|
309 | "nonstandard job character in cf %d.%d.%d.%d.%d.%d", |
---|
310 | cp[0], cp[1], cp[2], cp[3], |
---|
311 | cp[4], cp[5]); |
---|
312 | } |
---|
313 | |
---|
314 | /* Compute local filenames. */ |
---|
315 | sprintf(cfname, "cfA%03d%s", jobnum(), from); |
---|
316 | strncpy(tfname, cp, sizeof(tfname)); |
---|
317 | tfname[sizeof(tfname) - 1] = '\0'; |
---|
318 | if (strchr(cfname, '/') || strchr(tfname, '/')) |
---|
319 | { |
---|
320 | syslog(LOG_ERR, |
---|
321 | "/ found in control or temporary file name"); |
---|
322 | break; |
---|
323 | } |
---|
324 | tfname[0] = 't'; |
---|
325 | #ifdef KERBEROS |
---|
326 | strcpy(tempfile, tfname); |
---|
327 | tempfile[0] = 'T'; |
---|
328 | #endif |
---|
329 | if (!chksize(size)) { |
---|
330 | (void) write(1, "\2", 1); |
---|
331 | continue; |
---|
332 | } |
---|
333 | |
---|
334 | /* Don't send final acknowledge beacuse we may wish to |
---|
335 | send error below */ |
---|
336 | if (!readfile(tfname, size, 0, 't')) { |
---|
337 | syslog(LOG_DEBUG, "Failed read"); |
---|
338 | rcleanup(); |
---|
339 | continue; |
---|
340 | } |
---|
341 | |
---|
342 | if (!fixup_cf(tfname, tempfile)) { |
---|
343 | rcleanup(); |
---|
344 | continue; |
---|
345 | } |
---|
346 | |
---|
347 | #ifdef LACL |
---|
348 | if(RA && ((cret = check_remhost()) != 0)) { |
---|
349 | (void) write(1, cret, 1); |
---|
350 | rcleanup(); |
---|
351 | continue; |
---|
352 | } |
---|
353 | |
---|
354 | if(AC && (cret = check_lacl(tfname)) != 0) { |
---|
355 | /* We return !=0 for error. Old clients stupidly |
---|
356 | * don't print any error in this situation. |
---|
357 | * We do a cleanup cause we can't expect |
---|
358 | * client to do so. */ |
---|
359 | (void) write(1, cret, 1); |
---|
360 | #ifdef DEBUG |
---|
361 | syslog(LOG_DEBUG, "Got %s", cret); |
---|
362 | #endif |
---|
363 | rcleanup(); |
---|
364 | continue; |
---|
365 | } |
---|
366 | #endif /*LACL*/ |
---|
367 | |
---|
368 | #ifdef PQUOTA |
---|
369 | if(kerberos_cf && (RQ != NULL) && |
---|
370 | (cret = check_quota(tfname)) != 0) { |
---|
371 | /* We return !=0 for error. Old clients |
---|
372 | stupidly don't print any error in this sit. |
---|
373 | We do a cleanup cause we can't expect |
---|
374 | client to do so. */ |
---|
375 | (void) write(1, cret, 1); |
---|
376 | #ifdef DEBUG |
---|
377 | syslog(LOG_DEBUG, "Got %s", cret); |
---|
378 | #endif |
---|
379 | rcleanup(); |
---|
380 | continue; |
---|
381 | } |
---|
382 | #endif /* PQUOTA */ |
---|
383 | |
---|
384 | /* Send acknowldege, cause we didn't before */ |
---|
385 | ack(); |
---|
386 | |
---|
387 | if (link(tfname, cfname) < 0) |
---|
388 | frecverr("%s: %m", tfname); |
---|
389 | |
---|
390 | (void) spool_unlink(tfname, 't', 1); |
---|
391 | tfname[0] = '\0'; |
---|
392 | nfiles++; |
---|
393 | continue; |
---|
394 | |
---|
395 | case '\3': /* read df file */ |
---|
396 | size = 0; |
---|
397 | while (*cp >= '0' && *cp <= '9') { |
---|
398 | if (size > INT_MAX/10) toobig = 1; |
---|
399 | size = size * 10 + (*cp++ - '0'); |
---|
400 | } |
---|
401 | if (*cp++ != ' ' || toobig) |
---|
402 | break; |
---|
403 | |
---|
404 | if (!isalnum(cp[0]) || !isalnum(cp[1]) || |
---|
405 | !isalnum(cp[2]) || !isalnum(cp[3]) || |
---|
406 | !isalnum(cp[4]) || !isalnum(cp[5])) { |
---|
407 | syslog(LOG_ERR, |
---|
408 | "unexpected job character in df %d.%d.%d.%d.%d.%d", |
---|
409 | cp[0], cp[1], cp[2], cp[3], |
---|
410 | cp[4], cp[5]); |
---|
411 | break; |
---|
412 | } |
---|
413 | if (cp[0] != 'd' || cp[1] != 'f' || |
---|
414 | cp[2] != 'A' || !isxdigit(cp[3]) || |
---|
415 | !isxdigit(cp[4]) || !isxdigit(cp[5])) { |
---|
416 | syslog(LOG_NOTICE, |
---|
417 | "nonstandard job character in df %d.%d.%d.%d.%d.%d", |
---|
418 | cp[0], cp[1], cp[2], cp[3], |
---|
419 | cp[4], cp[5]); |
---|
420 | } |
---|
421 | |
---|
422 | if (!chksize(size)) { |
---|
423 | (void) write(1, "\2", 1); |
---|
424 | continue; |
---|
425 | } |
---|
426 | |
---|
427 | (void) strncpy(dfname, cp, sizeof(dfname)); |
---|
428 | dfname[sizeof(dfname) - 1] = '\0'; |
---|
429 | if (strchr(dfname, '/')) |
---|
430 | frecverr("illegal path name"); |
---|
431 | (void) readfile(dfname, size, 1, 'd'); |
---|
432 | continue; |
---|
433 | } |
---|
434 | frecverr("protocol screwup"); |
---|
435 | } |
---|
436 | } |
---|
437 | |
---|
438 | /* |
---|
439 | * Read files send by lpd and copy them to the spooling directory. |
---|
440 | */ |
---|
441 | readfile(file, size, acknowledge, flag) |
---|
442 | char *file; |
---|
443 | int size; |
---|
444 | int acknowledge; |
---|
445 | int flag; |
---|
446 | { |
---|
447 | register char *cp; |
---|
448 | char buf[BUFSIZ]; |
---|
449 | register int i, j, amt; |
---|
450 | int fd, err; |
---|
451 | |
---|
452 | fd = open(file, O_WRONLY|O_CREAT, FILMOD); |
---|
453 | if (fd < 0) |
---|
454 | frecverr("%s: %m", file); |
---|
455 | ack(); |
---|
456 | err = 0; |
---|
457 | for (i = 0; i < size; i += BUFSIZ) { |
---|
458 | amt = BUFSIZ; |
---|
459 | cp = buf; |
---|
460 | if (i + amt > size) |
---|
461 | amt = size - i; |
---|
462 | do { |
---|
463 | j = read(1, cp, amt); |
---|
464 | if (j <= 0) |
---|
465 | frecverr("Lost connection"); |
---|
466 | amt -= j; |
---|
467 | cp += j; |
---|
468 | } while (amt > 0); |
---|
469 | amt = BUFSIZ; |
---|
470 | if (i + amt > size) |
---|
471 | amt = size - i; |
---|
472 | if (write(fd, buf, amt) != amt) { |
---|
473 | err++; |
---|
474 | break; |
---|
475 | } |
---|
476 | } |
---|
477 | (void) close(fd); |
---|
478 | if (err) |
---|
479 | frecverr("%s: write error", file); |
---|
480 | if (noresponse()) { /* file sent had bad data in it */ |
---|
481 | (void) spool_unlink(file, flag, 1); |
---|
482 | return(0); |
---|
483 | } |
---|
484 | if(acknowledge) |
---|
485 | ack(); |
---|
486 | |
---|
487 | return(1); |
---|
488 | } |
---|
489 | |
---|
490 | fixup_cf(file, tfile) |
---|
491 | char *file, *tfile; |
---|
492 | { |
---|
493 | FILE *cfp, *tfp; |
---|
494 | char kname[ANAME_SZ + INST_SZ + REALM_SZ + 3]; |
---|
495 | char oldname[ANAME_SZ + INST_SZ + REALM_SZ + 3]; |
---|
496 | |
---|
497 | oldname[0] = '\0'; |
---|
498 | |
---|
499 | /* Form a complete string name consisting of principal, |
---|
500 | * instance and realm |
---|
501 | */ |
---|
502 | make_kname(kprincipal, kinstance, krealm, kname); |
---|
503 | |
---|
504 | /* If we cannot open tf file, then return error */ |
---|
505 | if ((cfp = fopen(file, "r")) == NULL) |
---|
506 | return (0); |
---|
507 | |
---|
508 | /* Read the control file for the person sending the job */ |
---|
509 | while (getline(cfp)) { |
---|
510 | if (line[0] == 'P') { |
---|
511 | strncpy(oldname, line+1, sizeof(oldname)-1); |
---|
512 | break; |
---|
513 | } |
---|
514 | } |
---|
515 | fclose(cfp); |
---|
516 | |
---|
517 | /* Have we got a name in oldname, if not, then return error */ |
---|
518 | if (oldname[0] == '\0') |
---|
519 | return(0); |
---|
520 | |
---|
521 | /* Does kname match oldname. If so do nothing */ |
---|
522 | if (!strcmp(kname, oldname)) |
---|
523 | return(1); /* all a-okay */ |
---|
524 | |
---|
525 | /* hmm, doesnt match, guess we have to change the name in |
---|
526 | * the control file by doing the following : |
---|
527 | * |
---|
528 | * (1) Move 'file' to 'tfile' |
---|
529 | * (2) Copy all of 'tfile' back to 'file' but |
---|
530 | * changing the persons name |
---|
531 | */ |
---|
532 | if (link(file, tfile) < 0) |
---|
533 | return(0); |
---|
534 | (void) spool_unlink(file, 't', 1); |
---|
535 | |
---|
536 | /* If we cannot open tf file, then return error */ |
---|
537 | if ((tfp = fopen(tfile, "r")) == NULL) |
---|
538 | return (0); |
---|
539 | if ((cfp = fopen(file, "w")) == NULL) { |
---|
540 | (void) fclose(tfp); |
---|
541 | return (0); |
---|
542 | } |
---|
543 | |
---|
544 | while (getline(tfp)) { |
---|
545 | /* Ignore any queue name that was specified in the original |
---|
546 | * .cf file -- we'll be adding it in shortly... |
---|
547 | */ |
---|
548 | if (line[0] == 'q') continue; |
---|
549 | |
---|
550 | #ifdef KERBEROS |
---|
551 | if (kerberos_cf) { |
---|
552 | if (line[0] == 'P') |
---|
553 | strcpy(&line[1], kname); |
---|
554 | else if (line[0] == 'L') |
---|
555 | strcpy(&line[1], kname); |
---|
556 | } |
---|
557 | #endif |
---|
558 | fprintf(cfp, "%s\n", line); |
---|
559 | |
---|
560 | } |
---|
561 | fprintf(cfp, "q%s\n", printer); |
---|
562 | |
---|
563 | (void) fclose(cfp); |
---|
564 | (void) fclose(tfp); |
---|
565 | (void) spool_unlink(tfile, 'T', 1); |
---|
566 | |
---|
567 | return(1); |
---|
568 | } |
---|
569 | |
---|
570 | noresponse() |
---|
571 | { |
---|
572 | char resp; |
---|
573 | |
---|
574 | if (read(1, &resp, 1) != 1) |
---|
575 | frecverr("Lost connection"); |
---|
576 | if (resp == '\0') |
---|
577 | return(0); |
---|
578 | return(1); |
---|
579 | } |
---|
580 | |
---|
581 | /* |
---|
582 | * Check to see if there is enough space on the disk for size bytes. |
---|
583 | * 1 == OK, 0 == Not OK. |
---|
584 | */ |
---|
585 | chksize(size) |
---|
586 | int size; |
---|
587 | { |
---|
588 | #ifdef USE_USTAT |
---|
589 | struct ustat ubuf; |
---|
590 | |
---|
591 | if (ustat(ddev, &ubuf)) return 1; |
---|
592 | size = (size+1023)/1024; |
---|
593 | if (minfree + size > ubuf.f_tfree) return 0; |
---|
594 | return 1; |
---|
595 | #else |
---|
596 | int spacefree; |
---|
597 | struct fs fs; |
---|
598 | |
---|
599 | if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0) |
---|
600 | return(1); |
---|
601 | if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs) |
---|
602 | return(1); |
---|
603 | spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag + |
---|
604 | fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) * |
---|
605 | fs.fs_fsize / 1024; |
---|
606 | size = (size + 1023) / 1024; |
---|
607 | if (minfree + size > spacefree) |
---|
608 | return(0); |
---|
609 | return(1); |
---|
610 | #endif |
---|
611 | } |
---|
612 | |
---|
613 | read_number(fn) |
---|
614 | char *fn; |
---|
615 | { |
---|
616 | char lin[80]; |
---|
617 | register FILE *fp; |
---|
618 | |
---|
619 | if ((fp = fopen(fn, "r")) == NULL) |
---|
620 | return (0); |
---|
621 | if (fgets(lin, 80, fp) == NULL) { |
---|
622 | fclose(fp); |
---|
623 | return (0); |
---|
624 | } |
---|
625 | fclose(fp); |
---|
626 | return (atoi(lin)); |
---|
627 | } |
---|
628 | |
---|
629 | /* |
---|
630 | * Remove all the files associated with the current job being transfered. |
---|
631 | */ |
---|
632 | rcleanup() |
---|
633 | { |
---|
634 | |
---|
635 | /* This was cretinous code.. which regularly walked off the end |
---|
636 | * of the name space... I changed the != to a >=.. |
---|
637 | */ |
---|
638 | |
---|
639 | if (tfname[0]) |
---|
640 | (void) spool_unlink(tfname, 't', 1); |
---|
641 | #ifdef KERBEROS |
---|
642 | if (tempfile[0]) |
---|
643 | (void) spool_unlink(tempfile, 'T', 1); |
---|
644 | #endif |
---|
645 | if (dfname[0]) |
---|
646 | do { |
---|
647 | do |
---|
648 | if ((spool_unlink(dfname, 'd', 0)) == -2) |
---|
649 | return; |
---|
650 | while (dfname[2]-- >= 'A'); |
---|
651 | dfname[2] = 'z'; |
---|
652 | } while (dfname[0]-- >= 'd'); |
---|
653 | dfname[0] = '\0'; |
---|
654 | } |
---|
655 | |
---|
656 | /* VARARGS1 */ |
---|
657 | frecverr(msg, a1, a2) |
---|
658 | char *msg; |
---|
659 | { |
---|
660 | rcleanup(); |
---|
661 | syslog(LOG_ERR, msg, a1, a2); |
---|
662 | putchar('\1'); /* return error code */ |
---|
663 | exit(1); |
---|
664 | } |
---|
665 | |
---|
666 | #ifdef PQUOTA |
---|
667 | |
---|
668 | char* check_quota(file) |
---|
669 | char file[]; |
---|
670 | { |
---|
671 | struct hostent *hp; |
---|
672 | char outbuf[BUFSIZ], inbuf[BUFSIZ]; |
---|
673 | int t, act=0, s1; |
---|
674 | FILE *cfp; |
---|
675 | struct sockaddr_in sin_c; |
---|
676 | int fd, retry; |
---|
677 | struct servent *servname; |
---|
678 | struct timeval tp; |
---|
679 | fd_set set; |
---|
680 | |
---|
681 | if(RQ == NULL) |
---|
682 | return 0; |
---|
683 | if((hp = gethostbyname(RQ)) == NULL) { |
---|
684 | syslog(LOG_WARNING, "Cannot resolve quota servername %s", RQ); |
---|
685 | return 0; |
---|
686 | } |
---|
687 | |
---|
688 | /* Setup output buffer.... */ |
---|
689 | outbuf[0] = QUOTA_QUERY_VERSION; |
---|
690 | outbuf[1] = (char) UDPPROTOCOL; |
---|
691 | |
---|
692 | /* Generate a sequence number... Since we fork the only realistic |
---|
693 | thing to use is the time... */ |
---|
694 | t = htonl(time((char *) 0)); |
---|
695 | memcpy(outbuf + 2, &t, 4); |
---|
696 | strncpy(outbuf + 5, printer, 30); |
---|
697 | |
---|
698 | |
---|
699 | if(QS == NULL) |
---|
700 | outbuf[40] = '\0'; |
---|
701 | else |
---|
702 | strncpy(outbuf + 40, QS, 20); |
---|
703 | /* If can't open the control file, then there is some error... |
---|
704 | We'll return allowed to print, but somewhere else it will be caught. |
---|
705 | Is this proper? XXX |
---|
706 | */ |
---|
707 | |
---|
708 | if ((cfp = fopen(file, "r")) == NULL) |
---|
709 | return 0; |
---|
710 | |
---|
711 | /* Read the control file for the person sending the job */ |
---|
712 | while (getline(cfp)) { |
---|
713 | if (line[0] == 'Q' || line[0] == 'A') { /* 'A' for old clients */ |
---|
714 | if(sscanf(line + 1, "%d", &act) != 1) act=0; |
---|
715 | break; |
---|
716 | } |
---|
717 | } |
---|
718 | fclose(cfp); |
---|
719 | |
---|
720 | act = htonl(act); |
---|
721 | memcpy(outbuf + 36, &act, 4); |
---|
722 | |
---|
723 | strncpy(outbuf + 60, kprincipal, ANAME_SZ); |
---|
724 | strncpy(outbuf + 60 + ANAME_SZ, kinstance, INST_SZ); |
---|
725 | strncpy(outbuf + 60 + ANAME_SZ + INST_SZ, krealm, REALM_SZ); |
---|
726 | |
---|
727 | if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
---|
728 | syslog(LOG_WARNING, "Could not create UDP socket\n"); |
---|
729 | /* Allow print */ |
---|
730 | return 0; |
---|
731 | } |
---|
732 | |
---|
733 | memset((char *)&sin_c, 0, sizeof(sin_c)); |
---|
734 | sin_c.sin_family = AF_INET; |
---|
735 | servname = getservbyname(QUOTASERVENTNAME,"udp"); |
---|
736 | if(!servname) |
---|
737 | sin_c.sin_port = htons(QUOTASERVENT); |
---|
738 | else |
---|
739 | sin_c.sin_port = servname->s_port; |
---|
740 | |
---|
741 | memcpy(&sin_c.sin_addr,hp->h_addr_list[0], sizeof(sin_c.sin_addr)); |
---|
742 | |
---|
743 | if(connect(fd, &sin_c, sizeof(sin_c)) < 0) { |
---|
744 | syslog(LOG_WARNING, "Could not connect with UDP - quota server down?"); |
---|
745 | /* This means that the quota serve is down */ |
---|
746 | /* Allow printing */ |
---|
747 | return 0; |
---|
748 | } |
---|
749 | |
---|
750 | for(retry = 0; retry < RETRY_COUNT; retry++) { |
---|
751 | if(send(fd, outbuf, 59+ANAME_SZ+REALM_SZ+INST_SZ+1,0)< |
---|
752 | 59+ANAME_SZ+REALM_SZ+INST_SZ+1) { |
---|
753 | syslog(LOG_WARNING, "Send failed to quota"); |
---|
754 | continue; |
---|
755 | } |
---|
756 | |
---|
757 | FD_ZERO(&set); |
---|
758 | FD_SET(fd, &set); |
---|
759 | tp.tv_sec = UDPTIMEOUT; |
---|
760 | tp.tv_usec = 0; |
---|
761 | |
---|
762 | /* So, select and wait for reply */ |
---|
763 | if((s1=select(fd+1, &set, 0, 0, &tp))==0) { |
---|
764 | /*Time out, retry */ |
---|
765 | continue; |
---|
766 | } |
---|
767 | |
---|
768 | if(s1 < 0) { |
---|
769 | /* Error, which makes no sense. Oh well, display */ |
---|
770 | syslog(LOG_WARNING, "Error in UDP return errno=%d", errno); |
---|
771 | /* Allow print */ |
---|
772 | return 0; |
---|
773 | } |
---|
774 | |
---|
775 | if((s1=recv(fd, inbuf, 36, 0)) != 36) { |
---|
776 | syslog(LOG_WARNING, "Receive error in UDP contacting quota"); |
---|
777 | /* Retry */ |
---|
778 | continue; |
---|
779 | } |
---|
780 | |
---|
781 | if(memcmp(inbuf, outbuf, 36)) { |
---|
782 | /* Wrong packet */ |
---|
783 | #ifdef DEBUG |
---|
784 | syslog(LOG_DEBUG, "Packet not for me on UDP"); |
---|
785 | #endif |
---|
786 | continue; |
---|
787 | } |
---|
788 | |
---|
789 | /* Packet good, send response */ |
---|
790 | switch ((int) inbuf[36]) { |
---|
791 | case ALLOWEDTOPRINT: |
---|
792 | #ifdef DEBUG |
---|
793 | syslog(LOG_DEBUG, "Allowed to print!!"); |
---|
794 | #endif |
---|
795 | return 0; |
---|
796 | case NOALLOWEDTOPRINT: |
---|
797 | return "\4"; |
---|
798 | case UNKNOWNUSER: |
---|
799 | return "\3"; |
---|
800 | case UNKNOWNGROUP: |
---|
801 | return "\5"; |
---|
802 | case USERNOTINGROUP: |
---|
803 | return "\6"; |
---|
804 | case USERDELETED: |
---|
805 | return "\7"; |
---|
806 | case GROUPDELETED: |
---|
807 | return "\10"; |
---|
808 | default: |
---|
809 | break; |
---|
810 | /* Bogus, retry */ |
---|
811 | } |
---|
812 | } |
---|
813 | |
---|
814 | if(retry == RETRY_COUNT) { |
---|
815 | /* We timed out in contacting... Allow printing*/ |
---|
816 | return 0; |
---|
817 | } |
---|
818 | return 0; |
---|
819 | } |
---|
820 | |
---|
821 | #endif |
---|
822 | |
---|
823 | #ifdef LACL |
---|
824 | char *check_lacl(file) |
---|
825 | char *file; |
---|
826 | { |
---|
827 | FILE *cfp; |
---|
828 | char person[BUFSIZ]; |
---|
829 | #ifdef KERBEROS |
---|
830 | extern char local_realm[]; |
---|
831 | #endif |
---|
832 | person[0] = '\0'; |
---|
833 | |
---|
834 | if(!AC) { |
---|
835 | syslog(LOG_ERR, "ACL file not set in printcap"); |
---|
836 | return NULL; |
---|
837 | } |
---|
838 | if(access(AC, R_OK)) { |
---|
839 | syslog(LOG_ERR, "Could not find ACL file %s", AC); |
---|
840 | return NULL; |
---|
841 | } |
---|
842 | |
---|
843 | /* Read the control file for the person sending the job */ |
---|
844 | if ((cfp = fopen(file, "r")) == NULL) |
---|
845 | return 0; |
---|
846 | while (getline(cfp)) { |
---|
847 | if (line[0] == 'P' && line[1]) { |
---|
848 | strcpy(person, line + 1); |
---|
849 | break; |
---|
850 | } |
---|
851 | } |
---|
852 | fclose(cfp); |
---|
853 | |
---|
854 | if(!person[0]) { |
---|
855 | #ifdef DEBUG |
---|
856 | syslog(LOG_DEBUG, "Person not found :%s", line); |
---|
857 | #endif |
---|
858 | goto notfound; |
---|
859 | } |
---|
860 | #ifdef DEBUG |
---|
861 | else |
---|
862 | syslog(LOG_DEBUG, "Found person :%s:%s", line, person); |
---|
863 | #endif |
---|
864 | |
---|
865 | #ifdef KERBEROS |
---|
866 | /* Now to tack the realm on */ |
---|
867 | if(kerberos_cf && !strchr(person, '@')) { |
---|
868 | strcat(person,"@"); |
---|
869 | strcat(person, local_realm); |
---|
870 | } |
---|
871 | |
---|
872 | #endif |
---|
873 | |
---|
874 | #ifdef DEBUG |
---|
875 | syslog(LOG_DEBUG, "Checking on :%s: ", person); |
---|
876 | #endif |
---|
877 | |
---|
878 | /* Now see if the person is in AC */ |
---|
879 | if ((cfp = fopen(AC, "r")) == NULL) |
---|
880 | return 0; |
---|
881 | while(getline(cfp)) { |
---|
882 | if(!strcasecmp(person, line)) { |
---|
883 | fclose(cfp); |
---|
884 | goto found; |
---|
885 | } |
---|
886 | } |
---|
887 | fclose(cfp); |
---|
888 | |
---|
889 | notfound: |
---|
890 | if(PA) return "\4"; /* NOALLOWEDTOPRINT */ |
---|
891 | else return NULL; |
---|
892 | |
---|
893 | found: |
---|
894 | if(PA) return NULL; |
---|
895 | else return "\4"; /* NOALLOWEDTOPRINT */ |
---|
896 | } |
---|
897 | |
---|
898 | char * |
---|
899 | check_remhost() |
---|
900 | { |
---|
901 | register char *cp, *sp; |
---|
902 | extern char from_host[]; |
---|
903 | register FILE *hostf; |
---|
904 | char ahost[MAXHOSTNAMELEN + 1]; |
---|
905 | int baselen = -1; |
---|
906 | |
---|
907 | if(!strcasecmp(from_host, host)) return NULL; |
---|
908 | #if 0 |
---|
909 | syslog(LOG_DEBUG, "About to check on %s\n", from_host); |
---|
910 | #endif |
---|
911 | sp = from_host; |
---|
912 | cp = ahost; |
---|
913 | while (*sp) { |
---|
914 | if (*sp == '.') { |
---|
915 | if (baselen == -1) |
---|
916 | baselen = sp - from_host; |
---|
917 | *cp++ = *sp++; |
---|
918 | } else { |
---|
919 | *cp++ = isupper(*sp) ? tolower(*sp++) : *sp++; |
---|
920 | } |
---|
921 | } |
---|
922 | *cp = '\0'; |
---|
923 | hostf = fopen("/etc/hosts.lpd", "r"); |
---|
924 | #define DUMMY ":nobody::" |
---|
925 | if (hostf) { |
---|
926 | if (!validuser(hostf, ahost, DUMMY, DUMMY, baselen)) { |
---|
927 | (void) fclose(hostf); |
---|
928 | return NULL; |
---|
929 | } |
---|
930 | (void) fclose(hostf); |
---|
931 | return "\4"; |
---|
932 | } else { |
---|
933 | /* Could not open hosts.lpd file */ |
---|
934 | return NULL; |
---|
935 | } |
---|
936 | } |
---|
937 | #endif /* LACL */ |
---|