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