xref: /original-bsd/usr.sbin/lpr/lpc/cmds.c (revision 4b2c5e10)
1 #ifndef lint
2 static char sccsid[] = "@(#)cmds.c	4.8 (Berkeley) 07/27/83";
3 #endif
4 
5 /*
6  * lpc -- line printer control program
7  */
8 
9 #include "lp.h"
10 
11 /*
12  * kill an existing daemon and disable printing.
13  */
14 abort(argc, argv)
15 	char *argv[];
16 {
17 	register int c, status;
18 	register char *cp1, *cp2;
19 	char prbuf[100];
20 
21 	if (argc == 1) {
22 		printf("Usage: abort {all | printer ...}\n");
23 		return;
24 	}
25 	if (argc == 2 && !strcmp(argv[1], "all")) {
26 		printer = prbuf;
27 		while (getprent(line) > 0) {
28 			cp1 = prbuf;
29 			cp2 = line;
30 			while ((c = *cp2++) && c != '|' && c != ':')
31 				*cp1++ = c;
32 			*cp1 = '\0';
33 			abortpr();
34 		}
35 		return;
36 	}
37 	while (--argc) {
38 		printer = *++argv;
39 		if ((status = pgetent(line, printer)) < 0) {
40 			printf("cannot open printer description file\n");
41 			continue;
42 		} else if (status == 0) {
43 			printf("unknown printer %s\n", printer);
44 			continue;
45 		}
46 		abortpr();
47 	}
48 }
49 
50 abortpr()
51 {
52 	register FILE *fp;
53 	struct stat stbuf;
54 	int pid, fd;
55 
56 	bp = pbuf;
57 	if ((SD = pgetstr("sd", &bp)) == NULL)
58 		SD = DEFSPOOL;
59 	if ((LO = pgetstr("lo", &bp)) == NULL)
60 		LO = DEFLOCK;
61 	(void) sprintf(line, "%s/%s", SD, LO);
62 	printf("%s:\n", printer);
63 
64 	/*
65 	 * Turn on the owner execute bit of the lock file to disable printing.
66 	 */
67 	if (stat(line, &stbuf) >= 0) {
68 		if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
69 			printf("\tcannot disable printing\n");
70 		else
71 			printf("\tprinting disabled\n");
72 	} else if (errno == ENOENT) {
73 		if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
74 			printf("\tcannot create lock file\n");
75 		else {
76 			(void) close(fd);
77 			printf("\tprinting disabled\n");
78 			printf("\tno daemon to abort\n");
79 		}
80 		return;
81 	} else {
82 		printf("\tcannot stat lock file\n");
83 		return;
84 	}
85 	/*
86 	 * Kill the current daemon to stop printing now.
87 	 */
88 	if ((fp = fopen(line, "r")) == NULL) {
89 		printf("\tcannot open lock file\n");
90 		return;
91 	}
92 	if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
93 		(void) fclose(fp);	/* unlocks as well */
94 		printf("\tno daemon to abort\n");
95 		return;
96 	}
97 	(void) fclose(fp);
98 	if (kill(pid = atoi(line), SIGINT) < 0)
99 		printf("\tWarning: daemon (pid %d) not killed\n", pid);
100 	else
101 		printf("\tdaemon (pid %d) killed\n", pid);
102 }
103 
104 /*
105  * Remove all spool files and temporaries from the spooling area.
106  */
107 clean(argc, argv)
108 	char *argv[];
109 {
110 	register int c, status;
111 	register char *cp1, *cp2;
112 	char prbuf[100];
113 
114 	if (argc == 1) {
115 		printf("Usage: clean {all | printer ...}\n");
116 		return;
117 	}
118 	if (argc == 2 && !strcmp(argv[1], "all")) {
119 		printer = prbuf;
120 		while (getprent(line) > 0) {
121 			cp1 = prbuf;
122 			cp2 = line;
123 			while ((c = *cp2++) && c != '|' && c != ':')
124 				*cp1++ = c;
125 			*cp1 = '\0';
126 			cleanpr();
127 		}
128 		return;
129 	}
130 	while (--argc) {
131 		printer = *++argv;
132 		if ((status = pgetent(line, printer)) < 0) {
133 			printf("cannot open printer description file\n");
134 			continue;
135 		} else if (status == 0) {
136 			printf("unknown printer %s\n", printer);
137 			continue;
138 		}
139 		cleanpr();
140 	}
141 }
142 
143 cleanpr()
144 {
145 	register int c;
146 	register DIR *dirp;
147 	register struct direct *dp;
148 	char *cp, *cp1;
149 
150 	bp = pbuf;
151 	if ((SD = pgetstr("sd", &bp)) == NULL)
152 		SD = DEFSPOOL;
153 	for (cp = line, cp1 = SD; *cp++ = *cp1++; );
154 	cp[-1] = '/';
155 	printf("%s:\n", printer);
156 
157 	if ((dirp = opendir(SD)) == NULL) {
158 		printf("\tcannot examine spool directory\n");
159 		return;
160 	}
161 	while ((dp = readdir(dirp)) != NULL) {
162 		c = dp->d_name[0];
163 		if ((c == 'c' || c == 't' || c == 'd') && dp->d_name[1]=='f') {
164 			strcpy(cp, dp->d_name);
165 			if (unlink(line) < 0)
166 				printf("\tcannot remove %s\n", line);
167 			else
168 				printf("\tremoved %s\n", line);
169 		}
170 	}
171 	closedir(dirp);
172 }
173 
174 /*
175  * Enable queuing to the printer (allow lpr's).
176  */
177 enable(argc, argv)
178 	char *argv[];
179 {
180 	register int c, status;
181 	register char *cp1, *cp2;
182 	char prbuf[100];
183 
184 	if (argc == 1) {
185 		printf("Usage: enable {all | printer ...}\n");
186 		return;
187 	}
188 	if (argc == 2 && !strcmp(argv[1], "all")) {
189 		printer = prbuf;
190 		while (getprent(line) > 0) {
191 			cp1 = prbuf;
192 			cp2 = line;
193 			while ((c = *cp2++) && c != '|' && c != ':')
194 				*cp1++ = c;
195 			*cp1 = '\0';
196 			enablepr();
197 		}
198 		return;
199 	}
200 	while (--argc) {
201 		printer = *++argv;
202 		if ((status = pgetent(line, printer)) < 0) {
203 			printf("cannot open printer description file\n");
204 			continue;
205 		} else if (status == 0) {
206 			printf("unknown printer %s\n", printer);
207 			continue;
208 		}
209 		enablepr();
210 	}
211 }
212 
213 enablepr()
214 {
215 	struct stat stbuf;
216 
217 	bp = pbuf;
218 	if ((SD = pgetstr("sd", &bp)) == NULL)
219 		SD = DEFSPOOL;
220 	if ((LO = pgetstr("lo", &bp)) == NULL)
221 		LO = DEFLOCK;
222 	(void) sprintf(line, "%s/%s", SD, LO);
223 	printf("%s:\n", printer);
224 
225 	/*
226 	 * Turn off the group execute bit of the lock file to enable queuing.
227 	 */
228 	if (stat(line, &stbuf) >= 0) {
229 		if (chmod(line, stbuf.st_mode & 0767) < 0)
230 			printf("\tcannot enable queuing\n");
231 		else
232 			printf("\tqueuing enabled\n");
233 	}
234 }
235 
236 /*
237  * Disable queuing.
238  */
239 disable(argc, argv)
240 	char *argv[];
241 {
242 	register int c, status;
243 	register char *cp1, *cp2;
244 	char prbuf[100];
245 
246 	if (argc == 1) {
247 		printf("Usage: disable {all | printer ...}\n");
248 		return;
249 	}
250 	if (argc == 2 && !strcmp(argv[1], "all")) {
251 		printer = prbuf;
252 		while (getprent(line) > 0) {
253 			cp1 = prbuf;
254 			cp2 = line;
255 			while ((c = *cp2++) && c != '|' && c != ':')
256 				*cp1++ = c;
257 			*cp1 = '\0';
258 			disablepr();
259 		}
260 		return;
261 	}
262 	while (--argc) {
263 		printer = *++argv;
264 		if ((status = pgetent(line, printer)) < 0) {
265 			printf("cannot open printer description file\n");
266 			continue;
267 		} else if (status == 0) {
268 			printf("unknown printer %s\n", printer);
269 			continue;
270 		}
271 		disablepr();
272 	}
273 }
274 
275 disablepr()
276 {
277 	register int fd;
278 	struct stat stbuf;
279 
280 	bp = pbuf;
281 	if ((SD = pgetstr("sd", &bp)) == NULL)
282 		SD = DEFSPOOL;
283 	if ((LO = pgetstr("lo", &bp)) == NULL)
284 		LO = DEFLOCK;
285 	(void) sprintf(line, "%s/%s", SD, LO);
286 	printf("%s:\n", printer);
287 	/*
288 	 * Turn on the group execute bit of the lock file to disable queuing.
289 	 */
290 	if (stat(line, &stbuf) >= 0) {
291 		if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
292 			printf("\tcannot disable queuing\n");
293 		else
294 			printf("\tqueuing disabled\n");
295 	} else if (errno == ENOENT) {
296 		if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
297 			printf("\tcannot create lock file\n");
298 		else {
299 			(void) close(fd);
300 			printf("\tqueuing disabled\n");
301 		}
302 		return;
303 	} else
304 		printf("\tcannot stat lock file\n");
305 }
306 
307 /*
308  * Exit lpc
309  */
310 quit(argc, argv)
311 	char *argv[];
312 {
313 	exit(0);
314 }
315 
316 /*
317  * Startup the daemon.
318  */
319 restart(argc, argv)
320 	char *argv[];
321 {
322 	register int c, status;
323 	register char *cp1, *cp2;
324 	char prbuf[100];
325 
326 	if (argc == 1) {
327 		printf("Usage: restart {all | printer ...}\n");
328 		return;
329 	}
330 	gethostname(host, sizeof(host));
331 	if (argc == 2 && !strcmp(argv[1], "all")) {
332 		printer = prbuf;
333 		while (getprent(line) > 0) {
334 			cp1 = prbuf;
335 			cp2 = line;
336 			while ((c = *cp2++) && c != '|' && c != ':')
337 				*cp1++ = c;
338 			*cp1 = '\0';
339 			startpr(0);
340 		}
341 		return;
342 	}
343 	while (--argc) {
344 		printer = *++argv;
345 		if ((status = pgetent(line, printer)) < 0) {
346 			printf("cannot open printer description file\n");
347 			continue;
348 		} else if (status == 0) {
349 			printf("unknown printer %s\n", printer);
350 			continue;
351 		}
352 		startpr(0);
353 	}
354 }
355 
356 /*
357  * Enable printing on the specified printer and startup the daemon.
358  */
359 start(argc, argv)
360 	char *argv[];
361 {
362 	register int c, status;
363 	register char *cp1, *cp2;
364 	char prbuf[100];
365 
366 	if (argc == 1) {
367 		printf("Usage: start {all | printer ...}\n");
368 		return;
369 	}
370 	gethostname(host, sizeof(host));
371 	if (argc == 2 && !strcmp(argv[1], "all")) {
372 		printer = prbuf;
373 		while (getprent(line) > 0) {
374 			cp1 = prbuf;
375 			cp2 = line;
376 			while ((c = *cp2++) && c != '|' && c != ':')
377 				*cp1++ = c;
378 			*cp1 = '\0';
379 			startpr(1);
380 		}
381 		return;
382 	}
383 	while (--argc) {
384 		printer = *++argv;
385 		if ((status = pgetent(line, printer)) < 0) {
386 			printf("cannot open printer description file\n");
387 			continue;
388 		} else if (status == 0) {
389 			printf("unknown printer %s\n", printer);
390 			continue;
391 		}
392 		startpr(1);
393 	}
394 }
395 
396 startpr(enable)
397 {
398 	struct stat stbuf;
399 
400 	bp = pbuf;
401 	if ((SD = pgetstr("sd", &bp)) == NULL)
402 		SD = DEFSPOOL;
403 	if ((LO = pgetstr("lo", &bp)) == NULL)
404 		LO = DEFLOCK;
405 	(void) sprintf(line, "%s/%s", SD, LO);
406 	printf("%s:\n", printer);
407 
408 	/*
409 	 * Turn off the owner execute bit of the lock file to enable printing.
410 	 */
411 	if (enable && stat(line, &stbuf) >= 0) {
412 		if (chmod(line, stbuf.st_mode & 0677) < 0)
413 			printf("\tcannot enable printing\n");
414 		else
415 			printf("\tprinting enabled\n");
416 	}
417 	if (!startdaemon(printer))
418 		printf("\tcouldn't start daemon\n");
419 	else
420 		printf("\tdaemon started\n");
421 }
422 
423 /*
424  * Print the status of each queue listed or all the queues.
425  */
426 status(argc, argv)
427 	char *argv[];
428 {
429 	register int c, status;
430 	register char *cp1, *cp2;
431 	char prbuf[100];
432 
433 	if (argc == 1) {
434 		printer = prbuf;
435 		while (getprent(line) > 0) {
436 			cp1 = prbuf;
437 			cp2 = line;
438 			while ((c = *cp2++) && c != '|' && c != ':')
439 				*cp1++ = c;
440 			*cp1 = '\0';
441 			prstat();
442 		}
443 		return;
444 	}
445 	while (--argc) {
446 		printer = *++argv;
447 		if ((status = pgetent(line, printer)) < 0) {
448 			printf("cannot open printer description file\n");
449 			continue;
450 		} else if (status == 0) {
451 			printf("unknown printer %s\n", printer);
452 			continue;
453 		}
454 		prstat();
455 	}
456 }
457 
458 /*
459  * Print the status of the printer queue.
460  */
461 prstat()
462 {
463 	struct stat stbuf;
464 	register int fd, i;
465 	register struct direct *dp;
466 	DIR *dirp;
467 
468 	bp = pbuf;
469 	if ((SD = pgetstr("sd", &bp)) == NULL)
470 		SD = DEFSPOOL;
471 	if ((LO = pgetstr("lo", &bp)) == NULL)
472 		LO = DEFLOCK;
473 	if ((ST = pgetstr("st", &bp)) == NULL)
474 		ST = DEFSTAT;
475 	printf("%s:\n", printer);
476 	(void) sprintf(line, "%s/%s", SD, LO);
477 	if (stat(line, &stbuf) >= 0) {
478 		printf("\tqueuing is %s\n",
479 			(stbuf.st_mode & 010) ? "disabled" : "enabled");
480 		printf("\tprinting is %s\n",
481 			(stbuf.st_mode & 0100) ? "disabled" : "enabled");
482 	} else {
483 		printf("\tqueuing is enabled\n");
484 		printf("\tprinting is enabled\n");
485 	}
486 	if ((dirp = opendir(SD)) == NULL) {
487 		printf("\tcannot examine spool directory\n");
488 		return;
489 	}
490 	i = 0;
491 	while ((dp = readdir(dirp)) != NULL) {
492 		if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
493 			i++;
494 	}
495 	closedir(dirp);
496 	if (i == 0)
497 		printf("\tno entries\n");
498 	else if (i == 1)
499 		printf("\t1 entry in spool area\n");
500 	else
501 		printf("\t%d entries in spool area\n", i);
502 	fd = open(line, O_RDONLY);
503 	if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
504 		(void) close(fd);	/* unlocks as well */
505 		printf("\tno daemon present\n");
506 		return;
507 	}
508 	(void) close(fd);
509 	putchar('\t');
510 	(void) sprintf(line, "%s/%s", SD, ST);
511 	fd = open(line, O_RDONLY);
512 	if (fd >= 0) {
513 		(void) flock(fd, LOCK_SH);
514 		while ((i = read(fd, line, sizeof(line))) > 0)
515 			(void) fwrite(line, 1, i, stdout);
516 		(void) close(fd);	/* unlocks as well */
517 	}
518 }
519 
520 /*
521  * Stop the specified daemon after completing the current job and disable
522  * printing.
523  */
524 stop(argc, argv)
525 	char *argv[];
526 {
527 	register int c, status;
528 	register char *cp1, *cp2;
529 	char prbuf[100];
530 
531 	if (argc == 1) {
532 		printf("Usage: stop {all | printer ...}\n");
533 		return;
534 	}
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 			stoppr();
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 		stoppr();
557 	}
558 }
559 
560 stoppr()
561 {
562 	register int fd;
563 	struct stat stbuf;
564 
565 	bp = pbuf;
566 	if ((SD = pgetstr("sd", &bp)) == NULL)
567 		SD = DEFSPOOL;
568 	if ((LO = pgetstr("lo", &bp)) == NULL)
569 		LO = DEFLOCK;
570 	(void) sprintf(line, "%s/%s", SD, LO);
571 	printf("%s:\n", printer);
572 
573 	/*
574 	 * Turn on the owner execute bit of the lock file to disable printing.
575 	 */
576 	if (stat(line, &stbuf) >= 0) {
577 		if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
578 			printf("\tcannot disable printing\n");
579 		else
580 			printf("\tprinting disabled\n");
581 	} else if (errno == ENOENT) {
582 		if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
583 			printf("\tcannot create lock file\n");
584 		else {
585 			(void) close(fd);
586 			printf("\tprinting disabled\n");
587 		}
588 	} else
589 		printf("\tcannot stat lock file\n");
590 }
591 
592 /*
593  * Put the specified jobs at the top of printer queue.
594  */
595 topq(argc, argv)
596 	char *argv[];
597 {
598 	register int status, nitems, n;
599 	struct stat stbuf;
600 	register char *cfname;
601 	struct queue **queue;
602 	int changed = 0;
603 
604 	if (argc == 1) {
605 		printf("Usage: topq printer [jobnum ...] [user ...]\n");
606 		return;
607 	}
608 
609 	--argc;
610 	printer = *++argv;
611 	status = pgetent(line, printer);
612 	if (status < 0) {
613 		printf("cannot open printer description file\n");
614 		return;
615 	} else if (status == 0) {
616 		printf("%s: unknown printer\n", printer);
617 		return;
618 	}
619 	bp = pbuf;
620 	if ((SD = pgetstr("sd", &bp)) == NULL)
621 		SD = DEFSPOOL;
622 	if ((LO = pgetstr("lo", &bp)) == NULL)
623 		LO = DEFLOCK;
624 	printf("%s:\n", printer);
625 
626 	if (chdir(SD) < 0) {
627 		printf("\tcannot chdir to %s\n", SD);
628 		return;
629 	}
630 	nitems = getq(&queue);
631 	while (--argc) {
632 		if ((n = inqueue(*++argv, queue, nitems)) < 0) {
633 			printf("\tjob %s is not in the queue\n", *argv);
634 			continue;
635 		}
636 		/*
637 		 * Reposition the job by changing the modification time of
638 		 * the control file.
639 		 */
640 		if (touch(queue[n]->q_name)) {
641 			free(queue[n]);
642 			queue[n] = NULL;
643 			changed++;
644 		}
645 	}
646 	/*
647 	 * Put the remaining jobs at the end of the queue.
648 	 */
649 	for (n = 0; n < nitems; n++) {
650 		if (queue[n] == NULL)
651 			continue;
652 		cfname = queue[n]->q_name;
653 		if (changed)
654 			touch(cfname);
655 		free(cfname);
656 	}
657 	free(queue);
658 	printf("\tqueue order %s\n", changed ? "changed" : "unchanged");
659 	/*
660 	 * Turn on the public execute bit of the lock file to
661 	 * get lpd to rebuild the queue after the current job.
662 	 */
663 	if (changed && stat(LO, &stbuf) >= 0)
664 		(void) chmod(LO, (stbuf.st_mode & 0777) | 01);
665 }
666 
667 /*
668  * Change the modification time of the file.
669  *	Returns boolean if successful.
670  */
671 touch(cfname)
672 	char *cfname;
673 {
674 	register int fd;
675 
676 	fd = open(cfname, O_RDWR);
677 	if (fd < 0) {
678 		printf("\tcannot open %s\n", cfname);
679 		return(0);
680 	}
681 	(void) read(fd, line, 1);
682 	(void) lseek(fd, 0L, 0); 	/* set pointer back to top of file */
683 	(void) write(fd, line, 1);
684 	(void) close(fd);
685 	sleep(1);			/* so times will be different */
686 	return(1);
687 }
688 
689 /*
690  * Checks if specified job name is in the printer's queue.
691  * Returns:  negative (-1) if argument name is not in the queue.
692  *     0 to n:  array index of pointer to argument name.
693  */
694 inqueue(job, queue, nitems)
695 	char *job;
696 	struct queue *queue[];
697 	int nitems;
698 {
699 	register struct queue *q;
700 	register int n, jobnum;
701 	register char *cp;
702 	FILE *fp;
703 
704 	jobnum = -1;
705 	if (isdigit(*job)) {
706 		jobnum = 0;
707 		do
708 			jobnum = jobnum * 10 + (*job++ - '0');
709 		while (isdigit(*job));
710 	}
711 
712 	while (--nitems >= 0) {
713 		if ((q = queue[nitems]) == NULL)
714 			continue;
715 		/* this needs to be fixed since the same number can be used
716 		   by different machines (i.e. jobnum & machine) */
717 		if (jobnum >= 0) {
718 			n = 0;
719 			for (cp = q->q_name+3; isdigit(*cp); )
720 				n = n * 10 + (*cp++ - '0');
721 			if (jobnum == n)
722 				return(nitems);
723 			continue;
724 		}
725 		/*
726 		 * Read cf file for owner's name
727 		 */
728 		if ((fp = fopen(q->q_name, "r")) == NULL)
729 			continue;
730 		while (getline(fp) > 0) {
731 			if (line[0] == 'P' && !strcmp(job, line+1)) {
732 				(void) fclose(fp);
733 				return(nitems);
734 			}
735 		}
736 		(void) fclose(fp);
737 	}
738 	return(-1);
739 }
740