Commit | Line | Data |
---|---|---|
51d1035a BJ |
1 | /* |
2 | * | |
3 | * 1.1 mike 5/77 - all files copied to spooler space | |
4 | * (see note below) | |
5 | * | |
6 | * 1.2 dlm 26 Sep 1977 | |
7 | * fix for allowing variable indents (-i flag) | |
8 | * | |
9 | * 1.3 dlm/njl 12 Dec 1977 | |
10 | * fix for open pipe when spawning progess (affects lpd) | |
11 | * | |
12 | * 1.4 dlm 24 Feb 1978 | |
13 | * test for data files; add -C option for classification | |
14 | * and change format of $L card; reversed 1.1 on copies | |
15 | * | |
16 | * 1.5 dlm 27 Mar 1978 | |
17 | * add job name and -h option | |
18 | * | |
19 | * 2.0 was 21 Dec 1978 | |
20 | * -h option changed to -J | |
21 | * added -H option to cause header page to be | |
22 | * printed, default is no header page | |
23 | * added -p option to cause files to be printed | |
24 | * using pr | |
25 | * default for classification changed | |
26 | * | |
27 | * 2.1 was 14 Mar 1979 | |
28 | * multiple printer logic changed, | |
29 | * printer number sent to daemon. | |
30 | * | |
31 | * 3.0 sjl 6 May 1980 | |
32 | * Mods for Version 7, plus portability | |
33 | * (in preparation for UNIX/24V) | |
34 | * | |
35 | * 3.1 sjl Oct 28 1980 | |
36 | * Mods for protected spooling area, see note below | |
37 | * | |
38 | * 3.2 sjl Mar 13 1981 | |
39 | * Add N card for file names to help out sq | |
40 | * | |
41 | * 3.3 sjl Mar 27 1981 from decvax!shannon | |
42 | * Mods and cleanup for 4bsd. | |
43 | * Send mail option added. | |
44 | * | |
45 | * 4.0 sjl Mar 28 1981 | |
46 | * Support multiple printers and daemons through termcap-like | |
47 | * data base | |
48 | * | |
49 | * 4.1 sjl Apr 28 1981 | |
50 | * Check for printer being down (mode 0 on device) | |
51 | * | |
52 | * 4.2 was May 1 1981 | |
53 | * Clean up handling of printcap database, add more defaults | |
54 | */ | |
55 | ||
56 | char lpr_id[] = "~|^`lpr.c:\t4.2\t1 May 1981\n"; | |
57 | ||
d0aeaf5a DF |
58 | /* |
59 | * Copyright (c) 1983 Regents of the University of California. | |
9d85c861 KB |
60 | * All rights reserved. |
61 | * | |
62 | * Redistribution and use in source and binary forms are permitted | |
a399f6c8 KB |
63 | * provided that the above copyright notice and this paragraph are |
64 | * duplicated in all such forms and that any documentation, | |
65 | * advertising materials, and other materials related to such | |
66 | * distribution and use acknowledge that the software was developed | |
67 | * by the University of California, Berkeley. The name of the | |
68 | * University may not be used to endorse or promote products derived | |
69 | * from this software without specific prior written permission. | |
70 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
71 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
72 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
d0aeaf5a DF |
73 | */ |
74 | ||
75 | #ifndef lint | |
76 | char copyright[] = | |
77 | "@(#) Copyright (c) 1983 Regents of the University of California.\n\ | |
78 | All rights reserved.\n"; | |
9d85c861 | 79 | #endif /* not lint */ |
d0aeaf5a | 80 | |
5f84f8f0 | 81 | #ifndef lint |
a399f6c8 | 82 | static char sccsid[] = "@(#)lpr.c 5.4 (Berkeley) %G%"; |
9d85c861 | 83 | #endif /* not lint */ |
5f84f8f0 | 84 | |
51d1035a BJ |
85 | /* |
86 | * lpr -- off line print | |
fdaeefb7 BJ |
87 | * |
88 | * Allows multiple printers and printers on remote machines by | |
89 | * using information from a printer data base. | |
51d1035a BJ |
90 | */ |
91 | ||
8fed920b RC |
92 | #include <stdio.h> |
93 | #include <sys/types.h> | |
94 | #include <sys/file.h> | |
95 | #include <sys/stat.h> | |
96 | #include <pwd.h> | |
5b9885a9 | 97 | #include <grp.h> |
8fed920b RC |
98 | #include <signal.h> |
99 | #include <ctype.h> | |
126fc76f | 100 | #include <syslog.h> |
8fed920b | 101 | #include "lp.local.h" |
51d1035a | 102 | |
fdaeefb7 BJ |
103 | char *tfname; /* tmp copy of cf before linking */ |
104 | char *cfname; /* daemon control files, linked from tf's */ | |
105 | char *dfname; /* data files */ | |
51d1035a BJ |
106 | |
107 | int nact; /* number of jobs to act on */ | |
fdaeefb7 | 108 | int tfd; /* control file descriptor */ |
51d1035a | 109 | int mailflg; /* send mail */ |
fdaeefb7 | 110 | int qflag; /* q job, but don't exec daemon */ |
878a0818 | 111 | char format = 'f'; /* format char for printing files */ |
fdaeefb7 | 112 | int rflag; /* remove files upon completion */ |
dfc1084e | 113 | int sflag; /* symbolic link flag */ |
51d1035a BJ |
114 | int inchar; /* location to increment char in file names */ |
115 | int ncopies = 1; /* # of copies to make */ | |
116 | int iflag; /* indentation wanted */ | |
117 | int indent; /* amount to indent */ | |
fdaeefb7 | 118 | int hdr = 1; /* print header or not (default is yes) */ |
878a0818 | 119 | int userid; /* user id */ |
dfc1084e | 120 | char *person; /* user name */ |
51d1035a | 121 | char *title; /* pr'ing title */ |
878a0818 RC |
122 | char *fonts[4]; /* troff font names */ |
123 | char *width; /* width for versatec printing */ | |
8fed920b | 124 | char host[32]; /* host name */ |
fdaeefb7 | 125 | char *class = host; /* class title on header page */ |
51d1035a | 126 | char *jobname; /* job name on header page */ |
8fed920b RC |
127 | char *name; /* program name */ |
128 | char *printer; /* printer name */ | |
98d189de | 129 | struct stat statb; |
8fed920b RC |
130 | |
131 | int MX; /* maximum number of blocks to copy */ | |
132 | int MC; /* maximum number of copies allowed */ | |
fa211baf | 133 | int DU; /* daemon user-id */ |
8fed920b RC |
134 | char *SD; /* spool directory */ |
135 | char *LO; /* lock file name */ | |
5b9885a9 | 136 | char *RG; /* restrict group */ |
8fed920b RC |
137 | short SC; /* suppress multiple copies */ |
138 | ||
139 | char *getenv(); | |
140 | char *rindex(); | |
af807caa | 141 | char *linked(); |
dfc1084e | 142 | int cleanup(); |
51d1035a | 143 | |
fdaeefb7 | 144 | /*ARGSUSED*/ |
51d1035a | 145 | main(argc, argv) |
6f038d7b RC |
146 | int argc; |
147 | char *argv[]; | |
51d1035a | 148 | { |
dfc1084e | 149 | extern struct passwd *getpwuid(); |
878a0818 | 150 | struct passwd *pw; |
5b9885a9 | 151 | struct group *gptr; |
878a0818 | 152 | extern char *itoa(); |
af807caa | 153 | register char *arg, *cp; |
98d189de | 154 | char buf[BUFSIZ]; |
dfc1084e | 155 | int i, f; |
fdaeefb7 | 156 | struct stat stb; |
51d1035a | 157 | |
6f038d7b | 158 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) |
dfc1084e | 159 | signal(SIGHUP, cleanup); |
6f038d7b | 160 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) |
dfc1084e | 161 | signal(SIGINT, cleanup); |
6f038d7b | 162 | if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) |
dfc1084e | 163 | signal(SIGQUIT, cleanup); |
6f038d7b | 164 | if (signal(SIGTERM, SIG_IGN) != SIG_IGN) |
dfc1084e | 165 | signal(SIGTERM, cleanup); |
fdaeefb7 | 166 | |
51d1035a | 167 | name = argv[0]; |
4d4caa50 | 168 | gethostname(host, sizeof (host)); |
126fc76f | 169 | openlog("lpd", 0, LOG_LPR); |
51d1035a | 170 | |
dfc1084e | 171 | while (argc > 1 && argv[1][0] == '-') { |
fdaeefb7 | 172 | argc--; |
dfc1084e | 173 | arg = *++argv; |
51d1035a BJ |
174 | switch (arg[1]) { |
175 | ||
fdaeefb7 | 176 | case 'P': /* specifiy printer name */ |
e5be50e6 RC |
177 | if (arg[2]) |
178 | printer = &arg[2]; | |
179 | else if (argc > 1) { | |
180 | argc--; | |
181 | printer = *++argv; | |
182 | } | |
51d1035a BJ |
183 | break; |
184 | ||
185 | case 'C': /* classification spec */ | |
186 | hdr++; | |
187 | if (arg[2]) | |
188 | class = &arg[2]; | |
878a0818 | 189 | else if (argc > 1) { |
51d1035a | 190 | argc--; |
fdaeefb7 | 191 | class = *++argv; |
51d1035a BJ |
192 | } |
193 | break; | |
194 | ||
fdaeefb7 BJ |
195 | case 'J': /* job name */ |
196 | hdr++; | |
197 | if (arg[2]) | |
51d1035a | 198 | jobname = &arg[2]; |
878a0818 | 199 | else if (argc > 1) { |
51d1035a | 200 | argc--; |
fdaeefb7 | 201 | jobname = *++argv; |
51d1035a BJ |
202 | } |
203 | break; | |
204 | ||
fdaeefb7 BJ |
205 | case 'T': /* pr's title line */ |
206 | if (arg[2]) | |
207 | title = &arg[2]; | |
878a0818 | 208 | else if (argc > 1) { |
fdaeefb7 BJ |
209 | argc--; |
210 | title = *++argv; | |
211 | } | |
51d1035a BJ |
212 | break; |
213 | ||
878a0818 RC |
214 | case 'l': /* literal output */ |
215 | case 'p': /* print using ``pr'' */ | |
dfc1084e | 216 | case 't': /* print troff output (cat files) */ |
a4f59913 | 217 | case 'n': /* print ditroff output */ |
dfc1084e RC |
218 | case 'd': /* print tex output (dvi files) */ |
219 | case 'g': /* print graph(1G) output */ | |
878a0818 RC |
220 | case 'c': /* print cifplot output */ |
221 | case 'v': /* print vplot output */ | |
222 | format = arg[1]; | |
223 | break; | |
224 | ||
dfc1084e RC |
225 | case 'f': /* print fortran output */ |
226 | format = 'r'; | |
227 | break; | |
228 | ||
878a0818 RC |
229 | case '4': /* troff fonts */ |
230 | case '3': | |
231 | case '2': | |
232 | case '1': | |
233 | if (argc > 1) { | |
234 | argc--; | |
235 | fonts[arg[1] - '1'] = *++argv; | |
878a0818 RC |
236 | } |
237 | break; | |
238 | ||
239 | case 'w': /* versatec page width */ | |
240 | width = arg+2; | |
51d1035a BJ |
241 | break; |
242 | ||
fdaeefb7 BJ |
243 | case 'r': /* remove file when done */ |
244 | rflag++; | |
51d1035a BJ |
245 | break; |
246 | ||
fdaeefb7 BJ |
247 | case 'm': /* send mail when done */ |
248 | mailflg++; | |
51d1035a BJ |
249 | break; |
250 | ||
fdaeefb7 | 251 | case 'h': /* toggle want of header page */ |
51d1035a BJ |
252 | hdr = !hdr; |
253 | break; | |
254 | ||
878a0818 | 255 | case 's': /* try to link files */ |
dfc1084e | 256 | sflag++; |
fdaeefb7 BJ |
257 | break; |
258 | ||
259 | case 'q': /* just q job */ | |
260 | qflag++; | |
261 | break; | |
262 | ||
263 | case 'i': /* indent output */ | |
264 | iflag++; | |
265 | indent = arg[2] ? atoi(&arg[2]) : 8; | |
266 | break; | |
267 | ||
af807caa | 268 | case '#': /* n copies */ |
eee484be RC |
269 | if (isdigit(arg[2])) { |
270 | i = atoi(&arg[2]); | |
271 | if (i > 0) | |
272 | ncopies = i; | |
273 | } | |
51d1035a | 274 | } |
51d1035a | 275 | } |
fdaeefb7 BJ |
276 | if (printer == NULL && (printer = getenv("PRINTER")) == NULL) |
277 | printer = DEFLP; | |
dfc1084e | 278 | chkprinter(printer); |
eee484be RC |
279 | if (SC && ncopies > 1) |
280 | fatal("multiple copies are not allowed"); | |
281 | if (MC > 0 && ncopies > MC) | |
282 | fatal("only %d copies are allowed", MC); | |
878a0818 | 283 | /* |
dfc1084e RC |
284 | * Get the identity of the person doing the lpr using the same |
285 | * algorithm as lprm. | |
878a0818 RC |
286 | */ |
287 | userid = getuid(); | |
dfc1084e RC |
288 | if ((pw = getpwuid(userid)) == NULL) |
289 | fatal("Who are you?"); | |
290 | person = pw->pw_name; | |
5b9885a9 MAN |
291 | /* |
292 | * Check for restricted group access. | |
293 | */ | |
ca1ba714 | 294 | if (RG != NULL) { |
5b9885a9 MAN |
295 | if ((gptr = getgrnam(RG)) == NULL) |
296 | fatal("Restricted group specified incorrectly"); | |
ca1ba714 RC |
297 | if (gptr->gr_gid != getgid()) { |
298 | while (*gptr->gr_mem != NULL) { | |
299 | if ((strcmp(person, *gptr->gr_mem)) == 0) | |
300 | break; | |
301 | gptr->gr_mem++; | |
302 | } | |
303 | if (*gptr->gr_mem == NULL) | |
304 | fatal("Not a member of the restricted group"); | |
5b9885a9 | 305 | } |
5b9885a9 | 306 | } |
eee484be RC |
307 | /* |
308 | * Check to make sure queuing is enabled if userid is not root. | |
309 | */ | |
8fed920b RC |
310 | (void) sprintf(buf, "%s/%s", SD, LO); |
311 | if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010)) | |
eee484be | 312 | fatal("Printer queue is disabled"); |
dfc1084e RC |
313 | /* |
314 | * Initialize the control file. | |
315 | */ | |
fdaeefb7 BJ |
316 | mktemps(); |
317 | tfd = nfile(tfname); | |
fa211baf | 318 | (void) fchown(tfd, DU, -1); /* owned by daemon for protection */ |
878a0818 RC |
319 | card('H', host); |
320 | card('P', person); | |
321 | if (hdr) { | |
322 | if (jobname == NULL) { | |
323 | if (argc == 1) | |
af807caa | 324 | jobname = "stdin"; |
878a0818 | 325 | else |
dfc1084e | 326 | jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1]; |
878a0818 RC |
327 | } |
328 | card('J', jobname); | |
329 | card('C', class); | |
330 | card('L', person); | |
51d1035a | 331 | } |
878a0818 RC |
332 | if (iflag) |
333 | card('I', itoa(indent)); | |
334 | if (mailflg) | |
335 | card('M', person); | |
a4f59913 | 336 | if (format == 't' || format == 'n' || format == 'd') |
878a0818 RC |
337 | for (i = 0; i < 4; i++) |
338 | if (fonts[i] != NULL) | |
339 | card('1'+i, fonts[i]); | |
af807caa | 340 | if (width != NULL) |
878a0818 | 341 | card('W', width); |
51d1035a | 342 | |
dfc1084e RC |
343 | /* |
344 | * Read the files and spool them. | |
345 | */ | |
6f038d7b | 346 | if (argc == 1) |
51d1035a | 347 | copy(0, " "); |
6f038d7b | 348 | else while (--argc) { |
af807caa | 349 | if ((f = test(arg = *++argv)) < 0) |
fdaeefb7 BJ |
350 | continue; /* file unreasonable */ |
351 | ||
4d4caa50 | 352 | if (sflag && (cp = linked(arg)) != NULL) { |
98d189de RC |
353 | (void) sprintf(buf, "%d %d", statb.st_dev, statb.st_ino); |
354 | card('S', buf); | |
878a0818 | 355 | if (format == 'p') |
fdaeefb7 | 356 | card('T', title ? title : arg); |
878a0818 RC |
357 | for (i = 0; i < ncopies; i++) |
358 | card(format, &dfname[inchar-2]); | |
fdaeefb7 | 359 | card('U', &dfname[inchar-2]); |
4d4caa50 | 360 | if (f) |
af807caa | 361 | card('U', cp); |
fdaeefb7 BJ |
362 | card('N', arg); |
363 | dfname[inchar]++; | |
51d1035a | 364 | nact++; |
4d4caa50 RC |
365 | continue; |
366 | } | |
367 | if (sflag) | |
368 | printf("%s: %s: not linked, copying instead\n", name, arg); | |
adec4d9e | 369 | if ((i = open(arg, O_RDONLY)) < 0) { |
4d4caa50 RC |
370 | printf("%s: cannot open %s\n", name, arg); |
371 | continue; | |
51d1035a | 372 | } |
4d4caa50 RC |
373 | copy(i, arg); |
374 | (void) close(i); | |
375 | if (f && unlink(arg) < 0) | |
376 | printf("%s: %s: not removed\n", name, arg); | |
51d1035a BJ |
377 | } |
378 | ||
6f038d7b | 379 | if (nact) { |
5c0abf7f | 380 | (void) close(tfd); |
51d1035a | 381 | tfname[inchar]--; |
5c0abf7f RC |
382 | /* |
383 | * Touch the control file to fix position in the queue. | |
384 | */ | |
adec4d9e | 385 | if ((tfd = open(tfname, O_RDWR)) >= 0) { |
5c0abf7f RC |
386 | char c; |
387 | ||
388 | if (read(tfd, &c, 1) == 1 && lseek(tfd, 0L, 0) == 0 && | |
389 | write(tfd, &c, 1) != 1) { | |
390 | printf("%s: cannot touch %s\n", name, tfname); | |
391 | tfname[inchar]++; | |
dfc1084e | 392 | cleanup(); |
5c0abf7f RC |
393 | } |
394 | (void) close(tfd); | |
395 | } | |
fdaeefb7 BJ |
396 | if (link(tfname, cfname) < 0) { |
397 | printf("%s: cannot rename %s\n", name, cfname); | |
51d1035a | 398 | tfname[inchar]++; |
dfc1084e | 399 | cleanup(); |
51d1035a BJ |
400 | } |
401 | unlink(tfname); | |
fdaeefb7 | 402 | if (qflag) /* just q things up */ |
51d1035a | 403 | exit(0); |
8fed920b | 404 | if (!startdaemon(printer)) |
dfc1084e | 405 | printf("jobs queued, but cannot start daemon.\n"); |
fdaeefb7 | 406 | exit(0); |
51d1035a | 407 | } |
dfc1084e RC |
408 | cleanup(); |
409 | /* NOTREACHED */ | |
51d1035a BJ |
410 | } |
411 | ||
fdaeefb7 BJ |
412 | /* |
413 | * Create the file n and copy from file descriptor f. | |
414 | */ | |
51d1035a | 415 | copy(f, n) |
6f038d7b RC |
416 | int f; |
417 | char n[]; | |
51d1035a | 418 | { |
fdaeefb7 | 419 | register int fd, i, nr, nc; |
98d189de | 420 | char buf[BUFSIZ]; |
51d1035a | 421 | |
878a0818 | 422 | if (format == 'p') |
fdaeefb7 BJ |
423 | card('T', title ? title : n); |
424 | for (i = 0; i < ncopies; i++) | |
878a0818 | 425 | card(format, &dfname[inchar-2]); |
fdaeefb7 BJ |
426 | card('U', &dfname[inchar-2]); |
427 | card('N', n); | |
428 | fd = nfile(dfname); | |
51d1035a | 429 | nr = nc = 0; |
6f038d7b | 430 | while ((i = read(f, buf, BUFSIZ)) > 0) { |
fdaeefb7 | 431 | if (write(fd, buf, i) != i) { |
51d1035a BJ |
432 | printf("%s: %s: temp file write error\n", name, n); |
433 | break; | |
434 | } | |
435 | nc += i; | |
6f038d7b | 436 | if (nc >= BUFSIZ) { |
51d1035a | 437 | nc -= BUFSIZ; |
c9f75218 RC |
438 | nr++; |
439 | if (MX > 0 && nr > MX) { | |
51d1035a BJ |
440 | printf("%s: %s: copy file is too large\n", name, n); |
441 | break; | |
442 | } | |
443 | } | |
444 | } | |
fdaeefb7 | 445 | (void) close(fd); |
bdddb896 RC |
446 | if (nc==0 && nr==0) |
447 | printf("%s: %s: empty input file\n", name, f ? n : "stdin"); | |
448 | else | |
449 | nact++; | |
51d1035a BJ |
450 | } |
451 | ||
fdaeefb7 | 452 | /* |
af807caa RC |
453 | * Try and link the file to dfname. Return a pointer to the full |
454 | * path name if successful. | |
fdaeefb7 | 455 | */ |
af807caa | 456 | char * |
fdaeefb7 BJ |
457 | linked(file) |
458 | register char *file; | |
459 | { | |
460 | register char *cp; | |
4d4caa50 | 461 | static char buf[BUFSIZ]; |
fdaeefb7 | 462 | |
fdaeefb7 BJ |
463 | if (*file != '/') { |
464 | if (getwd(buf) == NULL) | |
af807caa | 465 | return(NULL); |
fdaeefb7 BJ |
466 | while (file[0] == '.') { |
467 | switch (file[1]) { | |
468 | case '/': | |
469 | file += 2; | |
470 | continue; | |
471 | case '.': | |
472 | if (file[2] == '/') { | |
473 | if ((cp = rindex(buf, '/')) != NULL) | |
474 | *cp = '\0'; | |
475 | file += 3; | |
476 | continue; | |
477 | } | |
478 | } | |
479 | break; | |
480 | } | |
481 | strcat(buf, "/"); | |
482 | strcat(buf, file); | |
483 | file = buf; | |
484 | } | |
af807caa | 485 | return(symlink(file, dfname) ? NULL : file); |
fdaeefb7 BJ |
486 | } |
487 | ||
488 | /* | |
489 | * Put a line into the control file. | |
490 | */ | |
51d1035a | 491 | card(c, p2) |
6f038d7b | 492 | register char c, *p2; |
51d1035a | 493 | { |
98d189de | 494 | char buf[BUFSIZ]; |
51d1035a | 495 | register char *p1 = buf; |
fdaeefb7 | 496 | register int len = 2; |
51d1035a BJ |
497 | |
498 | *p1++ = c; | |
6f038d7b | 499 | while ((c = *p2++) != '\0') { |
51d1035a | 500 | *p1++ = c; |
fdaeefb7 | 501 | len++; |
51d1035a BJ |
502 | } |
503 | *p1++ = '\n'; | |
fdaeefb7 | 504 | write(tfd, buf, len); |
51d1035a BJ |
505 | } |
506 | ||
fdaeefb7 BJ |
507 | /* |
508 | * Create a new file in the spool directory. | |
509 | */ | |
51d1035a | 510 | nfile(n) |
6f038d7b | 511 | char *n; |
51d1035a BJ |
512 | { |
513 | register f; | |
fdaeefb7 | 514 | int oldumask = umask(0); /* should block signals */ |
51d1035a | 515 | |
6f038d7b RC |
516 | f = creat(n, FILMOD); |
517 | (void) umask(oldumask); | |
518 | if (f < 0) { | |
51d1035a | 519 | printf("%s: cannot create %s\n", name, n); |
dfc1084e | 520 | cleanup(); |
51d1035a | 521 | } |
fa211baf RC |
522 | if (fchown(f, userid, -1) < 0) { |
523 | printf("%s: cannot chown %s\n", name, n); | |
524 | cleanup(); | |
525 | } | |
5c0abf7f RC |
526 | if (++n[inchar] > 'z') { |
527 | if (++n[inchar-2] == 't') { | |
528 | printf("too many files - break up the job\n"); | |
dfc1084e | 529 | cleanup(); |
5c0abf7f RC |
530 | } |
531 | n[inchar] = 'A'; | |
532 | } else if (n[inchar] == '[') | |
533 | n[inchar] = 'a'; | |
fdaeefb7 | 534 | return(f); |
51d1035a BJ |
535 | } |
536 | ||
fdaeefb7 BJ |
537 | /* |
538 | * Cleanup after interrupts and errors. | |
539 | */ | |
dfc1084e | 540 | cleanup() |
51d1035a BJ |
541 | { |
542 | register i; | |
543 | ||
544 | signal(SIGHUP, SIG_IGN); | |
545 | signal(SIGINT, SIG_IGN); | |
546 | signal(SIGQUIT, SIG_IGN); | |
547 | signal(SIGTERM, SIG_IGN); | |
548 | i = inchar; | |
549 | if (tfname) | |
c9f75218 | 550 | do |
51d1035a | 551 | unlink(tfname); |
c9f75218 | 552 | while (tfname[i]-- != 'A'); |
51d1035a | 553 | if (cfname) |
c9f75218 | 554 | do |
51d1035a | 555 | unlink(cfname); |
c9f75218 | 556 | while (cfname[i]-- != 'A'); |
51d1035a | 557 | if (dfname) |
c9f75218 RC |
558 | do { |
559 | do | |
5c0abf7f | 560 | unlink(dfname); |
c9f75218 RC |
561 | while (dfname[i]-- != 'A'); |
562 | dfname[i] = 'z'; | |
563 | } while (dfname[i-2]-- != 'd'); | |
5c3a8db4 | 564 | exit(1); |
51d1035a BJ |
565 | } |
566 | ||
fdaeefb7 BJ |
567 | /* |
568 | * Test to see if this is a printable file. | |
4d4caa50 | 569 | * Return -1 if it is not, 0 if its printable, and 1 if |
af807caa | 570 | * we should remove it after printing. |
fdaeefb7 | 571 | */ |
51d1035a | 572 | test(file) |
6f038d7b | 573 | char *file; |
51d1035a | 574 | { |
fdaeefb7 | 575 | struct exec execb; |
af807caa RC |
576 | register int fd; |
577 | register char *cp; | |
51d1035a BJ |
578 | |
579 | if (access(file, 4) < 0) { | |
580 | printf("%s: cannot access %s\n", name, file); | |
fdaeefb7 | 581 | return(-1); |
51d1035a | 582 | } |
fdaeefb7 | 583 | if (stat(file, &statb) < 0) { |
51d1035a | 584 | printf("%s: cannot stat %s\n", name, file); |
fdaeefb7 | 585 | return(-1); |
51d1035a | 586 | } |
fdaeefb7 | 587 | if ((statb.st_mode & S_IFMT) == S_IFDIR) { |
51d1035a | 588 | printf("%s: %s is a directory\n", name, file); |
fdaeefb7 | 589 | return(-1); |
51d1035a | 590 | } |
bdddb896 RC |
591 | if (statb.st_size == 0) { |
592 | printf("%s: %s is an empty file\n", name, file); | |
593 | return(-1); | |
594 | } | |
adec4d9e | 595 | if ((fd = open(file, O_RDONLY)) < 0) { |
51d1035a | 596 | printf("%s: cannot open %s\n", name, file); |
fdaeefb7 | 597 | return(-1); |
51d1035a | 598 | } |
fdaeefb7 BJ |
599 | if (read(fd, &execb, sizeof(execb)) == sizeof(execb)) |
600 | switch(execb.a_magic) { | |
51d1035a BJ |
601 | case A_MAGIC1: |
602 | case A_MAGIC2: | |
603 | case A_MAGIC3: | |
604 | #ifdef A_MAGIC4 | |
605 | case A_MAGIC4: | |
606 | #endif | |
607 | printf("%s: %s is an executable program", name, file); | |
608 | goto error1; | |
609 | ||
610 | case ARMAG: | |
611 | printf("%s: %s is an archive file", name, file); | |
612 | goto error1; | |
613 | } | |
fdaeefb7 | 614 | (void) close(fd); |
af807caa RC |
615 | if (rflag) { |
616 | if ((cp = rindex(file, '/')) == NULL) { | |
617 | if (access(".", 2) == 0) | |
4d4caa50 | 618 | return(1); |
af807caa | 619 | } else { |
fdaeefb7 | 620 | *cp = '\0'; |
4d4caa50 | 621 | fd = access(file, 2); |
fdaeefb7 | 622 | *cp = '/'; |
4d4caa50 RC |
623 | if (fd == 0) |
624 | return(1); | |
878a0818 | 625 | } |
4d4caa50 | 626 | printf("%s: %s: is not removable by you\n", name, file); |
fdaeefb7 | 627 | } |
4d4caa50 | 628 | return(0); |
51d1035a | 629 | |
51d1035a BJ |
630 | error1: |
631 | printf(" and is unprintable\n"); | |
fdaeefb7 BJ |
632 | (void) close(fd); |
633 | return(-1); | |
51d1035a BJ |
634 | } |
635 | ||
636 | /* | |
637 | * itoa - integer to string conversion | |
638 | */ | |
639 | char * | |
640 | itoa(i) | |
6f038d7b | 641 | register int i; |
51d1035a BJ |
642 | { |
643 | static char b[10] = "########"; | |
644 | register char *p; | |
645 | ||
646 | p = &b[8]; | |
647 | do | |
648 | *p-- = i%10 + '0'; | |
649 | while (i /= 10); | |
fdaeefb7 | 650 | return(++p); |
51d1035a BJ |
651 | } |
652 | ||
653 | /* | |
654 | * Perform lookup for printer name or abbreviation -- | |
51d1035a BJ |
655 | */ |
656 | chkprinter(s) | |
8fed920b | 657 | char *s; |
51d1035a | 658 | { |
dfc1084e | 659 | int status; |
98d189de | 660 | char buf[BUFSIZ]; |
8fed920b RC |
661 | static char pbuf[BUFSIZ/2]; |
662 | char *bp = pbuf; | |
663 | extern char *pgetstr(); | |
dfc1084e | 664 | |
8fed920b | 665 | if ((status = pgetent(buf, s)) < 0) |
dfc1084e RC |
666 | fatal("cannot open printer description file"); |
667 | else if (status == 0) | |
8fed920b | 668 | fatal("%s: unknown printer", s); |
fdaeefb7 BJ |
669 | if ((SD = pgetstr("sd", &bp)) == NULL) |
670 | SD = DEFSPOOL; | |
4d4caa50 RC |
671 | if ((LO = pgetstr("lo", &bp)) == NULL) |
672 | LO = DEFLOCK; | |
ca1ba714 | 673 | RG = pgetstr("rg", &bp); |
51d1035a BJ |
674 | if ((MX = pgetnum("mx")) < 0) |
675 | MX = DEFMX; | |
eee484be RC |
676 | if ((MC = pgetnum("mc")) < 0) |
677 | MC = DEFMAXCOPIES; | |
fa211baf RC |
678 | if ((DU = pgetnum("du")) < 0) |
679 | DU = DEFUID; | |
eee484be | 680 | SC = pgetflag("sc"); |
fdaeefb7 BJ |
681 | } |
682 | ||
683 | /* | |
684 | * Make the temp files. | |
685 | */ | |
686 | mktemps() | |
687 | { | |
eee484be RC |
688 | register int c, len, fd, n; |
689 | register char *cp; | |
98d189de | 690 | char buf[BUFSIZ]; |
8fed920b | 691 | char *mktemp(); |
fdaeefb7 BJ |
692 | |
693 | (void) sprintf(buf, "%s/.seq", SD); | |
eee484be RC |
694 | if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) { |
695 | printf("%s: cannot create %s\n", name, buf); | |
696 | exit(1); | |
697 | } | |
698 | if (flock(fd, LOCK_EX)) { | |
699 | printf("%s: cannot lock %s\n", name, buf); | |
700 | exit(1); | |
701 | } | |
702 | n = 0; | |
703 | if ((len = read(fd, buf, sizeof(buf))) > 0) { | |
704 | for (cp = buf; len--; ) { | |
705 | if (*cp < '0' || *cp > '9') | |
706 | break; | |
707 | n = n * 10 + (*cp++ - '0'); | |
fdaeefb7 | 708 | } |
fdaeefb7 BJ |
709 | } |
710 | len = strlen(SD) + strlen(host) + 8; | |
711 | tfname = mktemp("tf", n, len); | |
712 | cfname = mktemp("cf", n, len); | |
713 | dfname = mktemp("df", n, len); | |
714 | inchar = strlen(SD) + 3; | |
715 | n = (n + 1) % 1000; | |
eee484be RC |
716 | (void) lseek(fd, 0L, 0); |
717 | sprintf(buf, "%03d\n", n); | |
718 | (void) write(fd, buf, strlen(buf)); | |
719 | (void) close(fd); /* unlocks as well */ | |
51d1035a BJ |
720 | } |
721 | ||
722 | /* | |
fdaeefb7 | 723 | * Make a temp file name. |
51d1035a BJ |
724 | */ |
725 | char * | |
fdaeefb7 BJ |
726 | mktemp(id, num, len) |
727 | char *id; | |
728 | int num, len; | |
51d1035a BJ |
729 | { |
730 | register char *s; | |
8fed920b | 731 | extern char *malloc(); |
51d1035a | 732 | |
dfc1084e RC |
733 | if ((s = malloc(len)) == NULL) |
734 | fatal("out of memory"); | |
fdaeefb7 BJ |
735 | (void) sprintf(s, "%s/%sA%03d%s", SD, id, num, host); |
736 | return(s); | |
51d1035a | 737 | } |
8fed920b RC |
738 | |
739 | /*VARARGS1*/ | |
740 | fatal(msg, a1, a2, a3) | |
741 | char *msg; | |
742 | { | |
743 | printf("%s: ", name); | |
744 | printf(msg, a1, a2, a3); | |
745 | putchar('\n'); | |
746 | exit(1); | |
747 | } |