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