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