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