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[] = | |
3b5e183c | 77 | "@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\ |
d0aeaf5a | 78 | All rights reserved.\n"; |
9d85c861 | 79 | #endif /* not lint */ |
d0aeaf5a | 80 | |
5f84f8f0 | 81 | #ifndef lint |
7abf8d65 | 82 | static char sccsid[] = "@(#)lpr.c 5.6 (Berkeley) %G%"; |
9d85c861 | 83 | #endif /* not lint */ |
51d1035a BJ |
84 | /* |
85 | * lpr -- off line print | |
fdaeefb7 BJ |
86 | * |
87 | * Allows multiple printers and printers on remote machines by | |
88 | * using information from a printer data base. | |
51d1035a BJ |
89 | */ |
90 | ||
8fed920b RC |
91 | #include <stdio.h> |
92 | #include <sys/types.h> | |
93 | #include <sys/file.h> | |
94 | #include <sys/stat.h> | |
95 | #include <pwd.h> | |
5b9885a9 | 96 | #include <grp.h> |
8fed920b RC |
97 | #include <signal.h> |
98 | #include <ctype.h> | |
126fc76f | 99 | #include <syslog.h> |
8fed920b | 100 | #include "lp.local.h" |
7abf8d65 | 101 | #include "pathnames.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 | ||
3b5e183c KS |
195 | case 'U': /* user name */ |
196 | hdr++; | |
197 | if (arg[2]) | |
198 | person = &arg[2]; | |
199 | else if (argc > 1) { | |
200 | argc--; | |
201 | person = *++argv; | |
202 | } | |
203 | break; | |
204 | ||
fdaeefb7 BJ |
205 | case 'J': /* job name */ |
206 | hdr++; | |
207 | if (arg[2]) | |
51d1035a | 208 | jobname = &arg[2]; |
878a0818 | 209 | else if (argc > 1) { |
51d1035a | 210 | argc--; |
fdaeefb7 | 211 | jobname = *++argv; |
51d1035a BJ |
212 | } |
213 | break; | |
214 | ||
fdaeefb7 BJ |
215 | case 'T': /* pr's title line */ |
216 | if (arg[2]) | |
217 | title = &arg[2]; | |
878a0818 | 218 | else if (argc > 1) { |
fdaeefb7 BJ |
219 | argc--; |
220 | title = *++argv; | |
221 | } | |
51d1035a BJ |
222 | break; |
223 | ||
878a0818 RC |
224 | case 'l': /* literal output */ |
225 | case 'p': /* print using ``pr'' */ | |
dfc1084e | 226 | case 't': /* print troff output (cat files) */ |
a4f59913 | 227 | case 'n': /* print ditroff output */ |
dfc1084e RC |
228 | case 'd': /* print tex output (dvi files) */ |
229 | case 'g': /* print graph(1G) output */ | |
878a0818 RC |
230 | case 'c': /* print cifplot output */ |
231 | case 'v': /* print vplot output */ | |
232 | format = arg[1]; | |
233 | break; | |
234 | ||
dfc1084e RC |
235 | case 'f': /* print fortran output */ |
236 | format = 'r'; | |
237 | break; | |
238 | ||
878a0818 RC |
239 | case '4': /* troff fonts */ |
240 | case '3': | |
241 | case '2': | |
242 | case '1': | |
243 | if (argc > 1) { | |
244 | argc--; | |
245 | fonts[arg[1] - '1'] = *++argv; | |
878a0818 RC |
246 | } |
247 | break; | |
248 | ||
249 | case 'w': /* versatec page width */ | |
250 | width = arg+2; | |
51d1035a BJ |
251 | break; |
252 | ||
fdaeefb7 BJ |
253 | case 'r': /* remove file when done */ |
254 | rflag++; | |
51d1035a BJ |
255 | break; |
256 | ||
fdaeefb7 BJ |
257 | case 'm': /* send mail when done */ |
258 | mailflg++; | |
51d1035a BJ |
259 | break; |
260 | ||
fdaeefb7 | 261 | case 'h': /* toggle want of header page */ |
51d1035a BJ |
262 | hdr = !hdr; |
263 | break; | |
264 | ||
878a0818 | 265 | case 's': /* try to link files */ |
dfc1084e | 266 | sflag++; |
fdaeefb7 BJ |
267 | break; |
268 | ||
269 | case 'q': /* just q job */ | |
270 | qflag++; | |
271 | break; | |
272 | ||
273 | case 'i': /* indent output */ | |
274 | iflag++; | |
275 | indent = arg[2] ? atoi(&arg[2]) : 8; | |
276 | break; | |
277 | ||
af807caa | 278 | case '#': /* n copies */ |
eee484be RC |
279 | if (isdigit(arg[2])) { |
280 | i = atoi(&arg[2]); | |
281 | if (i > 0) | |
282 | ncopies = i; | |
283 | } | |
51d1035a | 284 | } |
51d1035a | 285 | } |
fdaeefb7 BJ |
286 | if (printer == NULL && (printer = getenv("PRINTER")) == NULL) |
287 | printer = DEFLP; | |
dfc1084e | 288 | chkprinter(printer); |
eee484be RC |
289 | if (SC && ncopies > 1) |
290 | fatal("multiple copies are not allowed"); | |
291 | if (MC > 0 && ncopies > MC) | |
292 | fatal("only %d copies are allowed", MC); | |
878a0818 | 293 | /* |
dfc1084e RC |
294 | * Get the identity of the person doing the lpr using the same |
295 | * algorithm as lprm. | |
878a0818 RC |
296 | */ |
297 | userid = getuid(); | |
3b5e183c KS |
298 | if (userid != DU || person == 0) { |
299 | if ((pw = getpwuid(userid)) == NULL) | |
300 | fatal("Who are you?"); | |
301 | person = pw->pw_name; | |
302 | } | |
5b9885a9 MAN |
303 | /* |
304 | * Check for restricted group access. | |
305 | */ | |
3b5e183c | 306 | if (RG != NULL && userid != DU) { |
5b9885a9 MAN |
307 | if ((gptr = getgrnam(RG)) == NULL) |
308 | fatal("Restricted group specified incorrectly"); | |
ca1ba714 RC |
309 | if (gptr->gr_gid != getgid()) { |
310 | while (*gptr->gr_mem != NULL) { | |
311 | if ((strcmp(person, *gptr->gr_mem)) == 0) | |
312 | break; | |
313 | gptr->gr_mem++; | |
314 | } | |
315 | if (*gptr->gr_mem == NULL) | |
316 | fatal("Not a member of the restricted group"); | |
5b9885a9 | 317 | } |
5b9885a9 | 318 | } |
eee484be RC |
319 | /* |
320 | * Check to make sure queuing is enabled if userid is not root. | |
321 | */ | |
8fed920b RC |
322 | (void) sprintf(buf, "%s/%s", SD, LO); |
323 | if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010)) | |
eee484be | 324 | fatal("Printer queue is disabled"); |
dfc1084e RC |
325 | /* |
326 | * Initialize the control file. | |
327 | */ | |
fdaeefb7 BJ |
328 | mktemps(); |
329 | tfd = nfile(tfname); | |
fa211baf | 330 | (void) fchown(tfd, DU, -1); /* owned by daemon for protection */ |
878a0818 RC |
331 | card('H', host); |
332 | card('P', person); | |
333 | if (hdr) { | |
334 | if (jobname == NULL) { | |
335 | if (argc == 1) | |
af807caa | 336 | jobname = "stdin"; |
878a0818 | 337 | else |
dfc1084e | 338 | jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1]; |
878a0818 RC |
339 | } |
340 | card('J', jobname); | |
341 | card('C', class); | |
342 | card('L', person); | |
51d1035a | 343 | } |
878a0818 RC |
344 | if (iflag) |
345 | card('I', itoa(indent)); | |
346 | if (mailflg) | |
347 | card('M', person); | |
a4f59913 | 348 | if (format == 't' || format == 'n' || format == 'd') |
878a0818 RC |
349 | for (i = 0; i < 4; i++) |
350 | if (fonts[i] != NULL) | |
351 | card('1'+i, fonts[i]); | |
af807caa | 352 | if (width != NULL) |
878a0818 | 353 | card('W', width); |
51d1035a | 354 | |
dfc1084e RC |
355 | /* |
356 | * Read the files and spool them. | |
357 | */ | |
6f038d7b | 358 | if (argc == 1) |
51d1035a | 359 | copy(0, " "); |
6f038d7b | 360 | else while (--argc) { |
af807caa | 361 | if ((f = test(arg = *++argv)) < 0) |
fdaeefb7 BJ |
362 | continue; /* file unreasonable */ |
363 | ||
4d4caa50 | 364 | if (sflag && (cp = linked(arg)) != NULL) { |
98d189de RC |
365 | (void) sprintf(buf, "%d %d", statb.st_dev, statb.st_ino); |
366 | card('S', buf); | |
878a0818 | 367 | if (format == 'p') |
fdaeefb7 | 368 | card('T', title ? title : arg); |
878a0818 RC |
369 | for (i = 0; i < ncopies; i++) |
370 | card(format, &dfname[inchar-2]); | |
fdaeefb7 | 371 | card('U', &dfname[inchar-2]); |
4d4caa50 | 372 | if (f) |
af807caa | 373 | card('U', cp); |
fdaeefb7 BJ |
374 | card('N', arg); |
375 | dfname[inchar]++; | |
51d1035a | 376 | nact++; |
4d4caa50 RC |
377 | continue; |
378 | } | |
379 | if (sflag) | |
380 | printf("%s: %s: not linked, copying instead\n", name, arg); | |
adec4d9e | 381 | if ((i = open(arg, O_RDONLY)) < 0) { |
4d4caa50 RC |
382 | printf("%s: cannot open %s\n", name, arg); |
383 | continue; | |
51d1035a | 384 | } |
4d4caa50 RC |
385 | copy(i, arg); |
386 | (void) close(i); | |
387 | if (f && unlink(arg) < 0) | |
388 | printf("%s: %s: not removed\n", name, arg); | |
51d1035a BJ |
389 | } |
390 | ||
6f038d7b | 391 | if (nact) { |
5c0abf7f | 392 | (void) close(tfd); |
51d1035a | 393 | tfname[inchar]--; |
5c0abf7f RC |
394 | /* |
395 | * Touch the control file to fix position in the queue. | |
396 | */ | |
adec4d9e | 397 | if ((tfd = open(tfname, O_RDWR)) >= 0) { |
5c0abf7f RC |
398 | char c; |
399 | ||
400 | if (read(tfd, &c, 1) == 1 && lseek(tfd, 0L, 0) == 0 && | |
401 | write(tfd, &c, 1) != 1) { | |
402 | printf("%s: cannot touch %s\n", name, tfname); | |
403 | tfname[inchar]++; | |
dfc1084e | 404 | cleanup(); |
5c0abf7f RC |
405 | } |
406 | (void) close(tfd); | |
407 | } | |
fdaeefb7 BJ |
408 | if (link(tfname, cfname) < 0) { |
409 | printf("%s: cannot rename %s\n", name, cfname); | |
51d1035a | 410 | tfname[inchar]++; |
dfc1084e | 411 | cleanup(); |
51d1035a BJ |
412 | } |
413 | unlink(tfname); | |
fdaeefb7 | 414 | if (qflag) /* just q things up */ |
51d1035a | 415 | exit(0); |
8fed920b | 416 | if (!startdaemon(printer)) |
dfc1084e | 417 | printf("jobs queued, but cannot start daemon.\n"); |
fdaeefb7 | 418 | exit(0); |
51d1035a | 419 | } |
dfc1084e RC |
420 | cleanup(); |
421 | /* NOTREACHED */ | |
51d1035a BJ |
422 | } |
423 | ||
fdaeefb7 BJ |
424 | /* |
425 | * Create the file n and copy from file descriptor f. | |
426 | */ | |
51d1035a | 427 | copy(f, n) |
6f038d7b RC |
428 | int f; |
429 | char n[]; | |
51d1035a | 430 | { |
fdaeefb7 | 431 | register int fd, i, nr, nc; |
98d189de | 432 | char buf[BUFSIZ]; |
51d1035a | 433 | |
878a0818 | 434 | if (format == 'p') |
fdaeefb7 BJ |
435 | card('T', title ? title : n); |
436 | for (i = 0; i < ncopies; i++) | |
878a0818 | 437 | card(format, &dfname[inchar-2]); |
fdaeefb7 BJ |
438 | card('U', &dfname[inchar-2]); |
439 | card('N', n); | |
440 | fd = nfile(dfname); | |
51d1035a | 441 | nr = nc = 0; |
6f038d7b | 442 | while ((i = read(f, buf, BUFSIZ)) > 0) { |
fdaeefb7 | 443 | if (write(fd, buf, i) != i) { |
51d1035a BJ |
444 | printf("%s: %s: temp file write error\n", name, n); |
445 | break; | |
446 | } | |
447 | nc += i; | |
6f038d7b | 448 | if (nc >= BUFSIZ) { |
51d1035a | 449 | nc -= BUFSIZ; |
c9f75218 RC |
450 | nr++; |
451 | if (MX > 0 && nr > MX) { | |
51d1035a BJ |
452 | printf("%s: %s: copy file is too large\n", name, n); |
453 | break; | |
454 | } | |
455 | } | |
456 | } | |
fdaeefb7 | 457 | (void) close(fd); |
bdddb896 RC |
458 | if (nc==0 && nr==0) |
459 | printf("%s: %s: empty input file\n", name, f ? n : "stdin"); | |
460 | else | |
461 | nact++; | |
51d1035a BJ |
462 | } |
463 | ||
fdaeefb7 | 464 | /* |
af807caa RC |
465 | * Try and link the file to dfname. Return a pointer to the full |
466 | * path name if successful. | |
fdaeefb7 | 467 | */ |
af807caa | 468 | char * |
fdaeefb7 BJ |
469 | linked(file) |
470 | register char *file; | |
471 | { | |
472 | register char *cp; | |
4d4caa50 | 473 | static char buf[BUFSIZ]; |
fdaeefb7 | 474 | |
fdaeefb7 BJ |
475 | if (*file != '/') { |
476 | if (getwd(buf) == NULL) | |
af807caa | 477 | return(NULL); |
fdaeefb7 BJ |
478 | while (file[0] == '.') { |
479 | switch (file[1]) { | |
480 | case '/': | |
481 | file += 2; | |
482 | continue; | |
483 | case '.': | |
484 | if (file[2] == '/') { | |
485 | if ((cp = rindex(buf, '/')) != NULL) | |
486 | *cp = '\0'; | |
487 | file += 3; | |
488 | continue; | |
489 | } | |
490 | } | |
491 | break; | |
492 | } | |
493 | strcat(buf, "/"); | |
494 | strcat(buf, file); | |
495 | file = buf; | |
496 | } | |
af807caa | 497 | return(symlink(file, dfname) ? NULL : file); |
fdaeefb7 BJ |
498 | } |
499 | ||
500 | /* | |
501 | * Put a line into the control file. | |
502 | */ | |
51d1035a | 503 | card(c, p2) |
6f038d7b | 504 | register char c, *p2; |
51d1035a | 505 | { |
98d189de | 506 | char buf[BUFSIZ]; |
51d1035a | 507 | register char *p1 = buf; |
fdaeefb7 | 508 | register int len = 2; |
51d1035a BJ |
509 | |
510 | *p1++ = c; | |
6f038d7b | 511 | while ((c = *p2++) != '\0') { |
51d1035a | 512 | *p1++ = c; |
fdaeefb7 | 513 | len++; |
51d1035a BJ |
514 | } |
515 | *p1++ = '\n'; | |
fdaeefb7 | 516 | write(tfd, buf, len); |
51d1035a BJ |
517 | } |
518 | ||
fdaeefb7 BJ |
519 | /* |
520 | * Create a new file in the spool directory. | |
521 | */ | |
51d1035a | 522 | nfile(n) |
6f038d7b | 523 | char *n; |
51d1035a BJ |
524 | { |
525 | register f; | |
fdaeefb7 | 526 | int oldumask = umask(0); /* should block signals */ |
51d1035a | 527 | |
6f038d7b RC |
528 | f = creat(n, FILMOD); |
529 | (void) umask(oldumask); | |
530 | if (f < 0) { | |
51d1035a | 531 | printf("%s: cannot create %s\n", name, n); |
dfc1084e | 532 | cleanup(); |
51d1035a | 533 | } |
fa211baf RC |
534 | if (fchown(f, userid, -1) < 0) { |
535 | printf("%s: cannot chown %s\n", name, n); | |
536 | cleanup(); | |
537 | } | |
5c0abf7f RC |
538 | if (++n[inchar] > 'z') { |
539 | if (++n[inchar-2] == 't') { | |
540 | printf("too many files - break up the job\n"); | |
dfc1084e | 541 | cleanup(); |
5c0abf7f RC |
542 | } |
543 | n[inchar] = 'A'; | |
544 | } else if (n[inchar] == '[') | |
545 | n[inchar] = 'a'; | |
fdaeefb7 | 546 | return(f); |
51d1035a BJ |
547 | } |
548 | ||
fdaeefb7 BJ |
549 | /* |
550 | * Cleanup after interrupts and errors. | |
551 | */ | |
dfc1084e | 552 | cleanup() |
51d1035a BJ |
553 | { |
554 | register i; | |
555 | ||
556 | signal(SIGHUP, SIG_IGN); | |
557 | signal(SIGINT, SIG_IGN); | |
558 | signal(SIGQUIT, SIG_IGN); | |
559 | signal(SIGTERM, SIG_IGN); | |
560 | i = inchar; | |
561 | if (tfname) | |
c9f75218 | 562 | do |
51d1035a | 563 | unlink(tfname); |
c9f75218 | 564 | while (tfname[i]-- != 'A'); |
51d1035a | 565 | if (cfname) |
c9f75218 | 566 | do |
51d1035a | 567 | unlink(cfname); |
c9f75218 | 568 | while (cfname[i]-- != 'A'); |
51d1035a | 569 | if (dfname) |
c9f75218 RC |
570 | do { |
571 | do | |
5c0abf7f | 572 | unlink(dfname); |
c9f75218 RC |
573 | while (dfname[i]-- != 'A'); |
574 | dfname[i] = 'z'; | |
575 | } while (dfname[i-2]-- != 'd'); | |
5c3a8db4 | 576 | exit(1); |
51d1035a BJ |
577 | } |
578 | ||
fdaeefb7 BJ |
579 | /* |
580 | * Test to see if this is a printable file. | |
4d4caa50 | 581 | * Return -1 if it is not, 0 if its printable, and 1 if |
af807caa | 582 | * we should remove it after printing. |
fdaeefb7 | 583 | */ |
51d1035a | 584 | test(file) |
6f038d7b | 585 | char *file; |
51d1035a | 586 | { |
fdaeefb7 | 587 | struct exec execb; |
af807caa RC |
588 | register int fd; |
589 | register char *cp; | |
51d1035a BJ |
590 | |
591 | if (access(file, 4) < 0) { | |
592 | printf("%s: cannot access %s\n", name, file); | |
fdaeefb7 | 593 | return(-1); |
51d1035a | 594 | } |
fdaeefb7 | 595 | if (stat(file, &statb) < 0) { |
51d1035a | 596 | printf("%s: cannot stat %s\n", name, file); |
fdaeefb7 | 597 | return(-1); |
51d1035a | 598 | } |
fdaeefb7 | 599 | if ((statb.st_mode & S_IFMT) == S_IFDIR) { |
51d1035a | 600 | printf("%s: %s is a directory\n", name, file); |
fdaeefb7 | 601 | return(-1); |
51d1035a | 602 | } |
bdddb896 RC |
603 | if (statb.st_size == 0) { |
604 | printf("%s: %s is an empty file\n", name, file); | |
605 | return(-1); | |
606 | } | |
adec4d9e | 607 | if ((fd = open(file, O_RDONLY)) < 0) { |
51d1035a | 608 | printf("%s: cannot open %s\n", name, file); |
fdaeefb7 | 609 | return(-1); |
51d1035a | 610 | } |
fdaeefb7 BJ |
611 | if (read(fd, &execb, sizeof(execb)) == sizeof(execb)) |
612 | switch(execb.a_magic) { | |
51d1035a BJ |
613 | case A_MAGIC1: |
614 | case A_MAGIC2: | |
615 | case A_MAGIC3: | |
616 | #ifdef A_MAGIC4 | |
617 | case A_MAGIC4: | |
618 | #endif | |
619 | printf("%s: %s is an executable program", name, file); | |
620 | goto error1; | |
621 | ||
622 | case ARMAG: | |
623 | printf("%s: %s is an archive file", name, file); | |
624 | goto error1; | |
625 | } | |
fdaeefb7 | 626 | (void) close(fd); |
af807caa RC |
627 | if (rflag) { |
628 | if ((cp = rindex(file, '/')) == NULL) { | |
629 | if (access(".", 2) == 0) | |
4d4caa50 | 630 | return(1); |
af807caa | 631 | } else { |
fdaeefb7 | 632 | *cp = '\0'; |
4d4caa50 | 633 | fd = access(file, 2); |
fdaeefb7 | 634 | *cp = '/'; |
4d4caa50 RC |
635 | if (fd == 0) |
636 | return(1); | |
878a0818 | 637 | } |
4d4caa50 | 638 | printf("%s: %s: is not removable by you\n", name, file); |
fdaeefb7 | 639 | } |
4d4caa50 | 640 | return(0); |
51d1035a | 641 | |
51d1035a BJ |
642 | error1: |
643 | printf(" and is unprintable\n"); | |
fdaeefb7 BJ |
644 | (void) close(fd); |
645 | return(-1); | |
51d1035a BJ |
646 | } |
647 | ||
648 | /* | |
649 | * itoa - integer to string conversion | |
650 | */ | |
651 | char * | |
652 | itoa(i) | |
6f038d7b | 653 | register int i; |
51d1035a BJ |
654 | { |
655 | static char b[10] = "########"; | |
656 | register char *p; | |
657 | ||
658 | p = &b[8]; | |
659 | do | |
660 | *p-- = i%10 + '0'; | |
661 | while (i /= 10); | |
fdaeefb7 | 662 | return(++p); |
51d1035a BJ |
663 | } |
664 | ||
665 | /* | |
666 | * Perform lookup for printer name or abbreviation -- | |
51d1035a BJ |
667 | */ |
668 | chkprinter(s) | |
8fed920b | 669 | char *s; |
51d1035a | 670 | { |
dfc1084e | 671 | int status; |
98d189de | 672 | char buf[BUFSIZ]; |
8fed920b RC |
673 | static char pbuf[BUFSIZ/2]; |
674 | char *bp = pbuf; | |
675 | extern char *pgetstr(); | |
dfc1084e | 676 | |
8fed920b | 677 | if ((status = pgetent(buf, s)) < 0) |
dfc1084e RC |
678 | fatal("cannot open printer description file"); |
679 | else if (status == 0) | |
8fed920b | 680 | fatal("%s: unknown printer", s); |
fdaeefb7 | 681 | if ((SD = pgetstr("sd", &bp)) == NULL) |
7abf8d65 | 682 | SD = _PATH_DEFSPOOL; |
4d4caa50 RC |
683 | if ((LO = pgetstr("lo", &bp)) == NULL) |
684 | LO = DEFLOCK; | |
ca1ba714 | 685 | RG = pgetstr("rg", &bp); |
51d1035a BJ |
686 | if ((MX = pgetnum("mx")) < 0) |
687 | MX = DEFMX; | |
eee484be RC |
688 | if ((MC = pgetnum("mc")) < 0) |
689 | MC = DEFMAXCOPIES; | |
fa211baf RC |
690 | if ((DU = pgetnum("du")) < 0) |
691 | DU = DEFUID; | |
eee484be | 692 | SC = pgetflag("sc"); |
fdaeefb7 BJ |
693 | } |
694 | ||
695 | /* | |
696 | * Make the temp files. | |
697 | */ | |
698 | mktemps() | |
699 | { | |
eee484be RC |
700 | register int c, len, fd, n; |
701 | register char *cp; | |
98d189de | 702 | char buf[BUFSIZ]; |
8fed920b | 703 | char *mktemp(); |
fdaeefb7 BJ |
704 | |
705 | (void) sprintf(buf, "%s/.seq", SD); | |
eee484be RC |
706 | if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) { |
707 | printf("%s: cannot create %s\n", name, buf); | |
708 | exit(1); | |
709 | } | |
710 | if (flock(fd, LOCK_EX)) { | |
711 | printf("%s: cannot lock %s\n", name, buf); | |
712 | exit(1); | |
713 | } | |
714 | n = 0; | |
715 | if ((len = read(fd, buf, sizeof(buf))) > 0) { | |
716 | for (cp = buf; len--; ) { | |
717 | if (*cp < '0' || *cp > '9') | |
718 | break; | |
719 | n = n * 10 + (*cp++ - '0'); | |
fdaeefb7 | 720 | } |
fdaeefb7 BJ |
721 | } |
722 | len = strlen(SD) + strlen(host) + 8; | |
723 | tfname = mktemp("tf", n, len); | |
724 | cfname = mktemp("cf", n, len); | |
725 | dfname = mktemp("df", n, len); | |
726 | inchar = strlen(SD) + 3; | |
727 | n = (n + 1) % 1000; | |
eee484be RC |
728 | (void) lseek(fd, 0L, 0); |
729 | sprintf(buf, "%03d\n", n); | |
730 | (void) write(fd, buf, strlen(buf)); | |
731 | (void) close(fd); /* unlocks as well */ | |
51d1035a BJ |
732 | } |
733 | ||
734 | /* | |
fdaeefb7 | 735 | * Make a temp file name. |
51d1035a BJ |
736 | */ |
737 | char * | |
fdaeefb7 BJ |
738 | mktemp(id, num, len) |
739 | char *id; | |
740 | int num, len; | |
51d1035a BJ |
741 | { |
742 | register char *s; | |
8fed920b | 743 | extern char *malloc(); |
51d1035a | 744 | |
dfc1084e RC |
745 | if ((s = malloc(len)) == NULL) |
746 | fatal("out of memory"); | |
fdaeefb7 BJ |
747 | (void) sprintf(s, "%s/%sA%03d%s", SD, id, num, host); |
748 | return(s); | |
51d1035a | 749 | } |
8fed920b RC |
750 | |
751 | /*VARARGS1*/ | |
752 | fatal(msg, a1, a2, a3) | |
753 | char *msg; | |
754 | { | |
755 | printf("%s: ", name); | |
756 | printf(msg, a1, a2, a3); | |
757 | putchar('\n'); | |
758 | exit(1); | |
759 | } |