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