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