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