update the status file when printing is disabled
[unix-history] / usr / src / usr.sbin / lpr / lpc / cmds.c
CommitLineData
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 19static 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 */
33abort(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 69abortpr(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 */
131upstat(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 */
158clean(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
194select(d)
195struct 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 */
208sortq(d1, d2)
209struct 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
229cleanpr()
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
280unlinkf(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 */
292enable(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
328enablepr()
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 */
354disable(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
390disablepr()
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 */
426down(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
460putmsg(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 */
527quit(argc, argv)
528 char *argv[];
529{
530 exit(0);
531}
532
533/*
71a561a3 534 * Kill and restart the daemon.
5df74a28
RC
535 */
536restart(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 */
577start(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
613startpr(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 */
643status(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 */
678prstat()
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 */
741stop(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
777stoppr()
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
812struct queue **queue;
813int nitems;
814time_t mtime;
815
25e0cdec
BJ
816/*
817 * Put the specified jobs at the top of printer queue.
818 */
819topq(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
884touch(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 898doarg(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 */
966up(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}