xref: /csrg-svn/usr.sbin/lpr/lpc/cmds.c (revision 15907)
1 #ifndef lint
2 static char sccsid[] = "@(#)cmds.c	4.10 (Berkeley) 01/30/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: disable {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 	if (argc <= 0)
450 		return;
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 	cp1 = buf;
459 	while (--argc >= 0) {
460 		cp2 = *argv++;
461 		while (*cp1++ = *cp2++)
462 			;
463 		cp1[-1] = ' ';
464 	}
465 	cp1[-1] = '\n';
466 	*cp1 = '\0';
467 	(void) write(fd, buf, strlen(buf));
468 	(void) close(fd);
469 }
470 
471 /*
472  * Exit lpc
473  */
474 quit(argc, argv)
475 	char *argv[];
476 {
477 	exit(0);
478 }
479 
480 /*
481  * Startup the daemon.
482  */
483 restart(argc, argv)
484 	char *argv[];
485 {
486 	register int c, status;
487 	register char *cp1, *cp2;
488 	char prbuf[100];
489 
490 	if (argc == 1) {
491 		printf("Usage: restart {all | printer ...}\n");
492 		return;
493 	}
494 	gethostname(host, sizeof(host));
495 	if (argc == 2 && !strcmp(argv[1], "all")) {
496 		printer = prbuf;
497 		while (getprent(line) > 0) {
498 			cp1 = prbuf;
499 			cp2 = line;
500 			while ((c = *cp2++) && c != '|' && c != ':')
501 				*cp1++ = c;
502 			*cp1 = '\0';
503 			startpr(0);
504 		}
505 		return;
506 	}
507 	while (--argc) {
508 		printer = *++argv;
509 		if ((status = pgetent(line, printer)) < 0) {
510 			printf("cannot open printer description file\n");
511 			continue;
512 		} else if (status == 0) {
513 			printf("unknown printer %s\n", printer);
514 			continue;
515 		}
516 		startpr(0);
517 	}
518 }
519 
520 /*
521  * Enable printing on the specified printer and startup the daemon.
522  */
523 start(argc, argv)
524 	char *argv[];
525 {
526 	register int c, status;
527 	register char *cp1, *cp2;
528 	char prbuf[100];
529 
530 	if (argc == 1) {
531 		printf("Usage: start {all | printer ...}\n");
532 		return;
533 	}
534 	gethostname(host, sizeof(host));
535 	if (argc == 2 && !strcmp(argv[1], "all")) {
536 		printer = prbuf;
537 		while (getprent(line) > 0) {
538 			cp1 = prbuf;
539 			cp2 = line;
540 			while ((c = *cp2++) && c != '|' && c != ':')
541 				*cp1++ = c;
542 			*cp1 = '\0';
543 			startpr(1);
544 		}
545 		return;
546 	}
547 	while (--argc) {
548 		printer = *++argv;
549 		if ((status = pgetent(line, printer)) < 0) {
550 			printf("cannot open printer description file\n");
551 			continue;
552 		} else if (status == 0) {
553 			printf("unknown printer %s\n", printer);
554 			continue;
555 		}
556 		startpr(1);
557 	}
558 }
559 
560 startpr(enable)
561 {
562 	struct stat stbuf;
563 
564 	bp = pbuf;
565 	if ((SD = pgetstr("sd", &bp)) == NULL)
566 		SD = DEFSPOOL;
567 	if ((LO = pgetstr("lo", &bp)) == NULL)
568 		LO = DEFLOCK;
569 	(void) sprintf(line, "%s/%s", SD, LO);
570 	printf("%s:\n", printer);
571 
572 	/*
573 	 * Turn off the owner execute bit of the lock file to enable printing.
574 	 */
575 	if (enable && stat(line, &stbuf) >= 0) {
576 		if (chmod(line, stbuf.st_mode & 0677) < 0)
577 			printf("\tcannot enable printing\n");
578 		else
579 			printf("\tprinting enabled\n");
580 	}
581 	if (!startdaemon(printer))
582 		printf("\tcouldn't start daemon\n");
583 	else
584 		printf("\tdaemon started\n");
585 }
586 
587 /*
588  * Print the status of each queue listed or all the queues.
589  */
590 status(argc, argv)
591 	char *argv[];
592 {
593 	register int c, status;
594 	register char *cp1, *cp2;
595 	char prbuf[100];
596 
597 	if (argc == 1) {
598 		printer = prbuf;
599 		while (getprent(line) > 0) {
600 			cp1 = prbuf;
601 			cp2 = line;
602 			while ((c = *cp2++) && c != '|' && c != ':')
603 				*cp1++ = c;
604 			*cp1 = '\0';
605 			prstat();
606 		}
607 		return;
608 	}
609 	while (--argc) {
610 		printer = *++argv;
611 		if ((status = pgetent(line, printer)) < 0) {
612 			printf("cannot open printer description file\n");
613 			continue;
614 		} else if (status == 0) {
615 			printf("unknown printer %s\n", printer);
616 			continue;
617 		}
618 		prstat();
619 	}
620 }
621 
622 /*
623  * Print the status of the printer queue.
624  */
625 prstat()
626 {
627 	struct stat stbuf;
628 	register int fd, i;
629 	register struct direct *dp;
630 	DIR *dirp;
631 
632 	bp = pbuf;
633 	if ((SD = pgetstr("sd", &bp)) == NULL)
634 		SD = DEFSPOOL;
635 	if ((LO = pgetstr("lo", &bp)) == NULL)
636 		LO = DEFLOCK;
637 	if ((ST = pgetstr("st", &bp)) == NULL)
638 		ST = DEFSTAT;
639 	printf("%s:\n", printer);
640 	(void) sprintf(line, "%s/%s", SD, LO);
641 	if (stat(line, &stbuf) >= 0) {
642 		printf("\tqueuing is %s\n",
643 			(stbuf.st_mode & 010) ? "disabled" : "enabled");
644 		printf("\tprinting is %s\n",
645 			(stbuf.st_mode & 0100) ? "disabled" : "enabled");
646 	} else {
647 		printf("\tqueuing is enabled\n");
648 		printf("\tprinting is enabled\n");
649 	}
650 	if ((dirp = opendir(SD)) == NULL) {
651 		printf("\tcannot examine spool directory\n");
652 		return;
653 	}
654 	i = 0;
655 	while ((dp = readdir(dirp)) != NULL) {
656 		if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
657 			i++;
658 	}
659 	closedir(dirp);
660 	if (i == 0)
661 		printf("\tno entries\n");
662 	else if (i == 1)
663 		printf("\t1 entry in spool area\n");
664 	else
665 		printf("\t%d entries in spool area\n", i);
666 	fd = open(line, O_RDONLY);
667 	if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
668 		(void) close(fd);	/* unlocks as well */
669 		printf("\tno daemon present\n");
670 		return;
671 	}
672 	(void) close(fd);
673 	putchar('\t');
674 	(void) sprintf(line, "%s/%s", SD, ST);
675 	fd = open(line, O_RDONLY);
676 	if (fd >= 0) {
677 		(void) flock(fd, LOCK_SH);
678 		while ((i = read(fd, line, sizeof(line))) > 0)
679 			(void) fwrite(line, 1, i, stdout);
680 		(void) close(fd);	/* unlocks as well */
681 	}
682 }
683 
684 /*
685  * Stop the specified daemon after completing the current job and disable
686  * printing.
687  */
688 stop(argc, argv)
689 	char *argv[];
690 {
691 	register int c, status;
692 	register char *cp1, *cp2;
693 	char prbuf[100];
694 
695 	if (argc == 1) {
696 		printf("Usage: stop {all | printer ...}\n");
697 		return;
698 	}
699 	if (argc == 2 && !strcmp(argv[1], "all")) {
700 		printer = prbuf;
701 		while (getprent(line) > 0) {
702 			cp1 = prbuf;
703 			cp2 = line;
704 			while ((c = *cp2++) && c != '|' && c != ':')
705 				*cp1++ = c;
706 			*cp1 = '\0';
707 			stoppr();
708 		}
709 		return;
710 	}
711 	while (--argc) {
712 		printer = *++argv;
713 		if ((status = pgetent(line, printer)) < 0) {
714 			printf("cannot open printer description file\n");
715 			continue;
716 		} else if (status == 0) {
717 			printf("unknown printer %s\n", printer);
718 			continue;
719 		}
720 		stoppr();
721 	}
722 }
723 
724 stoppr()
725 {
726 	register int fd;
727 	struct stat stbuf;
728 
729 	bp = pbuf;
730 	if ((SD = pgetstr("sd", &bp)) == NULL)
731 		SD = DEFSPOOL;
732 	if ((LO = pgetstr("lo", &bp)) == NULL)
733 		LO = DEFLOCK;
734 	(void) sprintf(line, "%s/%s", SD, LO);
735 	printf("%s:\n", printer);
736 
737 	/*
738 	 * Turn on the owner execute bit of the lock file to disable printing.
739 	 */
740 	if (stat(line, &stbuf) >= 0) {
741 		if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
742 			printf("\tcannot disable printing\n");
743 		else
744 			printf("\tprinting disabled\n");
745 	} else if (errno == ENOENT) {
746 		if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
747 			printf("\tcannot create lock file\n");
748 		else {
749 			(void) close(fd);
750 			printf("\tprinting disabled\n");
751 		}
752 	} else
753 		printf("\tcannot stat lock file\n");
754 }
755 
756 struct	queue **queue;
757 int	nitems;
758 time_t	mtime;
759 
760 /*
761  * Put the specified jobs at the top of printer queue.
762  */
763 topq(argc, argv)
764 	char *argv[];
765 {
766 	register int n, i;
767 	struct stat stbuf;
768 	register char *cfname;
769 	int status, changed;
770 
771 	if (argc < 3) {
772 		printf("Usage: topq printer [jobnum ...] [user ...]\n");
773 		return;
774 	}
775 
776 	--argc;
777 	printer = *++argv;
778 	status = pgetent(line, printer);
779 	if (status < 0) {
780 		printf("cannot open printer description file\n");
781 		return;
782 	} else if (status == 0) {
783 		printf("%s: unknown printer\n", printer);
784 		return;
785 	}
786 	bp = pbuf;
787 	if ((SD = pgetstr("sd", &bp)) == NULL)
788 		SD = DEFSPOOL;
789 	if ((LO = pgetstr("lo", &bp)) == NULL)
790 		LO = DEFLOCK;
791 	printf("%s:\n", printer);
792 
793 	if (chdir(SD) < 0) {
794 		printf("\tcannot chdir to %s\n", SD);
795 		return;
796 	}
797 	nitems = getq(&queue);
798 	if (nitems == 0)
799 		return;
800 	changed = 0;
801 	mtime = queue[0]->q_time;
802 	for (i = argc; --i; ) {
803 		if (doarg(argv[i]) == 0) {
804 			printf("\tjob %s is not in the queue\n", argv[i]);
805 			continue;
806 		} else
807 			changed++;
808 	}
809 	for (i = 0; i < nitems; i++)
810 		free(queue[i]);
811 	free(queue);
812 	if (!changed) {
813 		printf("\tqueue order unchanged\n");
814 		return;
815 	}
816 	/*
817 	 * Turn on the public execute bit of the lock file to
818 	 * get lpd to rebuild the queue after the current job.
819 	 */
820 	if (changed && stat(LO, &stbuf) >= 0)
821 		(void) chmod(LO, (stbuf.st_mode & 0777) | 01);
822 }
823 
824 /*
825  * Reposition the job by changing the modification time of
826  * the control file.
827  */
828 touch(q)
829 	struct queue *q;
830 {
831 	struct timeval tvp[2];
832 
833 	tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
834 	tvp[0].tv_usec = tvp[1].tv_usec = 0;
835 	return(utimes(q->q_name, tvp));
836 }
837 
838 /*
839  * Checks if specified job name is in the printer's queue.
840  * Returns:  negative (-1) if argument name is not in the queue.
841  */
842 doarg(job)
843 	char *job;
844 {
845 	register struct queue **qq;
846 	register int jobnum, n;
847 	register char *cp, *machine;
848 	int cnt = 0;
849 	FILE *fp;
850 
851 	/*
852 	 * Look for a job item consisting of system name, colon, number
853 	 * (example: ucbarpa:114)
854 	 */
855 	if ((cp = index(job, ':')) != NULL) {
856 		machine = job;
857 		*cp++ = '\0';
858 		job = cp;
859 	} else
860 		machine = NULL;
861 
862 	/*
863 	 * Check for job specified by number (example: 112 or 235ucbarpa).
864 	 */
865 	if (isdigit(*job)) {
866 		jobnum = 0;
867 		do
868 			jobnum = jobnum * 10 + (*job++ - '0');
869 		while (isdigit(*job));
870 		for (qq = queue + nitems; --qq >= queue; ) {
871 			n = 0;
872 			for (cp = (*qq)->q_name+3; isdigit(*cp); )
873 				n = n * 10 + (*cp++ - '0');
874 			if (jobnum != n)
875 				continue;
876 			if (*job && strcmp(job, cp) != 0)
877 				continue;
878 			if (machine != NULL && strcmp(machine, cp) != 0)
879 				continue;
880 			if (touch(*qq) == 0) {
881 				printf("\tmoved %s\n", (*qq)->q_name);
882 				cnt++;
883 			}
884 		}
885 		return(cnt);
886 	}
887 	/*
888 	 * Process item consisting of owner's name (example: henry).
889 	 */
890 	for (qq = queue + nitems; --qq >= queue; ) {
891 		if ((fp = fopen((*qq)->q_name, "r")) == NULL)
892 			continue;
893 		while (getline(fp) > 0)
894 			if (line[0] == 'P')
895 				break;
896 		(void) fclose(fp);
897 		if (line[0] != 'P' || strcmp(job, line+1) != 0)
898 			continue;
899 		if (touch(*qq) == 0) {
900 			printf("\tmoved %s\n", (*qq)->q_name);
901 			cnt++;
902 		}
903 	}
904 	return(cnt);
905 }
906