1 | #ifndef SERVER |
---|
2 | |
---|
3 | #define TMPDIR "/tmp" |
---|
4 | #include "lp.h" |
---|
5 | |
---|
6 | /* |
---|
7 | * Error tokens |
---|
8 | */ |
---|
9 | #define REPRINT -2 |
---|
10 | #define ERROR -1 |
---|
11 | #define OK 0 |
---|
12 | #define FATALERR 1 |
---|
13 | #define NOACCT 2 |
---|
14 | #define FILTERERR 3 |
---|
15 | #define ACCESS 4 |
---|
16 | #endif |
---|
17 | |
---|
18 | /* |
---|
19 | * $Source: /afs/dev.mit.edu/source/repository/athena/bin/lpr/lpr.c,v $ |
---|
20 | * $Author: probe $ |
---|
21 | * $Locker: $ |
---|
22 | * $Header: /afs/dev.mit.edu/source/repository/athena/bin/lpr/lpr.c,v 1.14 1992-11-09 00:48:42 probe Exp $ |
---|
23 | */ |
---|
24 | |
---|
25 | #ifndef lint |
---|
26 | static char *rcsid_lpr_c = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/lpr/lpr.c,v 1.14 1992-11-09 00:48:42 probe Exp $"; |
---|
27 | #endif lint |
---|
28 | |
---|
29 | /* |
---|
30 | * Copyright (c) 1983 Regents of the University of California. |
---|
31 | * All rights reserved. The Berkeley software License Agreement |
---|
32 | * specifies the terms and conditions for redistribution. |
---|
33 | */ |
---|
34 | |
---|
35 | #ifndef lint |
---|
36 | char copyright[] = |
---|
37 | "@(#) Copyright (c) 1983 Regents of the University of California.\n\ |
---|
38 | All rights reserved.\n"; |
---|
39 | #endif not lint |
---|
40 | |
---|
41 | #ifndef lint |
---|
42 | static char sccsid[] = "@(#)lpr.c 5.2 (Berkeley) 11/17/85"; |
---|
43 | #endif not lint |
---|
44 | |
---|
45 | /* |
---|
46 | * lpr -- off line print |
---|
47 | * |
---|
48 | * Allows multiple printers and printers on remote machines by |
---|
49 | * using information from a printer data base. |
---|
50 | */ |
---|
51 | |
---|
52 | #include <stdio.h> |
---|
53 | #include <grp.h> |
---|
54 | #include <syslog.h> |
---|
55 | #include <sys/types.h> |
---|
56 | #ifdef SERVER |
---|
57 | #include <sys/file.h> |
---|
58 | #include <sys/stat.h> |
---|
59 | #include <pwd.h> |
---|
60 | #include <signal.h> |
---|
61 | #include <ctype.h> |
---|
62 | #include <netdb.h> |
---|
63 | #include <strings.h> |
---|
64 | #include "lp.local.h" |
---|
65 | #endif SERVER |
---|
66 | |
---|
67 | #define UNLINK unlink |
---|
68 | |
---|
69 | #ifndef SERVER |
---|
70 | char *RG; /* Restricted group */ |
---|
71 | |
---|
72 | #else SERVER |
---|
73 | char *tfname; /* tmp copy of cf before linking */ |
---|
74 | #endif SERVER |
---|
75 | char *cfname; /* daemon control files, linked from tf's */ |
---|
76 | char *dfname; /* data files */ |
---|
77 | |
---|
78 | int nact; /* number of jobs to act on */ |
---|
79 | #ifndef SERVER |
---|
80 | int pfd; /* Printer file descriptor */ |
---|
81 | #endif SERVER |
---|
82 | int tfd; /* control file descriptor */ |
---|
83 | int mailflg; /* send mail */ |
---|
84 | int qflag; /* q job, but don't exec daemon */ |
---|
85 | char format = 'f'; /* format char for printing files */ |
---|
86 | int rflag; /* remove files upon completion */ |
---|
87 | #ifdef SERVER |
---|
88 | int sflag; /* symbolic link flag */ |
---|
89 | #endif SERVER |
---|
90 | int inchar; /* location to increment char in file names */ |
---|
91 | int ncopies = 1; /* # of copies to make */ |
---|
92 | int iflag; /* indentation wanted */ |
---|
93 | int indent; /* amount to indent */ |
---|
94 | int noendpage; /* file contains own form feeds */ |
---|
95 | int hdr = 1; /* print header or not (default is yes) */ |
---|
96 | int userid; /* user id */ |
---|
97 | char *person; /* user name */ |
---|
98 | char *title; /* pr'ing title */ |
---|
99 | char *fonts[4]; /* troff font names */ |
---|
100 | char *width; /* width for versatec printing */ |
---|
101 | char host[32]; /* host name */ |
---|
102 | char *class = host; /* class title on header page */ |
---|
103 | char *jobname; /* job name on header page */ |
---|
104 | char *name; /* program name */ |
---|
105 | char *printer; /* printer name */ |
---|
106 | char *forms; /* printer forms (for Multics) */ |
---|
107 | char *lpropt; /* for lpropt env. variable */ |
---|
108 | struct stat statb; |
---|
109 | #ifdef HESIOD |
---|
110 | char alibuf[BUFSIZ/2]; /* buffer for printer alias */ |
---|
111 | #endif |
---|
112 | |
---|
113 | #ifdef KERBEROS |
---|
114 | int use_kerberos; |
---|
115 | int kerberos_override = -1; |
---|
116 | int account = 0; |
---|
117 | #endif KERBEROS |
---|
118 | |
---|
119 | #ifdef ZEPHYR |
---|
120 | int zephyrflag = 0; |
---|
121 | #endif ZEPHYR |
---|
122 | |
---|
123 | #ifdef SERVER |
---|
124 | int MX; /* maximum number of blocks to copy */ |
---|
125 | int MC; /* maximum number of copies allowed */ |
---|
126 | int DU; /* daemon user-id */ |
---|
127 | char *SD; /* spool directory */ |
---|
128 | char *LO; /* lock file name */ |
---|
129 | char *RG; /* restrict group */ |
---|
130 | short SC; /* suppress multiple copies */ |
---|
131 | |
---|
132 | #endif SERVER |
---|
133 | char *getenv(); |
---|
134 | char *linked(); |
---|
135 | int cleanup(); |
---|
136 | extern char *malloc(); |
---|
137 | |
---|
138 | /*ARGSUSED*/ |
---|
139 | main(argc, argv) |
---|
140 | int argc; |
---|
141 | char *argv[]; |
---|
142 | { |
---|
143 | extern struct passwd *getpwuid(); |
---|
144 | struct passwd *pw; |
---|
145 | struct group *gptr; |
---|
146 | extern char *itoa(); |
---|
147 | register char *arg, *cp; |
---|
148 | char buf[BUFSIZ]; |
---|
149 | |
---|
150 | #ifndef SERVER |
---|
151 | int i, f, retry; |
---|
152 | #else SERVER |
---|
153 | int i, f; |
---|
154 | struct stat stb; |
---|
155 | #endif SERVER |
---|
156 | struct hostent *hp; |
---|
157 | |
---|
158 | #ifndef SERVER |
---|
159 | pfd = -1; /* Printer isn't open yet */ |
---|
160 | |
---|
161 | #endif SERVER |
---|
162 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) |
---|
163 | signal(SIGHUP, cleanup); |
---|
164 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) |
---|
165 | signal(SIGINT, cleanup); |
---|
166 | if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) |
---|
167 | signal(SIGQUIT, cleanup); |
---|
168 | if (signal(SIGTERM, SIG_IGN) != SIG_IGN) |
---|
169 | signal(SIGTERM, cleanup); |
---|
170 | |
---|
171 | name = argv[0]; |
---|
172 | gethostname(host, sizeof (host)); |
---|
173 | #ifndef SERVER |
---|
174 | if (hp = gethostbyname(host)) |
---|
175 | (void) strcpy(host, hp -> h_name); |
---|
176 | #else SERVER |
---|
177 | if (hp = gethostbyname(host)) strcpy(host, hp -> h_name); |
---|
178 | #endif SERVER |
---|
179 | #ifdef LOG_LPR |
---|
180 | openlog("lpr", 0, LOG_LPR); |
---|
181 | #else |
---|
182 | openlog("lpr", 0); |
---|
183 | #endif |
---|
184 | |
---|
185 | /* Process LPROPT environment variable if it exists */ |
---|
186 | if((lpropt = getenv("LPROPT")) != NULL) { |
---|
187 | char *lpropt1, **nargv; |
---|
188 | |
---|
189 | /* Copy lpropt to permanent storage */ |
---|
190 | if(!(lpropt1 = malloc(strlen(lpropt)+1))) { |
---|
191 | printf("%s: out of memory\n", name); |
---|
192 | exit(1); |
---|
193 | } |
---|
194 | strcpy(lpropt1, lpropt); |
---|
195 | |
---|
196 | /* Count up spaces in lpropt1 - number of arguments */ |
---|
197 | |
---|
198 | for(i=1, cp = lpropt1; *cp != NULL; cp++) if(*cp == ' ') i++; |
---|
199 | |
---|
200 | if(!(nargv = (char **) malloc(sizeof(char *) *(i + argc +1 )))) { |
---|
201 | printf("%s: out of memory\n", name); |
---|
202 | exit(1); |
---|
203 | } |
---|
204 | |
---|
205 | nargv[0] = argv[0]; |
---|
206 | for(f = 1, cp = lpropt1; f <= i; f++) { |
---|
207 | nargv[f] = cp; |
---|
208 | while((*cp != NULL) && (*cp != ' ')) cp++; |
---|
209 | if(*cp == ' ') *cp = NULL, cp++; |
---|
210 | } |
---|
211 | for(f = i+1; f<= argc+i; f++) |
---|
212 | nargv[f] = argv[f-i]; |
---|
213 | argv = nargv; |
---|
214 | argc += i; |
---|
215 | } |
---|
216 | |
---|
217 | /* for(i = 0; i < argc; i++) printf("%d :%s:\n", i, argv[i]); */ |
---|
218 | |
---|
219 | while (argc > 1 && argv[1][0] == '-') { |
---|
220 | argc--; |
---|
221 | arg = *++argv; |
---|
222 | switch (arg[1]) { |
---|
223 | |
---|
224 | case 'P': /* specify printer name */ |
---|
225 | if (arg[2]) |
---|
226 | printer = &arg[2]; |
---|
227 | else if (argc > 1) { |
---|
228 | argc--; |
---|
229 | printer = *++argv; |
---|
230 | } |
---|
231 | break; |
---|
232 | |
---|
233 | case 'C': /* classification spec */ |
---|
234 | hdr++; |
---|
235 | if (arg[2]) |
---|
236 | class = &arg[2]; |
---|
237 | else if (argc > 1) { |
---|
238 | argc--; |
---|
239 | class = *++argv; |
---|
240 | } |
---|
241 | break; |
---|
242 | |
---|
243 | case 'J': /* job name */ |
---|
244 | hdr++; |
---|
245 | if (arg[2]) |
---|
246 | jobname = &arg[2]; |
---|
247 | else if (argc > 1) { |
---|
248 | argc--; |
---|
249 | jobname = *++argv; |
---|
250 | } |
---|
251 | break; |
---|
252 | |
---|
253 | case 'T': /* pr's title line */ |
---|
254 | if (arg[2]) |
---|
255 | title = &arg[2]; |
---|
256 | else if (argc > 1) { |
---|
257 | argc--; |
---|
258 | title = *++argv; |
---|
259 | } |
---|
260 | break; |
---|
261 | |
---|
262 | case 'l': /* literal output */ |
---|
263 | case 'p': /* print using ``pr'' */ |
---|
264 | case 't': /* print troff output (cat files) */ |
---|
265 | case 'n': /* print ditroff output */ |
---|
266 | case 'd': /* print tex output (dvi files) */ |
---|
267 | case 'g': /* print graph(1G) output */ |
---|
268 | case 'c': /* print cifplot output */ |
---|
269 | case 'v': /* print vplot output */ |
---|
270 | format = arg[1]; |
---|
271 | break; |
---|
272 | |
---|
273 | case 'f': /* print fortran output */ |
---|
274 | format = 'r'; |
---|
275 | break; |
---|
276 | |
---|
277 | case '4': /* troff fonts */ |
---|
278 | case '3': |
---|
279 | case '2': |
---|
280 | case '1': |
---|
281 | if (argc > 1) { |
---|
282 | argc--; |
---|
283 | fonts[arg[1] - '1'] = *++argv; |
---|
284 | } |
---|
285 | break; |
---|
286 | |
---|
287 | case 'w': /* versatec page width */ |
---|
288 | width = arg+2; |
---|
289 | break; |
---|
290 | |
---|
291 | case 'r': /* remove file when done */ |
---|
292 | rflag++; |
---|
293 | break; |
---|
294 | |
---|
295 | case 'm': /* send mail when done */ |
---|
296 | mailflg++; |
---|
297 | break; |
---|
298 | |
---|
299 | #ifdef ZEPHYR |
---|
300 | case 'z': |
---|
301 | zephyrflag++; |
---|
302 | break; |
---|
303 | #endif ZEPHYR |
---|
304 | |
---|
305 | case 'h': /* toggle want of header page */ |
---|
306 | hdr = !hdr; |
---|
307 | break; |
---|
308 | |
---|
309 | #ifdef SERVER |
---|
310 | case 's': /* try to link files */ |
---|
311 | sflag++; |
---|
312 | break; |
---|
313 | |
---|
314 | #endif SERVER |
---|
315 | case 'q': /* just q job */ |
---|
316 | qflag++; |
---|
317 | break; |
---|
318 | |
---|
319 | case 'i': /* indent output */ |
---|
320 | iflag++; |
---|
321 | indent = arg[2] ? atoi(&arg[2]) : 8; |
---|
322 | break; |
---|
323 | |
---|
324 | case '#': /* n copies */ |
---|
325 | if (isdigit(arg[2])) { |
---|
326 | i = atoi(&arg[2]); |
---|
327 | if (i > 0) |
---|
328 | ncopies = i; |
---|
329 | } |
---|
330 | case 'E': |
---|
331 | noendpage++; /* form feeds there already */ |
---|
332 | break; /* for multics */ |
---|
333 | |
---|
334 | case 'F': /* printer forms */ |
---|
335 | if (arg[2]) /* for multics */ |
---|
336 | forms = &arg[2]; |
---|
337 | else if (argc > 1) { |
---|
338 | argc--; |
---|
339 | forms = *++argv; |
---|
340 | } |
---|
341 | break; |
---|
342 | #ifdef KERBEROS |
---|
343 | case 'u': |
---|
344 | kerberos_override = 0; |
---|
345 | break; |
---|
346 | case 'k': |
---|
347 | kerberos_override = 1; |
---|
348 | break; |
---|
349 | case 'a': |
---|
350 | if (isdigit(arg[2])) { |
---|
351 | i = atoi(&arg[2]); |
---|
352 | if (i > 0) |
---|
353 | account = i; |
---|
354 | } |
---|
355 | break; |
---|
356 | #endif KERBEROS |
---|
357 | } |
---|
358 | } |
---|
359 | if (printer == NULL && (printer = getenv("PRINTER")) == NULL) |
---|
360 | printer = DEFLP; |
---|
361 | chkprinter(); |
---|
362 | if (SC && ncopies > 1) |
---|
363 | fatal("multiple copies are not allowed"); |
---|
364 | if (MC > 0 && ncopies > MC) |
---|
365 | fatal("only %d copies are allowed", MC); |
---|
366 | /* |
---|
367 | * Get the identity of the person doing the lpr using the same |
---|
368 | * algorithm as lprm. |
---|
369 | */ |
---|
370 | userid = getuid(); |
---|
371 | if ((pw = getpwuid(userid)) == NULL) |
---|
372 | fatal("Who are you?"); |
---|
373 | person = pw->pw_name; |
---|
374 | /* |
---|
375 | * Check for restricted group access. |
---|
376 | */ |
---|
377 | if (RG != NULL) { |
---|
378 | if ((gptr = getgrnam(RG)) == NULL) |
---|
379 | fatal("Restricted group specified incorrectly"); |
---|
380 | if (gptr->gr_gid != getgid()) { |
---|
381 | while (*gptr->gr_mem != NULL) { |
---|
382 | if ((strcmp(person, *gptr->gr_mem)) == 0) |
---|
383 | break; |
---|
384 | gptr->gr_mem++; |
---|
385 | } |
---|
386 | if (*gptr->gr_mem == NULL) |
---|
387 | fatal("Not a member of the restricted group"); |
---|
388 | } |
---|
389 | } |
---|
390 | #ifndef SERVER |
---|
391 | openpr(); |
---|
392 | mktemps(); |
---|
393 | (void) setuid(userid); /* Drop root privs */ |
---|
394 | #else |
---|
395 | /* |
---|
396 | * Check to make sure queuing is enabled if userid is not root. |
---|
397 | */ |
---|
398 | (void) sprintf(buf, "%s/%s", SD, LO); |
---|
399 | if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010)) |
---|
400 | fatal("Printer queue is disabled"); |
---|
401 | #endif SERVER |
---|
402 | /* |
---|
403 | * Initialize the control file. |
---|
404 | */ |
---|
405 | #ifndef SERVER |
---|
406 | tfd = creat(cfname, FILMOD); |
---|
407 | #else SERVER |
---|
408 | mktemps(); |
---|
409 | tfd = nfile(tfname); |
---|
410 | (void) fchown(tfd, DU, -1); /* owned by daemon for protection */ |
---|
411 | #endif SERVER |
---|
412 | card('H', host); |
---|
413 | card('P', person); |
---|
414 | #ifdef KERBEROS |
---|
415 | if (account) |
---|
416 | card('Q', itoa(account)); |
---|
417 | #endif KERBEROS |
---|
418 | if (forms != NULL) |
---|
419 | card('F', forms); |
---|
420 | if (hdr) { |
---|
421 | if (jobname == NULL) { |
---|
422 | if (argc == 1) |
---|
423 | jobname = "stdin"; |
---|
424 | else |
---|
425 | jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1]; |
---|
426 | } |
---|
427 | card('J', jobname); |
---|
428 | card('C', class); |
---|
429 | card('L', person); |
---|
430 | } |
---|
431 | if (noendpage) |
---|
432 | card('E', ""); |
---|
433 | if (iflag) |
---|
434 | card('I', itoa(indent)); |
---|
435 | if (mailflg) |
---|
436 | card('M', person); |
---|
437 | |
---|
438 | #ifdef ZEPHYR |
---|
439 | if (zephyrflag) |
---|
440 | card('Z', person); |
---|
441 | #endif ZEPHYR |
---|
442 | |
---|
443 | if (format == 't' || format == 'n' || format == 'd') |
---|
444 | for (i = 0; i < 4; i++) |
---|
445 | if (fonts[i] != NULL) |
---|
446 | card('1'+i, fonts[i]); |
---|
447 | if (width != NULL) |
---|
448 | card('W', width); |
---|
449 | |
---|
450 | /* |
---|
451 | * Read the files and spool them. |
---|
452 | */ |
---|
453 | if (argc == 1) |
---|
454 | copy(0, " "); |
---|
455 | else while (--argc) { |
---|
456 | if ((f = test(arg = *++argv)) < 0) |
---|
457 | continue; /* file unreasonable */ |
---|
458 | |
---|
459 | #ifndef SERVER |
---|
460 | if ((cp = linked(arg)) != NULL) { |
---|
461 | #else SERVER |
---|
462 | if (sflag && (cp = linked(arg)) != NULL) { |
---|
463 | #endif SERVER |
---|
464 | (void) sprintf(buf, "%d %d", statb.st_dev, statb.st_ino); |
---|
465 | card('S', buf); |
---|
466 | if (format == 'p') |
---|
467 | card('T', title ? title : arg); |
---|
468 | for (i = 0; i < ncopies; i++) |
---|
469 | card(format, &dfname[inchar-2]); |
---|
470 | card('U', &dfname[inchar-2]); |
---|
471 | if (f) |
---|
472 | card('U', cp); |
---|
473 | card('N', arg); |
---|
474 | dfname[inchar]++; |
---|
475 | nact++; |
---|
476 | continue; |
---|
477 | } |
---|
478 | #ifndef SERVER |
---|
479 | printf("%s: %s: not linked, copying instead\n", name, arg); |
---|
480 | #else SERVER |
---|
481 | if (sflag) |
---|
482 | printf("%s: %s: not linked, copying instead\n", name, arg); |
---|
483 | #endif SERVER |
---|
484 | if ((i = open(arg, O_RDONLY)) < 0) { |
---|
485 | printf("%s: cannot open %s\n", name, arg); |
---|
486 | continue; |
---|
487 | } |
---|
488 | copy(i, arg); |
---|
489 | (void) close(i); |
---|
490 | if (f && UNLINK(arg) < 0) |
---|
491 | printf("%s: %s: not removed\n", name, arg); |
---|
492 | } |
---|
493 | |
---|
494 | if (nact) { |
---|
495 | (void) close(tfd); |
---|
496 | #ifdef SERVER |
---|
497 | tfname[inchar]--; |
---|
498 | /* |
---|
499 | * Touch the control file to fix position in the queue. |
---|
500 | */ |
---|
501 | if ((tfd = open(tfname, O_RDWR)) >= 0) { |
---|
502 | char c; |
---|
503 | |
---|
504 | if (read(tfd, &c, 1) == 1 && lseek(tfd, 0L, 0) == 0 && |
---|
505 | write(tfd, &c, 1) != 1) { |
---|
506 | printf("%s: cannot touch %s\n", name, tfname); |
---|
507 | tfname[inchar]++; |
---|
508 | cleanup(); |
---|
509 | } |
---|
510 | (void) close(tfd); |
---|
511 | } |
---|
512 | if (link(tfname, cfname) < 0) { |
---|
513 | printf("%s: cannot rename %s\n", name, cfname); |
---|
514 | tfname[inchar]++; |
---|
515 | cleanup(); |
---|
516 | } |
---|
517 | UNLINK(tfname); |
---|
518 | #endif SERVER |
---|
519 | if (qflag) /* just q things up */ |
---|
520 | exit(0); |
---|
521 | #ifndef SERVER |
---|
522 | retry=0; /* Retry counter */ |
---|
523 | while (((i = sendit(&cfname[inchar-2])) == REPRINT) && |
---|
524 | (retry<3)) |
---|
525 | retry++; |
---|
526 | if (i != OK) { |
---|
527 | fprintf(stderr,"I can't seem to be able to send "); |
---|
528 | fprintf(stderr,"your request to the printer.\n"); |
---|
529 | fprintf(stderr,"Please try again later or try "); |
---|
530 | fprintf(stderr,"using another printer.\n"); |
---|
531 | exit(1); |
---|
532 | } |
---|
533 | #else SERVER |
---|
534 | if (!startdaemon(printer)) |
---|
535 | printf("jobs queued, but cannot start daemon.\n"); |
---|
536 | #endif SERVER |
---|
537 | exit(0); |
---|
538 | } |
---|
539 | cleanup(); |
---|
540 | /* NOTREACHED */ |
---|
541 | } |
---|
542 | |
---|
543 | /* |
---|
544 | * Create the file n and copy from file descriptor f. |
---|
545 | */ |
---|
546 | copy(f, n) |
---|
547 | int f; |
---|
548 | char n[]; |
---|
549 | { |
---|
550 | register int fd, i, nr, nc; |
---|
551 | char buf[BUFSIZ]; |
---|
552 | |
---|
553 | if (format == 'p') |
---|
554 | card('T', title ? title : n); |
---|
555 | for (i = 0; i < ncopies; i++) |
---|
556 | card(format, &dfname[inchar-2]); |
---|
557 | card('U', &dfname[inchar-2]); |
---|
558 | card('N', n); |
---|
559 | fd = nfile(dfname); |
---|
560 | nr = nc = 0; |
---|
561 | while ((i = read(f, buf, BUFSIZ)) > 0) { |
---|
562 | if (write(fd, buf, i) != i) { |
---|
563 | printf("%s: %s: temp file write error\n", name, n); |
---|
564 | break; |
---|
565 | } |
---|
566 | nc += i; |
---|
567 | if (nc >= BUFSIZ) { |
---|
568 | nc -= BUFSIZ; |
---|
569 | nr++; |
---|
570 | if (MX > 0 && nr > MX) { |
---|
571 | printf("%s: %s: copy file is too large\n", name, n); |
---|
572 | break; |
---|
573 | } |
---|
574 | } |
---|
575 | } |
---|
576 | (void) close(fd); |
---|
577 | if (nc==0 && nr==0) |
---|
578 | printf("%s: %s: empty input file\n", name, f ? n : "stdin"); |
---|
579 | else |
---|
580 | nact++; |
---|
581 | } |
---|
582 | |
---|
583 | /* |
---|
584 | * Try and link the file to dfname. Return a pointer to the full |
---|
585 | * path name if successful. |
---|
586 | */ |
---|
587 | char * |
---|
588 | linked(file) |
---|
589 | register char *file; |
---|
590 | { |
---|
591 | register char *cp; |
---|
592 | static char buf[BUFSIZ]; |
---|
593 | |
---|
594 | if (*file != '/') { |
---|
595 | if (getwd(buf) == NULL) |
---|
596 | return(NULL); |
---|
597 | while (file[0] == '.') { |
---|
598 | switch (file[1]) { |
---|
599 | case '/': |
---|
600 | file += 2; |
---|
601 | continue; |
---|
602 | case '.': |
---|
603 | if (file[2] == '/') { |
---|
604 | if ((cp = rindex(buf, '/')) != NULL) |
---|
605 | *cp = '\0'; |
---|
606 | file += 3; |
---|
607 | continue; |
---|
608 | } |
---|
609 | } |
---|
610 | break; |
---|
611 | } |
---|
612 | (void) strcat(buf, "/"); |
---|
613 | (void) strcat(buf, file); |
---|
614 | file = buf; |
---|
615 | } |
---|
616 | return(symlink(file, dfname) ? NULL : file); |
---|
617 | } |
---|
618 | |
---|
619 | /* |
---|
620 | * Put a line into the control file. |
---|
621 | */ |
---|
622 | card(c, p2) |
---|
623 | register char c, *p2; |
---|
624 | { |
---|
625 | char buf[BUFSIZ]; |
---|
626 | register char *p1 = buf; |
---|
627 | register int len = 2; |
---|
628 | |
---|
629 | *p1++ = c; |
---|
630 | while ((c = *p2++) != '\0') { |
---|
631 | *p1++ = c; |
---|
632 | len++; |
---|
633 | } |
---|
634 | *p1++ = '\n'; |
---|
635 | write(tfd, buf, len); |
---|
636 | } |
---|
637 | |
---|
638 | /* |
---|
639 | * Create a new file in the spool directory. |
---|
640 | */ |
---|
641 | nfile(n) |
---|
642 | char *n; |
---|
643 | { |
---|
644 | register int f; |
---|
645 | int oldumask = umask(0); /* should block signals */ |
---|
646 | |
---|
647 | f = creat(n, FILMOD); |
---|
648 | (void) umask(oldumask); |
---|
649 | if (f < 0) { |
---|
650 | printf("%s: cannot create %s\n", name, n); |
---|
651 | cleanup(); |
---|
652 | } |
---|
653 | #ifdef SERVER |
---|
654 | if (fchown(f, userid, -1) < 0) { |
---|
655 | printf("%s: cannot chown %s\n", name, n); |
---|
656 | cleanup(); |
---|
657 | } |
---|
658 | #endif SERVER |
---|
659 | if (++n[inchar] > 'z') { |
---|
660 | if (++n[inchar-2] == 't') { |
---|
661 | printf("too many files - break up the job\n"); |
---|
662 | cleanup(); |
---|
663 | } |
---|
664 | n[inchar] = 'A'; |
---|
665 | } else if (n[inchar] == '[') |
---|
666 | n[inchar] = 'a'; |
---|
667 | return(f); |
---|
668 | } |
---|
669 | |
---|
670 | /* |
---|
671 | * Cleanup after interrupts and errors. |
---|
672 | */ |
---|
673 | cleanup() |
---|
674 | { |
---|
675 | register int i; |
---|
676 | |
---|
677 | signal(SIGHUP, SIG_IGN); |
---|
678 | signal(SIGINT, SIG_IGN); |
---|
679 | signal(SIGQUIT, SIG_IGN); |
---|
680 | signal(SIGTERM, SIG_IGN); |
---|
681 | i = inchar; |
---|
682 | #ifdef SERVER |
---|
683 | if (tfname) |
---|
684 | do |
---|
685 | UNLINK(tfname); |
---|
686 | while (tfname[i]-- != 'A'); |
---|
687 | #endif SERVER |
---|
688 | if (cfname) |
---|
689 | #ifdef SERVER |
---|
690 | do { |
---|
691 | UNLINK(cfname); |
---|
692 | } while (cfname[i]-- != 'A'); |
---|
693 | #else |
---|
694 | UNLINK(cfname); |
---|
695 | #endif SERVER |
---|
696 | if (dfname) |
---|
697 | do { |
---|
698 | do |
---|
699 | UNLINK(dfname); |
---|
700 | while (dfname[i]-- != 'A'); |
---|
701 | dfname[i] = 'z'; |
---|
702 | } while (dfname[i-2]-- != 'd'); |
---|
703 | #ifndef SERVER |
---|
704 | if (pfd > 0) |
---|
705 | (void) close(pfd); /* Shutdown printer connection */ |
---|
706 | #endif SERVER |
---|
707 | exit(1); |
---|
708 | } |
---|
709 | |
---|
710 | /* |
---|
711 | * Test to see if this is a printable file. |
---|
712 | * Return -1 if it is not, 0 if its printable, and 1 if |
---|
713 | * we should remove it after printing. |
---|
714 | */ |
---|
715 | test(file) |
---|
716 | char *file; |
---|
717 | { |
---|
718 | #if defined(LP_COFF_DEFINES) |
---|
719 | struct filehdr execb; |
---|
720 | #else |
---|
721 | struct exec execb; |
---|
722 | #endif |
---|
723 | register int fd; |
---|
724 | register char *cp; |
---|
725 | |
---|
726 | #ifdef SERVER |
---|
727 | if (access(file, 4) < 0) { |
---|
728 | printf("%s: cannot access %s\n", name, file); |
---|
729 | return(-1); |
---|
730 | } |
---|
731 | #endif SERVER |
---|
732 | if (stat(file, &statb) < 0) { |
---|
733 | printf("%s: cannot stat %s\n", name, file); |
---|
734 | return(-1); |
---|
735 | } |
---|
736 | if ((statb.st_mode & S_IFMT) == S_IFDIR) { |
---|
737 | printf("%s: %s is a directory\n", name, file); |
---|
738 | return(-1); |
---|
739 | } |
---|
740 | if (statb.st_size == 0) { |
---|
741 | printf("%s: %s is an empty file\n", name, file); |
---|
742 | return(-1); |
---|
743 | } |
---|
744 | if ((fd = open(file, O_RDONLY)) < 0) { |
---|
745 | printf("%s: cannot open %s\n", name, file); |
---|
746 | return(-1); |
---|
747 | } |
---|
748 | |
---|
749 | if (read(fd, &execb, sizeof(execb)) == sizeof(execb)) |
---|
750 | #ifndef LP_COFF_DEFINES |
---|
751 | switch((int) execb.a_magic) { |
---|
752 | case A_MAGIC1: |
---|
753 | case A_MAGIC2: |
---|
754 | case A_MAGIC3: |
---|
755 | #ifdef A_MAGIC4 |
---|
756 | case A_MAGIC4: |
---|
757 | #endif |
---|
758 | printf("%s: %s is an executable program", name, file); |
---|
759 | goto error1; |
---|
760 | case ARMAG: |
---|
761 | printf("%s: %s is an archive file", name, file); |
---|
762 | goto error1; |
---|
763 | } |
---|
764 | #else /* LP_COFF_DEFINES */ |
---|
765 | if(ISCOFF(execb.f_magic)) { |
---|
766 | printf("%s: %s is an executable program", name, file); |
---|
767 | goto error1; |
---|
768 | } |
---|
769 | if(execb.f_magic == ARMAG) { |
---|
770 | printf("%s: %s is an archive file", name, file); |
---|
771 | goto error1; |
---|
772 | } |
---|
773 | #endif /* coff */ |
---|
774 | (void) close(fd); |
---|
775 | if (rflag) { |
---|
776 | if ((cp = rindex(file, '/')) == NULL) { |
---|
777 | if (access(".", 2) == 0) |
---|
778 | return(1); |
---|
779 | } else { |
---|
780 | *cp = '\0'; |
---|
781 | fd = access(file, 2); |
---|
782 | *cp = '/'; |
---|
783 | if (fd == 0) |
---|
784 | return(1); |
---|
785 | } |
---|
786 | printf("%s: %s: is not removable by you\n", name, file); |
---|
787 | } |
---|
788 | return(0); |
---|
789 | |
---|
790 | error1: |
---|
791 | printf(" and is unprintable\n"); |
---|
792 | (void) close(fd); |
---|
793 | return(-1); |
---|
794 | } |
---|
795 | |
---|
796 | /* |
---|
797 | * itoa - integer to string conversion |
---|
798 | */ |
---|
799 | char * |
---|
800 | itoa(i) |
---|
801 | register int i; |
---|
802 | { |
---|
803 | static char b[10] = "########"; |
---|
804 | register char *p; |
---|
805 | |
---|
806 | p = &b[8]; |
---|
807 | do |
---|
808 | *p-- = i%10 + '0'; |
---|
809 | while (i /= 10); |
---|
810 | return(++p); |
---|
811 | } |
---|
812 | |
---|
813 | /* |
---|
814 | * Get printcap entry for printer. |
---|
815 | */ |
---|
816 | chkprinter() |
---|
817 | { |
---|
818 | int status; |
---|
819 | char buf[BUFSIZ]; |
---|
820 | static char pbuf[BUFSIZ/2]; |
---|
821 | char *bp = pbuf; |
---|
822 | extern char *pgetstr(); |
---|
823 | |
---|
824 | #if defined(KERBEROS) && !defined(SERVER) |
---|
825 | short KA; |
---|
826 | #endif /* KERBEROS */ |
---|
827 | |
---|
828 | #ifdef HESIOD |
---|
829 | if ((status = pgetent(buf, printer)) <= 0) { |
---|
830 | if (pralias(alibuf, printer)) |
---|
831 | printer = alibuf; |
---|
832 | if ((status = hpgetent(buf, printer)) < 1) |
---|
833 | fatal("%s: unknown printer", printer); |
---|
834 | } |
---|
835 | #else |
---|
836 | if ((status = pgetent(buf, printer)) < 0) |
---|
837 | fatal("cannot open printer description file"); |
---|
838 | else if (status == 0) |
---|
839 | fatal("%s: unknown printer", printer); |
---|
840 | #endif HESIOD |
---|
841 | #ifdef SERVER |
---|
842 | if ((SD = pgetstr("sd", &bp)) == NULL) |
---|
843 | SD = DEFSPOOL; |
---|
844 | if ((LO = pgetstr("lo", &bp)) == NULL) |
---|
845 | LO = DEFLOCK; |
---|
846 | #endif SERVER |
---|
847 | RG = pgetstr("rg", &bp); |
---|
848 | if ((MX = pgetnum("mx")) < 0) |
---|
849 | MX = DEFMX; |
---|
850 | if ((MC = pgetnum("mc")) < 0) |
---|
851 | MC = DEFMAXCOPIES; |
---|
852 | #ifdef SERVER |
---|
853 | if ((DU = pgetnum("du")) < 0) |
---|
854 | DU = DEFUID; |
---|
855 | #endif SERVER |
---|
856 | SC = pgetflag("sc"); |
---|
857 | #ifndef SERVER |
---|
858 | if ((RM = pgetstr("rm",&bp)) == NULL) |
---|
859 | RM = host; /* If no remote machine name, assume */ |
---|
860 | /* its local */ |
---|
861 | if ((RP = pgetstr("rp",&bp)) == NULL) |
---|
862 | RP = printer; /* Use same name if no remote printer */ |
---|
863 | /* name */ |
---|
864 | #ifdef KERBEROS |
---|
865 | KA = pgetnum("ka"); |
---|
866 | if (KA > 0) |
---|
867 | use_kerberos = 1; |
---|
868 | else |
---|
869 | use_kerberos = 0; |
---|
870 | if (kerberos_override > -1) |
---|
871 | use_kerberos = kerberos_override; |
---|
872 | #endif KERBEROS |
---|
873 | #endif SERVER |
---|
874 | } |
---|
875 | |
---|
876 | /* |
---|
877 | * Make the temp files. |
---|
878 | */ |
---|
879 | mktemps() |
---|
880 | { |
---|
881 | #ifndef SERVER |
---|
882 | register int len, fd, n; |
---|
883 | register char *cp; |
---|
884 | #else SERVER |
---|
885 | register int len, fd, n; |
---|
886 | register char *cp; |
---|
887 | #endif SERVER |
---|
888 | char buf[BUFSIZ]; |
---|
889 | #ifndef SERVER |
---|
890 | char *maketemp(); |
---|
891 | #else SERVER |
---|
892 | char *mktemp(); |
---|
893 | #endif SERVER |
---|
894 | |
---|
895 | #ifndef SERVER |
---|
896 | (void) sprintf(buf, "%s/.seq", TMPDIR); |
---|
897 | #else SERVER |
---|
898 | (void) sprintf(buf, "%s/.seq", SD); |
---|
899 | #endif SERVER |
---|
900 | if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) { |
---|
901 | printf("%s: cannot create %s\n", name, buf); |
---|
902 | #ifndef SERVER |
---|
903 | cleanup(); |
---|
904 | #else SERVER |
---|
905 | exit(1); |
---|
906 | #endif SERVER |
---|
907 | } |
---|
908 | if (flock(fd, LOCK_EX)) { |
---|
909 | printf("%s: cannot lock %s\n", name, buf); |
---|
910 | #ifndef SERVER |
---|
911 | cleanup(); |
---|
912 | #else SERVER |
---|
913 | exit(1); |
---|
914 | #endif SERVER |
---|
915 | } |
---|
916 | n = 0; |
---|
917 | if ((len = read(fd, buf, sizeof(buf))) > 0) { |
---|
918 | for (cp = buf; len--; ) { |
---|
919 | if (*cp < '0' || *cp > '9') |
---|
920 | break; |
---|
921 | n = n * 10 + (*cp++ - '0'); |
---|
922 | } |
---|
923 | } |
---|
924 | #ifndef SERVER |
---|
925 | len = strlen(TMPDIR) + strlen(host) + 8; |
---|
926 | cfname = maketemp("cf", n, len); |
---|
927 | dfname = maketemp("df", n, len); |
---|
928 | inchar = strlen(TMPDIR) + 3; |
---|
929 | #else SERVER |
---|
930 | len = strlen(SD) + strlen(host) + 8; |
---|
931 | tfname = mktemp("tf", n, len); |
---|
932 | cfname = mktemp("cf", n, len); |
---|
933 | dfname = mktemp("df", n, len); |
---|
934 | inchar = strlen(SD) + 3; |
---|
935 | #endif SERVER |
---|
936 | n = (n + 1) % 1000; |
---|
937 | (void) lseek(fd, 0L, 0); |
---|
938 | sprintf(buf, "%03d\n", n); |
---|
939 | (void) write(fd, buf, strlen(buf)); |
---|
940 | (void) close(fd); /* unlocks as well */ |
---|
941 | } |
---|
942 | |
---|
943 | /* |
---|
944 | * Make a temp file name. |
---|
945 | */ |
---|
946 | char * |
---|
947 | #ifndef SERVER |
---|
948 | maketemp(id, num, len) |
---|
949 | #else SERVER |
---|
950 | mktemp(id, num, len) |
---|
951 | #endif SERVER |
---|
952 | char *id; |
---|
953 | int num, len; |
---|
954 | { |
---|
955 | register char *s; |
---|
956 | |
---|
957 | if ((s = malloc(len)) == NULL) |
---|
958 | fatal("out of memory"); |
---|
959 | #ifndef SERVER |
---|
960 | (void) sprintf(s, "%s/%sA%03d%s", TMPDIR, id, num, host); |
---|
961 | #else SERVER |
---|
962 | (void) sprintf(s, "%s/%sA%03d%s", SD, id, num, host); |
---|
963 | #endif SERVER |
---|
964 | return(s); |
---|
965 | } |
---|