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