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