Commit | Line | Data |
---|---|---|
d0aeaf5a DF |
1 | /* |
2 | * Copyright (c) 1983 Regents of the University of California. | |
9d85c861 KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
a399f6c8 KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
d0aeaf5a DF |
16 | */ |
17 | ||
5df74a28 | 18 | #ifndef lint |
845a514d | 19 | static char sccsid[] = "@(#)cmds.c 5.6 (Berkeley) %G%"; |
9d85c861 | 20 | #endif /* not lint */ |
5df74a28 RC |
21 | |
22 | /* | |
a7a48f56 | 23 | * lpc -- line printer control program -- commands: |
5df74a28 RC |
24 | */ |
25 | ||
26 | #include "lp.h" | |
a7a48f56 | 27 | #include <sys/time.h> |
7abf8d65 | 28 | #include "pathnames.h" |
5df74a28 RC |
29 | |
30 | /* | |
31 | * kill an existing daemon and disable printing. | |
32 | */ | |
33 | abort(argc, argv) | |
34 | char *argv[]; | |
35 | { | |
36 | register int c, status; | |
37 | register char *cp1, *cp2; | |
38 | char prbuf[100]; | |
39 | ||
40 | if (argc == 1) { | |
41 | printf("Usage: abort {all | printer ...}\n"); | |
42 | return; | |
43 | } | |
44 | if (argc == 2 && !strcmp(argv[1], "all")) { | |
45 | printer = prbuf; | |
46 | while (getprent(line) > 0) { | |
47 | cp1 = prbuf; | |
48 | cp2 = line; | |
49 | while ((c = *cp2++) && c != '|' && c != ':') | |
50 | *cp1++ = c; | |
51 | *cp1 = '\0'; | |
71a561a3 | 52 | abortpr(1); |
5df74a28 RC |
53 | } |
54 | return; | |
55 | } | |
56 | while (--argc) { | |
57 | printer = *++argv; | |
58 | if ((status = pgetent(line, printer)) < 0) { | |
7b22a8ae | 59 | printf("cannot open printer description file\n"); |
5df74a28 RC |
60 | continue; |
61 | } else if (status == 0) { | |
7b22a8ae | 62 | printf("unknown printer %s\n", printer); |
5df74a28 RC |
63 | continue; |
64 | } | |
71a561a3 | 65 | abortpr(1); |
5df74a28 RC |
66 | } |
67 | } | |
68 | ||
71a561a3 | 69 | abortpr(dis) |
5df74a28 RC |
70 | { |
71 | register FILE *fp; | |
72 | struct stat stbuf; | |
73 | int pid, fd; | |
74 | ||
75 | bp = pbuf; | |
76 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 77 | SD = _PATH_DEFSPOOL; |
5df74a28 RC |
78 | if ((LO = pgetstr("lo", &bp)) == NULL) |
79 | LO = DEFLOCK; | |
80 | (void) sprintf(line, "%s/%s", SD, LO); | |
81 | printf("%s:\n", printer); | |
82 | ||
83 | /* | |
84 | * Turn on the owner execute bit of the lock file to disable printing. | |
85 | */ | |
71a561a3 RC |
86 | if (dis) { |
87 | if (stat(line, &stbuf) >= 0) { | |
88 | if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) | |
89 | printf("\tcannot disable printing\n"); | |
845a514d TF |
90 | else { |
91 | upstat("printing disabled\n"); | |
71a561a3 | 92 | printf("\tprinting disabled\n"); |
845a514d | 93 | } |
71a561a3 RC |
94 | } else if (errno == ENOENT) { |
95 | if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) | |
96 | printf("\tcannot create lock file\n"); | |
97 | else { | |
98 | (void) close(fd); | |
845a514d | 99 | upstat("printing disabled\n"); |
71a561a3 RC |
100 | printf("\tprinting disabled\n"); |
101 | printf("\tno daemon to abort\n"); | |
102 | } | |
103 | return; | |
104 | } else { | |
105 | printf("\tcannot stat lock file\n"); | |
106 | return; | |
5df74a28 | 107 | } |
5df74a28 RC |
108 | } |
109 | /* | |
110 | * Kill the current daemon to stop printing now. | |
111 | */ | |
112 | if ((fp = fopen(line, "r")) == NULL) { | |
113 | printf("\tcannot open lock file\n"); | |
114 | return; | |
115 | } | |
adec4d9e | 116 | if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { |
f7e314e3 | 117 | (void) fclose(fp); /* unlocks as well */ |
5df74a28 RC |
118 | printf("\tno daemon to abort\n"); |
119 | return; | |
120 | } | |
121 | (void) fclose(fp); | |
71a561a3 | 122 | if (kill(pid = atoi(line), SIGTERM) < 0) |
5df74a28 RC |
123 | printf("\tWarning: daemon (pid %d) not killed\n", pid); |
124 | else | |
125 | printf("\tdaemon (pid %d) killed\n", pid); | |
126 | } | |
127 | ||
845a514d TF |
128 | /* |
129 | * Write a message into the status file. | |
130 | */ | |
131 | upstat(msg) | |
132 | char *msg; | |
133 | { | |
134 | register int fd; | |
135 | char statfile[BUFSIZ]; | |
136 | ||
137 | bp = pbuf; | |
138 | if ((ST = pgetstr("st", &bp)) == NULL) | |
139 | ST = DEFSTAT; | |
140 | (void) sprintf(statfile, "%s/%s", SD, ST); | |
141 | umask(0); | |
142 | fd = open(statfile, O_WRONLY|O_CREAT, 0664); | |
143 | if (fd < 0 || flock(fd, LOCK_EX) < 0) { | |
144 | printf("\tcannot create status file\n"); | |
145 | return; | |
146 | } | |
147 | (void) ftruncate(fd, 0); | |
148 | if (msg == (char *)NULL) | |
149 | (void) write(fd, "\n", 1); | |
150 | else | |
151 | (void) write(fd, msg, strlen(msg)); | |
152 | (void) close(fd); | |
153 | } | |
154 | ||
5df74a28 RC |
155 | /* |
156 | * Remove all spool files and temporaries from the spooling area. | |
157 | */ | |
158 | clean(argc, argv) | |
159 | char *argv[]; | |
160 | { | |
161 | register int c, status; | |
162 | register char *cp1, *cp2; | |
163 | char prbuf[100]; | |
164 | ||
165 | if (argc == 1) { | |
166 | printf("Usage: clean {all | printer ...}\n"); | |
167 | return; | |
168 | } | |
169 | if (argc == 2 && !strcmp(argv[1], "all")) { | |
170 | printer = prbuf; | |
171 | while (getprent(line) > 0) { | |
172 | cp1 = prbuf; | |
173 | cp2 = line; | |
174 | while ((c = *cp2++) && c != '|' && c != ':') | |
175 | *cp1++ = c; | |
176 | *cp1 = '\0'; | |
177 | cleanpr(); | |
178 | } | |
179 | return; | |
180 | } | |
181 | while (--argc) { | |
182 | printer = *++argv; | |
183 | if ((status = pgetent(line, printer)) < 0) { | |
7b22a8ae | 184 | printf("cannot open printer description file\n"); |
5df74a28 RC |
185 | continue; |
186 | } else if (status == 0) { | |
7b22a8ae | 187 | printf("unknown printer %s\n", printer); |
5df74a28 RC |
188 | continue; |
189 | } | |
190 | cleanpr(); | |
191 | } | |
192 | } | |
193 | ||
a7a48f56 RC |
194 | select(d) |
195 | struct direct *d; | |
196 | { | |
197 | int c = d->d_name[0]; | |
198 | ||
199 | if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') | |
200 | return(1); | |
201 | return(0); | |
202 | } | |
203 | ||
204 | /* | |
205 | * Comparison routine for scandir. Sort by job number and machine, then | |
206 | * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. | |
207 | */ | |
208 | sortq(d1, d2) | |
209 | struct direct **d1, **d2; | |
210 | { | |
211 | int c1, c2; | |
212 | ||
213 | if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) | |
214 | return(c1); | |
215 | c1 = (*d1)->d_name[0]; | |
216 | c2 = (*d2)->d_name[0]; | |
217 | if (c1 == c2) | |
218 | return((*d1)->d_name[2] - (*d2)->d_name[2]); | |
219 | if (c1 == 'c') | |
220 | return(-1); | |
221 | if (c1 == 'd' || c2 == 'c') | |
222 | return(1); | |
223 | return(-1); | |
224 | } | |
225 | ||
226 | /* | |
227 | * Remove incomplete jobs from spooling area. | |
228 | */ | |
5df74a28 RC |
229 | cleanpr() |
230 | { | |
a7a48f56 RC |
231 | register int i, n; |
232 | register char *cp, *cp1, *lp; | |
233 | struct direct **queue; | |
234 | int nitems; | |
5df74a28 RC |
235 | |
236 | bp = pbuf; | |
237 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 238 | SD = _PATH_DEFSPOOL; |
5df74a28 RC |
239 | printf("%s:\n", printer); |
240 | ||
a7a48f56 RC |
241 | for (lp = line, cp = SD; *lp++ = *cp++; ) |
242 | ; | |
243 | lp[-1] = '/'; | |
244 | ||
245 | nitems = scandir(SD, &queue, select, sortq); | |
246 | if (nitems < 0) { | |
5df74a28 RC |
247 | printf("\tcannot examine spool directory\n"); |
248 | return; | |
249 | } | |
a7a48f56 RC |
250 | if (nitems == 0) |
251 | return; | |
252 | i = 0; | |
253 | do { | |
254 | cp = queue[i]->d_name; | |
255 | if (*cp == 'c') { | |
256 | n = 0; | |
257 | while (i + 1 < nitems) { | |
258 | cp1 = queue[i + 1]->d_name; | |
259 | if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) | |
260 | break; | |
261 | i++; | |
262 | n++; | |
263 | } | |
264 | if (n == 0) { | |
265 | strcpy(lp, cp); | |
266 | unlinkf(line); | |
267 | } | |
268 | } else { | |
269 | /* | |
270 | * Must be a df with no cf (otherwise, it would have | |
271 | * been skipped above) or a tf file (which can always | |
272 | * be removed). | |
273 | */ | |
274 | strcpy(lp, cp); | |
275 | unlinkf(line); | |
5df74a28 | 276 | } |
a7a48f56 RC |
277 | } while (++i < nitems); |
278 | } | |
279 | ||
280 | unlinkf(name) | |
281 | char *name; | |
282 | { | |
283 | if (unlink(name) < 0) | |
284 | printf("\tcannot remove %s\n", name); | |
285 | else | |
286 | printf("\tremoved %s\n", name); | |
5df74a28 RC |
287 | } |
288 | ||
289 | /* | |
290 | * Enable queuing to the printer (allow lpr's). | |
291 | */ | |
292 | enable(argc, argv) | |
293 | char *argv[]; | |
294 | { | |
295 | register int c, status; | |
296 | register char *cp1, *cp2; | |
297 | char prbuf[100]; | |
298 | ||
299 | if (argc == 1) { | |
300 | printf("Usage: enable {all | printer ...}\n"); | |
301 | return; | |
302 | } | |
303 | if (argc == 2 && !strcmp(argv[1], "all")) { | |
304 | printer = prbuf; | |
305 | while (getprent(line) > 0) { | |
306 | cp1 = prbuf; | |
307 | cp2 = line; | |
308 | while ((c = *cp2++) && c != '|' && c != ':') | |
309 | *cp1++ = c; | |
310 | *cp1 = '\0'; | |
311 | enablepr(); | |
312 | } | |
313 | return; | |
314 | } | |
315 | while (--argc) { | |
316 | printer = *++argv; | |
317 | if ((status = pgetent(line, printer)) < 0) { | |
7b22a8ae | 318 | printf("cannot open printer description file\n"); |
5df74a28 RC |
319 | continue; |
320 | } else if (status == 0) { | |
7b22a8ae | 321 | printf("unknown printer %s\n", printer); |
5df74a28 RC |
322 | continue; |
323 | } | |
324 | enablepr(); | |
325 | } | |
326 | } | |
327 | ||
328 | enablepr() | |
329 | { | |
330 | struct stat stbuf; | |
331 | ||
332 | bp = pbuf; | |
333 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 334 | SD = _PATH_DEFSPOOL; |
5df74a28 RC |
335 | if ((LO = pgetstr("lo", &bp)) == NULL) |
336 | LO = DEFLOCK; | |
337 | (void) sprintf(line, "%s/%s", SD, LO); | |
338 | printf("%s:\n", printer); | |
339 | ||
340 | /* | |
341 | * Turn off the group execute bit of the lock file to enable queuing. | |
342 | */ | |
343 | if (stat(line, &stbuf) >= 0) { | |
344 | if (chmod(line, stbuf.st_mode & 0767) < 0) | |
7b22a8ae | 345 | printf("\tcannot enable queuing\n"); |
5df74a28 RC |
346 | else |
347 | printf("\tqueuing enabled\n"); | |
348 | } | |
349 | } | |
350 | ||
351 | /* | |
352 | * Disable queuing. | |
353 | */ | |
354 | disable(argc, argv) | |
355 | char *argv[]; | |
356 | { | |
357 | register int c, status; | |
358 | register char *cp1, *cp2; | |
359 | char prbuf[100]; | |
360 | ||
361 | if (argc == 1) { | |
362 | printf("Usage: disable {all | printer ...}\n"); | |
363 | return; | |
364 | } | |
365 | if (argc == 2 && !strcmp(argv[1], "all")) { | |
366 | printer = prbuf; | |
367 | while (getprent(line) > 0) { | |
368 | cp1 = prbuf; | |
369 | cp2 = line; | |
370 | while ((c = *cp2++) && c != '|' && c != ':') | |
371 | *cp1++ = c; | |
372 | *cp1 = '\0'; | |
373 | disablepr(); | |
374 | } | |
375 | return; | |
376 | } | |
377 | while (--argc) { | |
378 | printer = *++argv; | |
379 | if ((status = pgetent(line, printer)) < 0) { | |
7b22a8ae | 380 | printf("cannot open printer description file\n"); |
5df74a28 RC |
381 | continue; |
382 | } else if (status == 0) { | |
7b22a8ae | 383 | printf("unknown printer %s\n", printer); |
5df74a28 RC |
384 | continue; |
385 | } | |
386 | disablepr(); | |
387 | } | |
388 | } | |
389 | ||
390 | disablepr() | |
391 | { | |
392 | register int fd; | |
393 | struct stat stbuf; | |
394 | ||
395 | bp = pbuf; | |
396 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 397 | SD = _PATH_DEFSPOOL; |
5df74a28 RC |
398 | if ((LO = pgetstr("lo", &bp)) == NULL) |
399 | LO = DEFLOCK; | |
400 | (void) sprintf(line, "%s/%s", SD, LO); | |
401 | printf("%s:\n", printer); | |
402 | /* | |
403 | * Turn on the group execute bit of the lock file to disable queuing. | |
404 | */ | |
405 | if (stat(line, &stbuf) >= 0) { | |
406 | if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0) | |
407 | printf("\tcannot disable queuing\n"); | |
408 | else | |
409 | printf("\tqueuing disabled\n"); | |
410 | } else if (errno == ENOENT) { | |
adec4d9e | 411 | if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0) |
5df74a28 RC |
412 | printf("\tcannot create lock file\n"); |
413 | else { | |
414 | (void) close(fd); | |
415 | printf("\tqueuing disabled\n"); | |
416 | } | |
417 | return; | |
418 | } else | |
419 | printf("\tcannot stat lock file\n"); | |
420 | } | |
421 | ||
815c5da6 RC |
422 | /* |
423 | * Disable queuing and printing and put a message into the status file | |
424 | * (reason for being down). | |
425 | */ | |
426 | down(argc, argv) | |
427 | char *argv[]; | |
428 | { | |
429 | register int c, status; | |
430 | register char *cp1, *cp2; | |
431 | char prbuf[100]; | |
432 | ||
433 | if (argc == 1) { | |
da8800e5 | 434 | printf("Usage: down {all | printer} [message ...]\n"); |
815c5da6 RC |
435 | return; |
436 | } | |
437 | if (!strcmp(argv[1], "all")) { | |
438 | printer = prbuf; | |
439 | while (getprent(line) > 0) { | |
440 | cp1 = prbuf; | |
441 | cp2 = line; | |
442 | while ((c = *cp2++) && c != '|' && c != ':') | |
443 | *cp1++ = c; | |
444 | *cp1 = '\0'; | |
445 | putmsg(argc - 2, argv + 2); | |
446 | } | |
447 | return; | |
448 | } | |
449 | printer = argv[1]; | |
450 | if ((status = pgetent(line, printer)) < 0) { | |
451 | printf("cannot open printer description file\n"); | |
452 | return; | |
453 | } else if (status == 0) { | |
454 | printf("unknown printer %s\n", printer); | |
455 | return; | |
456 | } | |
457 | putmsg(argc - 2, argv + 2); | |
458 | } | |
459 | ||
460 | putmsg(argc, argv) | |
461 | char **argv; | |
462 | { | |
463 | register int fd; | |
464 | register char *cp1, *cp2; | |
465 | char buf[1024]; | |
466 | struct stat stbuf; | |
467 | ||
468 | bp = pbuf; | |
469 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 470 | SD = _PATH_DEFSPOOL; |
815c5da6 RC |
471 | if ((LO = pgetstr("lo", &bp)) == NULL) |
472 | LO = DEFLOCK; | |
473 | if ((ST = pgetstr("st", &bp)) == NULL) | |
474 | ST = DEFSTAT; | |
475 | printf("%s:\n", printer); | |
476 | /* | |
477 | * Turn on the group execute bit of the lock file to disable queuing and | |
478 | * turn on the owner execute bit of the lock file to disable printing. | |
479 | */ | |
480 | (void) sprintf(line, "%s/%s", SD, LO); | |
481 | if (stat(line, &stbuf) >= 0) { | |
482 | if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0) | |
483 | printf("\tcannot disable queuing\n"); | |
484 | else | |
485 | printf("\tprinter and queuing disabled\n"); | |
486 | } else if (errno == ENOENT) { | |
487 | if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0) | |
488 | printf("\tcannot create lock file\n"); | |
489 | else { | |
490 | (void) close(fd); | |
491 | printf("\tprinter and queuing disabled\n"); | |
492 | } | |
493 | return; | |
494 | } else | |
495 | printf("\tcannot stat lock file\n"); | |
496 | /* | |
497 | * Write the message into the status file. | |
498 | */ | |
815c5da6 RC |
499 | (void) sprintf(line, "%s/%s", SD, ST); |
500 | fd = open(line, O_WRONLY|O_CREAT, 0664); | |
501 | if (fd < 0 || flock(fd, LOCK_EX) < 0) { | |
502 | printf("\tcannot create status file\n"); | |
503 | return; | |
504 | } | |
505 | (void) ftruncate(fd, 0); | |
da8800e5 RC |
506 | if (argc <= 0) { |
507 | (void) write(fd, "\n", 1); | |
508 | (void) close(fd); | |
509 | return; | |
510 | } | |
815c5da6 RC |
511 | cp1 = buf; |
512 | while (--argc >= 0) { | |
513 | cp2 = *argv++; | |
514 | while (*cp1++ = *cp2++) | |
515 | ; | |
516 | cp1[-1] = ' '; | |
517 | } | |
518 | cp1[-1] = '\n'; | |
519 | *cp1 = '\0'; | |
520 | (void) write(fd, buf, strlen(buf)); | |
521 | (void) close(fd); | |
522 | } | |
523 | ||
5df74a28 RC |
524 | /* |
525 | * Exit lpc | |
526 | */ | |
527 | quit(argc, argv) | |
528 | char *argv[]; | |
529 | { | |
530 | exit(0); | |
531 | } | |
532 | ||
533 | /* | |
71a561a3 | 534 | * Kill and restart the daemon. |
5df74a28 RC |
535 | */ |
536 | restart(argc, argv) | |
537 | char *argv[]; | |
538 | { | |
539 | register int c, status; | |
540 | register char *cp1, *cp2; | |
541 | char prbuf[100]; | |
542 | ||
543 | if (argc == 1) { | |
544 | printf("Usage: restart {all | printer ...}\n"); | |
545 | return; | |
546 | } | |
5df74a28 RC |
547 | if (argc == 2 && !strcmp(argv[1], "all")) { |
548 | printer = prbuf; | |
549 | while (getprent(line) > 0) { | |
550 | cp1 = prbuf; | |
551 | cp2 = line; | |
552 | while ((c = *cp2++) && c != '|' && c != ':') | |
553 | *cp1++ = c; | |
554 | *cp1 = '\0'; | |
71a561a3 | 555 | abortpr(0); |
5df74a28 RC |
556 | startpr(0); |
557 | } | |
558 | return; | |
559 | } | |
560 | while (--argc) { | |
561 | printer = *++argv; | |
562 | if ((status = pgetent(line, printer)) < 0) { | |
7b22a8ae | 563 | printf("cannot open printer description file\n"); |
5df74a28 RC |
564 | continue; |
565 | } else if (status == 0) { | |
7b22a8ae | 566 | printf("unknown printer %s\n", printer); |
5df74a28 RC |
567 | continue; |
568 | } | |
71a561a3 | 569 | abortpr(0); |
5df74a28 RC |
570 | startpr(0); |
571 | } | |
572 | } | |
573 | ||
574 | /* | |
575 | * Enable printing on the specified printer and startup the daemon. | |
576 | */ | |
577 | start(argc, argv) | |
578 | char *argv[]; | |
579 | { | |
580 | register int c, status; | |
581 | register char *cp1, *cp2; | |
582 | char prbuf[100]; | |
583 | ||
584 | if (argc == 1) { | |
585 | printf("Usage: start {all | printer ...}\n"); | |
586 | return; | |
587 | } | |
5df74a28 RC |
588 | if (argc == 2 && !strcmp(argv[1], "all")) { |
589 | printer = prbuf; | |
590 | while (getprent(line) > 0) { | |
591 | cp1 = prbuf; | |
592 | cp2 = line; | |
593 | while ((c = *cp2++) && c != '|' && c != ':') | |
594 | *cp1++ = c; | |
595 | *cp1 = '\0'; | |
596 | startpr(1); | |
597 | } | |
598 | return; | |
599 | } | |
600 | while (--argc) { | |
601 | printer = *++argv; | |
602 | if ((status = pgetent(line, printer)) < 0) { | |
7b22a8ae | 603 | printf("cannot open printer description file\n"); |
5df74a28 RC |
604 | continue; |
605 | } else if (status == 0) { | |
7b22a8ae | 606 | printf("unknown printer %s\n", printer); |
5df74a28 RC |
607 | continue; |
608 | } | |
609 | startpr(1); | |
610 | } | |
611 | } | |
612 | ||
613 | startpr(enable) | |
614 | { | |
615 | struct stat stbuf; | |
616 | ||
617 | bp = pbuf; | |
618 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 619 | SD = _PATH_DEFSPOOL; |
5df74a28 RC |
620 | if ((LO = pgetstr("lo", &bp)) == NULL) |
621 | LO = DEFLOCK; | |
5df74a28 RC |
622 | (void) sprintf(line, "%s/%s", SD, LO); |
623 | printf("%s:\n", printer); | |
624 | ||
625 | /* | |
626 | * Turn off the owner execute bit of the lock file to enable printing. | |
627 | */ | |
628 | if (enable && stat(line, &stbuf) >= 0) { | |
66a3ae2e | 629 | if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0) |
5df74a28 RC |
630 | printf("\tcannot enable printing\n"); |
631 | else | |
632 | printf("\tprinting enabled\n"); | |
633 | } | |
25e0cdec | 634 | if (!startdaemon(printer)) |
5df74a28 RC |
635 | printf("\tcouldn't start daemon\n"); |
636 | else | |
637 | printf("\tdaemon started\n"); | |
638 | } | |
639 | ||
640 | /* | |
641 | * Print the status of each queue listed or all the queues. | |
642 | */ | |
643 | status(argc, argv) | |
644 | char *argv[]; | |
645 | { | |
646 | register int c, status; | |
647 | register char *cp1, *cp2; | |
648 | char prbuf[100]; | |
649 | ||
650 | if (argc == 1) { | |
651 | printer = prbuf; | |
652 | while (getprent(line) > 0) { | |
653 | cp1 = prbuf; | |
654 | cp2 = line; | |
655 | while ((c = *cp2++) && c != '|' && c != ':') | |
656 | *cp1++ = c; | |
657 | *cp1 = '\0'; | |
658 | prstat(); | |
659 | } | |
660 | return; | |
661 | } | |
662 | while (--argc) { | |
663 | printer = *++argv; | |
664 | if ((status = pgetent(line, printer)) < 0) { | |
7b22a8ae | 665 | printf("cannot open printer description file\n"); |
5df74a28 RC |
666 | continue; |
667 | } else if (status == 0) { | |
7b22a8ae | 668 | printf("unknown printer %s\n", printer); |
5df74a28 RC |
669 | continue; |
670 | } | |
671 | prstat(); | |
672 | } | |
673 | } | |
674 | ||
675 | /* | |
676 | * Print the status of the printer queue. | |
677 | */ | |
678 | prstat() | |
679 | { | |
680 | struct stat stbuf; | |
681 | register int fd, i; | |
682 | register struct direct *dp; | |
683 | DIR *dirp; | |
684 | ||
685 | bp = pbuf; | |
686 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 687 | SD = _PATH_DEFSPOOL; |
5df74a28 RC |
688 | if ((LO = pgetstr("lo", &bp)) == NULL) |
689 | LO = DEFLOCK; | |
690 | if ((ST = pgetstr("st", &bp)) == NULL) | |
691 | ST = DEFSTAT; | |
692 | printf("%s:\n", printer); | |
693 | (void) sprintf(line, "%s/%s", SD, LO); | |
694 | if (stat(line, &stbuf) >= 0) { | |
695 | printf("\tqueuing is %s\n", | |
696 | (stbuf.st_mode & 010) ? "disabled" : "enabled"); | |
697 | printf("\tprinting is %s\n", | |
698 | (stbuf.st_mode & 0100) ? "disabled" : "enabled"); | |
699 | } else { | |
700 | printf("\tqueuing is enabled\n"); | |
701 | printf("\tprinting is enabled\n"); | |
702 | } | |
703 | if ((dirp = opendir(SD)) == NULL) { | |
704 | printf("\tcannot examine spool directory\n"); | |
705 | return; | |
706 | } | |
707 | i = 0; | |
708 | while ((dp = readdir(dirp)) != NULL) { | |
709 | if (*dp->d_name == 'c' && dp->d_name[1] == 'f') | |
710 | i++; | |
711 | } | |
712 | closedir(dirp); | |
713 | if (i == 0) | |
714 | printf("\tno entries\n"); | |
715 | else if (i == 1) | |
716 | printf("\t1 entry in spool area\n"); | |
717 | else | |
718 | printf("\t%d entries in spool area\n", i); | |
adec4d9e SL |
719 | fd = open(line, O_RDONLY); |
720 | if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { | |
f7e314e3 | 721 | (void) close(fd); /* unlocks as well */ |
5df74a28 RC |
722 | printf("\tno daemon present\n"); |
723 | return; | |
724 | } | |
725 | (void) close(fd); | |
726 | putchar('\t'); | |
727 | (void) sprintf(line, "%s/%s", SD, ST); | |
adec4d9e SL |
728 | fd = open(line, O_RDONLY); |
729 | if (fd >= 0) { | |
730 | (void) flock(fd, LOCK_SH); | |
5df74a28 RC |
731 | while ((i = read(fd, line, sizeof(line))) > 0) |
732 | (void) fwrite(line, 1, i, stdout); | |
f7e314e3 | 733 | (void) close(fd); /* unlocks as well */ |
5df74a28 RC |
734 | } |
735 | } | |
736 | ||
737 | /* | |
738 | * Stop the specified daemon after completing the current job and disable | |
739 | * printing. | |
740 | */ | |
741 | stop(argc, argv) | |
742 | char *argv[]; | |
743 | { | |
744 | register int c, status; | |
745 | register char *cp1, *cp2; | |
746 | char prbuf[100]; | |
747 | ||
748 | if (argc == 1) { | |
749 | printf("Usage: stop {all | printer ...}\n"); | |
750 | return; | |
751 | } | |
752 | if (argc == 2 && !strcmp(argv[1], "all")) { | |
753 | printer = prbuf; | |
754 | while (getprent(line) > 0) { | |
755 | cp1 = prbuf; | |
756 | cp2 = line; | |
757 | while ((c = *cp2++) && c != '|' && c != ':') | |
758 | *cp1++ = c; | |
759 | *cp1 = '\0'; | |
760 | stoppr(); | |
761 | } | |
762 | return; | |
763 | } | |
764 | while (--argc) { | |
765 | printer = *++argv; | |
766 | if ((status = pgetent(line, printer)) < 0) { | |
7b22a8ae | 767 | printf("cannot open printer description file\n"); |
5df74a28 RC |
768 | continue; |
769 | } else if (status == 0) { | |
7b22a8ae | 770 | printf("unknown printer %s\n", printer); |
5df74a28 RC |
771 | continue; |
772 | } | |
773 | stoppr(); | |
774 | } | |
775 | } | |
776 | ||
777 | stoppr() | |
778 | { | |
779 | register int fd; | |
780 | struct stat stbuf; | |
781 | ||
782 | bp = pbuf; | |
783 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 784 | SD = _PATH_DEFSPOOL; |
5df74a28 RC |
785 | if ((LO = pgetstr("lo", &bp)) == NULL) |
786 | LO = DEFLOCK; | |
787 | (void) sprintf(line, "%s/%s", SD, LO); | |
788 | printf("%s:\n", printer); | |
789 | ||
790 | /* | |
791 | * Turn on the owner execute bit of the lock file to disable printing. | |
792 | */ | |
793 | if (stat(line, &stbuf) >= 0) { | |
794 | if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) | |
795 | printf("\tcannot disable printing\n"); | |
845a514d TF |
796 | else { |
797 | upstat("printing disabled\n"); | |
5df74a28 | 798 | printf("\tprinting disabled\n"); |
845a514d | 799 | } |
5df74a28 | 800 | } else if (errno == ENOENT) { |
adec4d9e | 801 | if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) |
5df74a28 RC |
802 | printf("\tcannot create lock file\n"); |
803 | else { | |
804 | (void) close(fd); | |
845a514d | 805 | upstat("printing disabled\n"); |
5df74a28 RC |
806 | printf("\tprinting disabled\n"); |
807 | } | |
808 | } else | |
809 | printf("\tcannot stat lock file\n"); | |
810 | } | |
25e0cdec | 811 | |
a7a48f56 RC |
812 | struct queue **queue; |
813 | int nitems; | |
814 | time_t mtime; | |
815 | ||
25e0cdec BJ |
816 | /* |
817 | * Put the specified jobs at the top of printer queue. | |
818 | */ | |
819 | topq(argc, argv) | |
820 | char *argv[]; | |
821 | { | |
a7a48f56 | 822 | register int n, i; |
25e0cdec BJ |
823 | struct stat stbuf; |
824 | register char *cfname; | |
a7a48f56 | 825 | int status, changed; |
25e0cdec | 826 | |
a7a48f56 | 827 | if (argc < 3) { |
25e0cdec BJ |
828 | printf("Usage: topq printer [jobnum ...] [user ...]\n"); |
829 | return; | |
830 | } | |
831 | ||
832 | --argc; | |
833 | printer = *++argv; | |
834 | status = pgetent(line, printer); | |
835 | if (status < 0) { | |
836 | printf("cannot open printer description file\n"); | |
837 | return; | |
2138712c | 838 | } else if (status == 0) { |
25e0cdec BJ |
839 | printf("%s: unknown printer\n", printer); |
840 | return; | |
841 | } | |
842 | bp = pbuf; | |
843 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
7abf8d65 | 844 | SD = _PATH_DEFSPOOL; |
25e0cdec BJ |
845 | if ((LO = pgetstr("lo", &bp)) == NULL) |
846 | LO = DEFLOCK; | |
847 | printf("%s:\n", printer); | |
848 | ||
849 | if (chdir(SD) < 0) { | |
850 | printf("\tcannot chdir to %s\n", SD); | |
851 | return; | |
852 | } | |
853 | nitems = getq(&queue); | |
a7a48f56 RC |
854 | if (nitems == 0) |
855 | return; | |
856 | changed = 0; | |
857 | mtime = queue[0]->q_time; | |
858 | for (i = argc; --i; ) { | |
859 | if (doarg(argv[i]) == 0) { | |
860 | printf("\tjob %s is not in the queue\n", argv[i]); | |
25e0cdec | 861 | continue; |
a7a48f56 | 862 | } else |
2138712c | 863 | changed++; |
25e0cdec | 864 | } |
a7a48f56 RC |
865 | for (i = 0; i < nitems; i++) |
866 | free(queue[i]); | |
25e0cdec | 867 | free(queue); |
a7a48f56 RC |
868 | if (!changed) { |
869 | printf("\tqueue order unchanged\n"); | |
870 | return; | |
871 | } | |
25e0cdec BJ |
872 | /* |
873 | * Turn on the public execute bit of the lock file to | |
874 | * get lpd to rebuild the queue after the current job. | |
875 | */ | |
2138712c RC |
876 | if (changed && stat(LO, &stbuf) >= 0) |
877 | (void) chmod(LO, (stbuf.st_mode & 0777) | 01); | |
25e0cdec BJ |
878 | } |
879 | ||
a7a48f56 RC |
880 | /* |
881 | * Reposition the job by changing the modification time of | |
882 | * the control file. | |
25e0cdec | 883 | */ |
a7a48f56 RC |
884 | touch(q) |
885 | struct queue *q; | |
25e0cdec | 886 | { |
a7a48f56 | 887 | struct timeval tvp[2]; |
25e0cdec | 888 | |
a7a48f56 RC |
889 | tvp[0].tv_sec = tvp[1].tv_sec = --mtime; |
890 | tvp[0].tv_usec = tvp[1].tv_usec = 0; | |
891 | return(utimes(q->q_name, tvp)); | |
25e0cdec BJ |
892 | } |
893 | ||
894 | /* | |
895 | * Checks if specified job name is in the printer's queue. | |
896 | * Returns: negative (-1) if argument name is not in the queue. | |
25e0cdec | 897 | */ |
a7a48f56 | 898 | doarg(job) |
25e0cdec | 899 | char *job; |
25e0cdec | 900 | { |
a7a48f56 RC |
901 | register struct queue **qq; |
902 | register int jobnum, n; | |
903 | register char *cp, *machine; | |
904 | int cnt = 0; | |
2138712c | 905 | FILE *fp; |
25e0cdec | 906 | |
a7a48f56 RC |
907 | /* |
908 | * Look for a job item consisting of system name, colon, number | |
909 | * (example: ucbarpa:114) | |
910 | */ | |
911 | if ((cp = index(job, ':')) != NULL) { | |
912 | machine = job; | |
913 | *cp++ = '\0'; | |
914 | job = cp; | |
915 | } else | |
916 | machine = NULL; | |
917 | ||
918 | /* | |
919 | * Check for job specified by number (example: 112 or 235ucbarpa). | |
920 | */ | |
25e0cdec BJ |
921 | if (isdigit(*job)) { |
922 | jobnum = 0; | |
923 | do | |
924 | jobnum = jobnum * 10 + (*job++ - '0'); | |
925 | while (isdigit(*job)); | |
a7a48f56 | 926 | for (qq = queue + nitems; --qq >= queue; ) { |
25e0cdec | 927 | n = 0; |
a7a48f56 | 928 | for (cp = (*qq)->q_name+3; isdigit(*cp); ) |
2138712c | 929 | n = n * 10 + (*cp++ - '0'); |
a7a48f56 RC |
930 | if (jobnum != n) |
931 | continue; | |
932 | if (*job && strcmp(job, cp) != 0) | |
933 | continue; | |
934 | if (machine != NULL && strcmp(machine, cp) != 0) | |
935 | continue; | |
936 | if (touch(*qq) == 0) { | |
937 | printf("\tmoved %s\n", (*qq)->q_name); | |
938 | cnt++; | |
25e0cdec BJ |
939 | } |
940 | } | |
a7a48f56 RC |
941 | return(cnt); |
942 | } | |
943 | /* | |
944 | * Process item consisting of owner's name (example: henry). | |
945 | */ | |
946 | for (qq = queue + nitems; --qq >= queue; ) { | |
947 | if ((fp = fopen((*qq)->q_name, "r")) == NULL) | |
948 | continue; | |
949 | while (getline(fp) > 0) | |
950 | if (line[0] == 'P') | |
951 | break; | |
2138712c | 952 | (void) fclose(fp); |
a7a48f56 RC |
953 | if (line[0] != 'P' || strcmp(job, line+1) != 0) |
954 | continue; | |
955 | if (touch(*qq) == 0) { | |
956 | printf("\tmoved %s\n", (*qq)->q_name); | |
957 | cnt++; | |
958 | } | |
25e0cdec | 959 | } |
a7a48f56 | 960 | return(cnt); |
25e0cdec | 961 | } |
71a561a3 RC |
962 | |
963 | /* | |
964 | * Enable everything and start printer (undo `down'). | |
965 | */ | |
966 | up(argc, argv) | |
967 | char *argv[]; | |
968 | { | |
969 | register int c, status; | |
970 | register char *cp1, *cp2; | |
971 | char prbuf[100]; | |
972 | ||
973 | if (argc == 1) { | |
974 | printf("Usage: up {all | printer ...}\n"); | |
975 | return; | |
976 | } | |
977 | if (argc == 2 && !strcmp(argv[1], "all")) { | |
978 | printer = prbuf; | |
979 | while (getprent(line) > 0) { | |
980 | cp1 = prbuf; | |
981 | cp2 = line; | |
982 | while ((c = *cp2++) && c != '|' && c != ':') | |
983 | *cp1++ = c; | |
984 | *cp1 = '\0'; | |
985 | startpr(2); | |
986 | } | |
987 | return; | |
988 | } | |
989 | while (--argc) { | |
990 | printer = *++argv; | |
991 | if ((status = pgetent(line, printer)) < 0) { | |
992 | printf("cannot open printer description file\n"); | |
993 | continue; | |
994 | } else if (status == 0) { | |
995 | printf("unknown printer %s\n", printer); | |
996 | continue; | |
997 | } | |
998 | startpr(2); | |
999 | } | |
1000 | } |