xref: /csrg-svn/usr.sbin/lpr/lpc/cmds.c (revision 55472)
122424Sdist /*
222424Sdist  * Copyright (c) 1983 Regents of the University of California.
334203Sbostic  * All rights reserved.
434203Sbostic  *
542801Sbostic  * %sccs.include.redist.c%
622424Sdist  */
722424Sdist 
812382Sralph #ifndef lint
9*55472Sbostic static char sccsid[] = "@(#)cmds.c	5.8 (Berkeley) 07/21/92";
1034203Sbostic #endif /* not lint */
1112382Sralph 
1212382Sralph /*
1315719Sralph  * lpc -- line printer control program -- commands:
1412382Sralph  */
1512382Sralph 
16*55472Sbostic #include <sys/param.h>
17*55472Sbostic #include <sys/time.h>
18*55472Sbostic #include <sys/stat.h>
19*55472Sbostic 
20*55472Sbostic #include <signal.h>
21*55472Sbostic #include <fcntl.h>
22*55472Sbostic #include <errno.h>
23*55472Sbostic #include <dirent.h>
24*55472Sbostic #include <unistd.h>
25*55472Sbostic #include <stdlib.h>
26*55472Sbostic #include <stdio.h>
27*55472Sbostic #include <ctype.h>
28*55472Sbostic #include <string.h>
2912382Sralph #include "lp.h"
30*55472Sbostic #include "lp.local.h"
31*55472Sbostic #include "lpc.h"
32*55472Sbostic #include "extern.h"
3337968Sbostic #include "pathnames.h"
3412382Sralph 
35*55472Sbostic static void	abortpr __P((int));
36*55472Sbostic static void	cleanpr __P((void));
37*55472Sbostic static int	doselect __P((struct dirent *));
38*55472Sbostic static void	upstat __P((char *));
39*55472Sbostic static int	sortq __P((const void *, const void *));
40*55472Sbostic static void	unlinkf __P((char *));
41*55472Sbostic static int	doarg __P((char *));
42*55472Sbostic static int	touch __P((struct queue *));
43*55472Sbostic static void	stoppr __P((void));
44*55472Sbostic static void	prstat __P((void));
45*55472Sbostic static void	startpr __P((int));
46*55472Sbostic static void	putmsg __P((int, char **));
47*55472Sbostic static void	disablepr __P((void));
48*55472Sbostic static void	enablepr __P((void));
49*55472Sbostic 
50*55472Sbostic 
5112382Sralph /*
5212382Sralph  * kill an existing daemon and disable printing.
5312382Sralph  */
54*55472Sbostic void
55*55472Sbostic doabort(argc, argv)
56*55472Sbostic 	int argc;
5712382Sralph 	char *argv[];
5812382Sralph {
5912382Sralph 	register int c, status;
6012382Sralph 	register char *cp1, *cp2;
6112382Sralph 	char prbuf[100];
6212382Sralph 
6312382Sralph 	if (argc == 1) {
6412382Sralph 		printf("Usage: abort {all | printer ...}\n");
6512382Sralph 		return;
6612382Sralph 	}
6712382Sralph 	if (argc == 2 && !strcmp(argv[1], "all")) {
6812382Sralph 		printer = prbuf;
6912382Sralph 		while (getprent(line) > 0) {
7012382Sralph 			cp1 = prbuf;
7112382Sralph 			cp2 = line;
7212382Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
7312382Sralph 				*cp1++ = c;
7412382Sralph 			*cp1 = '\0';
7516755Sralph 			abortpr(1);
7612382Sralph 		}
7712382Sralph 		return;
7812382Sralph 	}
7912382Sralph 	while (--argc) {
8012382Sralph 		printer = *++argv;
8112382Sralph 		if ((status = pgetent(line, printer)) < 0) {
8212514Sralph 			printf("cannot open printer description file\n");
8312382Sralph 			continue;
8412382Sralph 		} else if (status == 0) {
8512514Sralph 			printf("unknown printer %s\n", printer);
8612382Sralph 			continue;
8712382Sralph 		}
8816755Sralph 		abortpr(1);
8912382Sralph 	}
9012382Sralph }
9112382Sralph 
92*55472Sbostic static void
9316755Sralph abortpr(dis)
94*55472Sbostic 	int dis;
9512382Sralph {
9612382Sralph 	register FILE *fp;
9712382Sralph 	struct stat stbuf;
9812382Sralph 	int pid, fd;
9912382Sralph 
10012382Sralph 	bp = pbuf;
10112382Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
10237968Sbostic 		SD = _PATH_DEFSPOOL;
10312382Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
10412382Sralph 		LO = DEFLOCK;
10512382Sralph 	(void) sprintf(line, "%s/%s", SD, LO);
10612382Sralph 	printf("%s:\n", printer);
10712382Sralph 
10812382Sralph 	/*
10912382Sralph 	 * Turn on the owner execute bit of the lock file to disable printing.
11012382Sralph 	 */
11116755Sralph 	if (dis) {
11216755Sralph 		if (stat(line, &stbuf) >= 0) {
11316755Sralph 			if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
11416755Sralph 				printf("\tcannot disable printing\n");
11538735Stef 			else {
11638735Stef 				upstat("printing disabled\n");
11716755Sralph 				printf("\tprinting disabled\n");
11838735Stef 			}
11916755Sralph 		} else if (errno == ENOENT) {
12016755Sralph 			if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
12116755Sralph 				printf("\tcannot create lock file\n");
12216755Sralph 			else {
12316755Sralph 				(void) close(fd);
12438735Stef 				upstat("printing disabled\n");
12516755Sralph 				printf("\tprinting disabled\n");
12616755Sralph 				printf("\tno daemon to abort\n");
12716755Sralph 			}
12816755Sralph 			return;
12916755Sralph 		} else {
13016755Sralph 			printf("\tcannot stat lock file\n");
13116755Sralph 			return;
13212382Sralph 		}
13312382Sralph 	}
13412382Sralph 	/*
13512382Sralph 	 * Kill the current daemon to stop printing now.
13612382Sralph 	 */
13712382Sralph 	if ((fp = fopen(line, "r")) == NULL) {
13812382Sralph 		printf("\tcannot open lock file\n");
13912382Sralph 		return;
14012382Sralph 	}
14113146Ssam 	if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
14213168Sralph 		(void) fclose(fp);	/* unlocks as well */
14312382Sralph 		printf("\tno daemon to abort\n");
14412382Sralph 		return;
14512382Sralph 	}
14612382Sralph 	(void) fclose(fp);
14716755Sralph 	if (kill(pid = atoi(line), SIGTERM) < 0)
14812382Sralph 		printf("\tWarning: daemon (pid %d) not killed\n", pid);
14912382Sralph 	else
15012382Sralph 		printf("\tdaemon (pid %d) killed\n", pid);
15112382Sralph }
15212382Sralph 
15312382Sralph /*
15438735Stef  * Write a message into the status file.
15538735Stef  */
156*55472Sbostic static void
15738735Stef upstat(msg)
15838735Stef 	char *msg;
15938735Stef {
16038735Stef 	register int fd;
16138735Stef 	char statfile[BUFSIZ];
16238735Stef 
16338735Stef 	bp = pbuf;
16438735Stef 	if ((ST = pgetstr("st", &bp)) == NULL)
16538735Stef 		ST = DEFSTAT;
16638735Stef 	(void) sprintf(statfile, "%s/%s", SD, ST);
16738735Stef 	umask(0);
16838735Stef 	fd = open(statfile, O_WRONLY|O_CREAT, 0664);
16938735Stef 	if (fd < 0 || flock(fd, LOCK_EX) < 0) {
17038735Stef 		printf("\tcannot create status file\n");
17138735Stef 		return;
17238735Stef 	}
17338735Stef 	(void) ftruncate(fd, 0);
17438735Stef 	if (msg == (char *)NULL)
17538735Stef 		(void) write(fd, "\n", 1);
17638735Stef 	else
17738735Stef 		(void) write(fd, msg, strlen(msg));
17838735Stef 	(void) close(fd);
17938735Stef }
18038735Stef 
18138735Stef /*
18212382Sralph  * Remove all spool files and temporaries from the spooling area.
18312382Sralph  */
184*55472Sbostic void
18512382Sralph clean(argc, argv)
186*55472Sbostic 	int argc;
18712382Sralph 	char *argv[];
18812382Sralph {
18912382Sralph 	register int c, status;
19012382Sralph 	register char *cp1, *cp2;
19112382Sralph 	char prbuf[100];
19212382Sralph 
19312382Sralph 	if (argc == 1) {
19412382Sralph 		printf("Usage: clean {all | printer ...}\n");
19512382Sralph 		return;
19612382Sralph 	}
19712382Sralph 	if (argc == 2 && !strcmp(argv[1], "all")) {
19812382Sralph 		printer = prbuf;
19912382Sralph 		while (getprent(line) > 0) {
20012382Sralph 			cp1 = prbuf;
20112382Sralph 			cp2 = line;
20212382Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
20312382Sralph 				*cp1++ = c;
20412382Sralph 			*cp1 = '\0';
20512382Sralph 			cleanpr();
20612382Sralph 		}
20712382Sralph 		return;
20812382Sralph 	}
20912382Sralph 	while (--argc) {
21012382Sralph 		printer = *++argv;
21112382Sralph 		if ((status = pgetent(line, printer)) < 0) {
21212514Sralph 			printf("cannot open printer description file\n");
21312382Sralph 			continue;
21412382Sralph 		} else if (status == 0) {
21512514Sralph 			printf("unknown printer %s\n", printer);
21612382Sralph 			continue;
21712382Sralph 		}
21812382Sralph 		cleanpr();
21912382Sralph 	}
22012382Sralph }
22112382Sralph 
222*55472Sbostic static int
223*55472Sbostic doselect(d)
224*55472Sbostic 	struct dirent *d;
22515719Sralph {
22615719Sralph 	int c = d->d_name[0];
22715719Sralph 
22815719Sralph 	if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f')
22915719Sralph 		return(1);
23015719Sralph 	return(0);
23115719Sralph }
23215719Sralph 
23315719Sralph /*
23415719Sralph  * Comparison routine for scandir. Sort by job number and machine, then
23515719Sralph  * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z.
23615719Sralph  */
237*55472Sbostic static int
238*55472Sbostic sortq(a, b)
239*55472Sbostic 	const void *a, *b;
24015719Sralph {
241*55472Sbostic 	struct dirent **d1, **d2;
24215719Sralph 	int c1, c2;
24315719Sralph 
244*55472Sbostic 	d1 = (struct dirent **)a;
245*55472Sbostic 	d2 = (struct dirent **)b;
24615719Sralph 	if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))
24715719Sralph 		return(c1);
24815719Sralph 	c1 = (*d1)->d_name[0];
24915719Sralph 	c2 = (*d2)->d_name[0];
25015719Sralph 	if (c1 == c2)
25115719Sralph 		return((*d1)->d_name[2] - (*d2)->d_name[2]);
25215719Sralph 	if (c1 == 'c')
25315719Sralph 		return(-1);
25415719Sralph 	if (c1 == 'd' || c2 == 'c')
25515719Sralph 		return(1);
25615719Sralph 	return(-1);
25715719Sralph }
25815719Sralph 
25915719Sralph /*
26015719Sralph  * Remove incomplete jobs from spooling area.
26115719Sralph  */
262*55472Sbostic static void
26312382Sralph cleanpr()
26412382Sralph {
26515719Sralph 	register int i, n;
26615719Sralph 	register char *cp, *cp1, *lp;
267*55472Sbostic 	struct dirent **queue;
26815719Sralph 	int nitems;
26912382Sralph 
27012382Sralph 	bp = pbuf;
27112382Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
27237968Sbostic 		SD = _PATH_DEFSPOOL;
27312382Sralph 	printf("%s:\n", printer);
27412382Sralph 
27515719Sralph 	for (lp = line, cp = SD; *lp++ = *cp++; )
27615719Sralph 		;
27715719Sralph 	lp[-1] = '/';
27815719Sralph 
279*55472Sbostic 	nitems = scandir(SD, &queue, doselect, sortq);
28015719Sralph 	if (nitems < 0) {
28112382Sralph 		printf("\tcannot examine spool directory\n");
28212382Sralph 		return;
28312382Sralph 	}
28415719Sralph 	if (nitems == 0)
28515719Sralph 		return;
28615719Sralph 	i = 0;
28715719Sralph 	do {
28815719Sralph 		cp = queue[i]->d_name;
28915719Sralph 		if (*cp == 'c') {
29015719Sralph 			n = 0;
29115719Sralph 			while (i + 1 < nitems) {
29215719Sralph 				cp1 = queue[i + 1]->d_name;
29315719Sralph 				if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3))
29415719Sralph 					break;
29515719Sralph 				i++;
29615719Sralph 				n++;
29715719Sralph 			}
29815719Sralph 			if (n == 0) {
29915719Sralph 				strcpy(lp, cp);
30015719Sralph 				unlinkf(line);
30115719Sralph 			}
30215719Sralph 		} else {
30315719Sralph 			/*
30415719Sralph 			 * Must be a df with no cf (otherwise, it would have
30515719Sralph 			 * been skipped above) or a tf file (which can always
30615719Sralph 			 * be removed).
30715719Sralph 			 */
30815719Sralph 			strcpy(lp, cp);
30915719Sralph 			unlinkf(line);
31012382Sralph 		}
31115719Sralph      	} while (++i < nitems);
31212382Sralph }
31315719Sralph 
314*55472Sbostic static void
31515719Sralph unlinkf(name)
31615719Sralph 	char	*name;
31715719Sralph {
31815719Sralph 	if (unlink(name) < 0)
31915719Sralph 		printf("\tcannot remove %s\n", name);
32015719Sralph 	else
32115719Sralph 		printf("\tremoved %s\n", name);
32215719Sralph }
32312382Sralph 
32412382Sralph /*
32512382Sralph  * Enable queuing to the printer (allow lpr's).
32612382Sralph  */
327*55472Sbostic void
32812382Sralph enable(argc, argv)
329*55472Sbostic 	int argc;
33012382Sralph 	char *argv[];
33112382Sralph {
33212382Sralph 	register int c, status;
33312382Sralph 	register char *cp1, *cp2;
33412382Sralph 	char prbuf[100];
33512382Sralph 
33612382Sralph 	if (argc == 1) {
33712382Sralph 		printf("Usage: enable {all | printer ...}\n");
33812382Sralph 		return;
33912382Sralph 	}
34012382Sralph 	if (argc == 2 && !strcmp(argv[1], "all")) {
34112382Sralph 		printer = prbuf;
34212382Sralph 		while (getprent(line) > 0) {
34312382Sralph 			cp1 = prbuf;
34412382Sralph 			cp2 = line;
34512382Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
34612382Sralph 				*cp1++ = c;
34712382Sralph 			*cp1 = '\0';
34812382Sralph 			enablepr();
34912382Sralph 		}
35012382Sralph 		return;
35112382Sralph 	}
35212382Sralph 	while (--argc) {
35312382Sralph 		printer = *++argv;
35412382Sralph 		if ((status = pgetent(line, printer)) < 0) {
35512514Sralph 			printf("cannot open printer description file\n");
35612382Sralph 			continue;
35712382Sralph 		} else if (status == 0) {
35812514Sralph 			printf("unknown printer %s\n", printer);
35912382Sralph 			continue;
36012382Sralph 		}
36112382Sralph 		enablepr();
36212382Sralph 	}
36312382Sralph }
36412382Sralph 
365*55472Sbostic static void
36612382Sralph enablepr()
36712382Sralph {
36812382Sralph 	struct stat stbuf;
36912382Sralph 
37012382Sralph 	bp = pbuf;
37112382Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
37237968Sbostic 		SD = _PATH_DEFSPOOL;
37312382Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
37412382Sralph 		LO = DEFLOCK;
37512382Sralph 	(void) sprintf(line, "%s/%s", SD, LO);
37612382Sralph 	printf("%s:\n", printer);
37712382Sralph 
37812382Sralph 	/*
37912382Sralph 	 * Turn off the group execute bit of the lock file to enable queuing.
38012382Sralph 	 */
38112382Sralph 	if (stat(line, &stbuf) >= 0) {
38212382Sralph 		if (chmod(line, stbuf.st_mode & 0767) < 0)
38312514Sralph 			printf("\tcannot enable queuing\n");
38412382Sralph 		else
38512382Sralph 			printf("\tqueuing enabled\n");
38612382Sralph 	}
38712382Sralph }
38812382Sralph 
38912382Sralph /*
39012382Sralph  * Disable queuing.
39112382Sralph  */
392*55472Sbostic void
39312382Sralph disable(argc, argv)
394*55472Sbostic 	int argc;
39512382Sralph 	char *argv[];
39612382Sralph {
39712382Sralph 	register int c, status;
39812382Sralph 	register char *cp1, *cp2;
39912382Sralph 	char prbuf[100];
40012382Sralph 
40112382Sralph 	if (argc == 1) {
40212382Sralph 		printf("Usage: disable {all | printer ...}\n");
40312382Sralph 		return;
40412382Sralph 	}
40512382Sralph 	if (argc == 2 && !strcmp(argv[1], "all")) {
40612382Sralph 		printer = prbuf;
40712382Sralph 		while (getprent(line) > 0) {
40812382Sralph 			cp1 = prbuf;
40912382Sralph 			cp2 = line;
41012382Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
41112382Sralph 				*cp1++ = c;
41212382Sralph 			*cp1 = '\0';
41312382Sralph 			disablepr();
41412382Sralph 		}
41512382Sralph 		return;
41612382Sralph 	}
41712382Sralph 	while (--argc) {
41812382Sralph 		printer = *++argv;
41912382Sralph 		if ((status = pgetent(line, printer)) < 0) {
42012514Sralph 			printf("cannot open printer description file\n");
42112382Sralph 			continue;
42212382Sralph 		} else if (status == 0) {
42312514Sralph 			printf("unknown printer %s\n", printer);
42412382Sralph 			continue;
42512382Sralph 		}
42612382Sralph 		disablepr();
42712382Sralph 	}
42812382Sralph }
42912382Sralph 
430*55472Sbostic static void
43112382Sralph disablepr()
43212382Sralph {
43312382Sralph 	register int fd;
43412382Sralph 	struct stat stbuf;
43512382Sralph 
43612382Sralph 	bp = pbuf;
43712382Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
43837968Sbostic 		SD = _PATH_DEFSPOOL;
43912382Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
44012382Sralph 		LO = DEFLOCK;
44112382Sralph 	(void) sprintf(line, "%s/%s", SD, LO);
44212382Sralph 	printf("%s:\n", printer);
44312382Sralph 	/*
44412382Sralph 	 * Turn on the group execute bit of the lock file to disable queuing.
44512382Sralph 	 */
44612382Sralph 	if (stat(line, &stbuf) >= 0) {
44712382Sralph 		if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
44812382Sralph 			printf("\tcannot disable queuing\n");
44912382Sralph 		else
45012382Sralph 			printf("\tqueuing disabled\n");
45112382Sralph 	} else if (errno == ENOENT) {
45213146Ssam 		if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
45312382Sralph 			printf("\tcannot create lock file\n");
45412382Sralph 		else {
45512382Sralph 			(void) close(fd);
45612382Sralph 			printf("\tqueuing disabled\n");
45712382Sralph 		}
45812382Sralph 		return;
45912382Sralph 	} else
46012382Sralph 		printf("\tcannot stat lock file\n");
46112382Sralph }
46212382Sralph 
46312382Sralph /*
46415907Sralph  * Disable queuing and printing and put a message into the status file
46515907Sralph  * (reason for being down).
46615907Sralph  */
467*55472Sbostic void
46815907Sralph down(argc, argv)
469*55472Sbostic 	int argc;
47015907Sralph 	char *argv[];
47115907Sralph {
47215907Sralph 	register int c, status;
47315907Sralph 	register char *cp1, *cp2;
47415907Sralph 	char prbuf[100];
47515907Sralph 
47615907Sralph 	if (argc == 1) {
47716204Sralph 		printf("Usage: down {all | printer} [message ...]\n");
47815907Sralph 		return;
47915907Sralph 	}
48015907Sralph 	if (!strcmp(argv[1], "all")) {
48115907Sralph 		printer = prbuf;
48215907Sralph 		while (getprent(line) > 0) {
48315907Sralph 			cp1 = prbuf;
48415907Sralph 			cp2 = line;
48515907Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
48615907Sralph 				*cp1++ = c;
48715907Sralph 			*cp1 = '\0';
48815907Sralph 			putmsg(argc - 2, argv + 2);
48915907Sralph 		}
49015907Sralph 		return;
49115907Sralph 	}
49215907Sralph 	printer = argv[1];
49315907Sralph 	if ((status = pgetent(line, printer)) < 0) {
49415907Sralph 		printf("cannot open printer description file\n");
49515907Sralph 		return;
49615907Sralph 	} else if (status == 0) {
49715907Sralph 		printf("unknown printer %s\n", printer);
49815907Sralph 		return;
49915907Sralph 	}
50015907Sralph 	putmsg(argc - 2, argv + 2);
50115907Sralph }
50215907Sralph 
503*55472Sbostic static void
50415907Sralph putmsg(argc, argv)
505*55472Sbostic 	int argc;
50615907Sralph 	char **argv;
50715907Sralph {
50815907Sralph 	register int fd;
50915907Sralph 	register char *cp1, *cp2;
51015907Sralph 	char buf[1024];
51115907Sralph 	struct stat stbuf;
51215907Sralph 
51315907Sralph 	bp = pbuf;
51415907Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
51537968Sbostic 		SD = _PATH_DEFSPOOL;
51615907Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
51715907Sralph 		LO = DEFLOCK;
51815907Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
51915907Sralph 		ST = DEFSTAT;
52015907Sralph 	printf("%s:\n", printer);
52115907Sralph 	/*
52215907Sralph 	 * Turn on the group execute bit of the lock file to disable queuing and
52315907Sralph 	 * turn on the owner execute bit of the lock file to disable printing.
52415907Sralph 	 */
52515907Sralph 	(void) sprintf(line, "%s/%s", SD, LO);
52615907Sralph 	if (stat(line, &stbuf) >= 0) {
52715907Sralph 		if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
52815907Sralph 			printf("\tcannot disable queuing\n");
52915907Sralph 		else
53015907Sralph 			printf("\tprinter and queuing disabled\n");
53115907Sralph 	} else if (errno == ENOENT) {
53215907Sralph 		if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0)
53315907Sralph 			printf("\tcannot create lock file\n");
53415907Sralph 		else {
53515907Sralph 			(void) close(fd);
53615907Sralph 			printf("\tprinter and queuing disabled\n");
53715907Sralph 		}
53815907Sralph 		return;
53915907Sralph 	} else
54015907Sralph 		printf("\tcannot stat lock file\n");
54115907Sralph 	/*
54215907Sralph 	 * Write the message into the status file.
54315907Sralph 	 */
54415907Sralph 	(void) sprintf(line, "%s/%s", SD, ST);
54515907Sralph 	fd = open(line, O_WRONLY|O_CREAT, 0664);
54615907Sralph 	if (fd < 0 || flock(fd, LOCK_EX) < 0) {
54715907Sralph 		printf("\tcannot create status file\n");
54815907Sralph 		return;
54915907Sralph 	}
55015907Sralph 	(void) ftruncate(fd, 0);
55116204Sralph 	if (argc <= 0) {
55216204Sralph 		(void) write(fd, "\n", 1);
55316204Sralph 		(void) close(fd);
55416204Sralph 		return;
55516204Sralph 	}
55615907Sralph 	cp1 = buf;
55715907Sralph 	while (--argc >= 0) {
55815907Sralph 		cp2 = *argv++;
55915907Sralph 		while (*cp1++ = *cp2++)
56015907Sralph 			;
56115907Sralph 		cp1[-1] = ' ';
56215907Sralph 	}
56315907Sralph 	cp1[-1] = '\n';
56415907Sralph 	*cp1 = '\0';
56515907Sralph 	(void) write(fd, buf, strlen(buf));
56615907Sralph 	(void) close(fd);
56715907Sralph }
56815907Sralph 
56915907Sralph /*
57012382Sralph  * Exit lpc
57112382Sralph  */
572*55472Sbostic void
57312382Sralph quit(argc, argv)
574*55472Sbostic 	int argc;
57512382Sralph 	char *argv[];
57612382Sralph {
57712382Sralph 	exit(0);
57812382Sralph }
57912382Sralph 
58012382Sralph /*
58116755Sralph  * Kill and restart the daemon.
58212382Sralph  */
583*55472Sbostic void
58412382Sralph restart(argc, argv)
585*55472Sbostic 	int argc;
58612382Sralph 	char *argv[];
58712382Sralph {
58812382Sralph 	register int c, status;
58912382Sralph 	register char *cp1, *cp2;
59012382Sralph 	char prbuf[100];
59112382Sralph 
59212382Sralph 	if (argc == 1) {
59312382Sralph 		printf("Usage: restart {all | printer ...}\n");
59412382Sralph 		return;
59512382Sralph 	}
59612382Sralph 	if (argc == 2 && !strcmp(argv[1], "all")) {
59712382Sralph 		printer = prbuf;
59812382Sralph 		while (getprent(line) > 0) {
59912382Sralph 			cp1 = prbuf;
60012382Sralph 			cp2 = line;
60112382Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
60212382Sralph 				*cp1++ = c;
60312382Sralph 			*cp1 = '\0';
60416755Sralph 			abortpr(0);
60512382Sralph 			startpr(0);
60612382Sralph 		}
60712382Sralph 		return;
60812382Sralph 	}
60912382Sralph 	while (--argc) {
61012382Sralph 		printer = *++argv;
61112382Sralph 		if ((status = pgetent(line, printer)) < 0) {
61212514Sralph 			printf("cannot open printer description file\n");
61312382Sralph 			continue;
61412382Sralph 		} else if (status == 0) {
61512514Sralph 			printf("unknown printer %s\n", printer);
61612382Sralph 			continue;
61712382Sralph 		}
61816755Sralph 		abortpr(0);
61912382Sralph 		startpr(0);
62012382Sralph 	}
62112382Sralph }
62212382Sralph 
62312382Sralph /*
62412382Sralph  * Enable printing on the specified printer and startup the daemon.
62512382Sralph  */
626*55472Sbostic void
62712382Sralph start(argc, argv)
628*55472Sbostic 	int argc;
62912382Sralph 	char *argv[];
63012382Sralph {
63112382Sralph 	register int c, status;
63212382Sralph 	register char *cp1, *cp2;
63312382Sralph 	char prbuf[100];
63412382Sralph 
63512382Sralph 	if (argc == 1) {
63612382Sralph 		printf("Usage: start {all | printer ...}\n");
63712382Sralph 		return;
63812382Sralph 	}
63912382Sralph 	if (argc == 2 && !strcmp(argv[1], "all")) {
64012382Sralph 		printer = prbuf;
64112382Sralph 		while (getprent(line) > 0) {
64212382Sralph 			cp1 = prbuf;
64312382Sralph 			cp2 = line;
64412382Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
64512382Sralph 				*cp1++ = c;
64612382Sralph 			*cp1 = '\0';
64712382Sralph 			startpr(1);
64812382Sralph 		}
64912382Sralph 		return;
65012382Sralph 	}
65112382Sralph 	while (--argc) {
65212382Sralph 		printer = *++argv;
65312382Sralph 		if ((status = pgetent(line, printer)) < 0) {
65412514Sralph 			printf("cannot open printer description file\n");
65512382Sralph 			continue;
65612382Sralph 		} else if (status == 0) {
65712514Sralph 			printf("unknown printer %s\n", printer);
65812382Sralph 			continue;
65912382Sralph 		}
66012382Sralph 		startpr(1);
66112382Sralph 	}
66212382Sralph }
66312382Sralph 
664*55472Sbostic static void
66512382Sralph startpr(enable)
666*55472Sbostic 	int enable;
66712382Sralph {
66812382Sralph 	struct stat stbuf;
66912382Sralph 
67012382Sralph 	bp = pbuf;
67112382Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
67237968Sbostic 		SD = _PATH_DEFSPOOL;
67312382Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
67412382Sralph 		LO = DEFLOCK;
67512382Sralph 	(void) sprintf(line, "%s/%s", SD, LO);
67612382Sralph 	printf("%s:\n", printer);
67712382Sralph 
67812382Sralph 	/*
67912382Sralph 	 * Turn off the owner execute bit of the lock file to enable printing.
68012382Sralph 	 */
68112382Sralph 	if (enable && stat(line, &stbuf) >= 0) {
68216771Sralph 		if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0)
68312382Sralph 			printf("\tcannot enable printing\n");
68412382Sralph 		else
68512382Sralph 			printf("\tprinting enabled\n");
68612382Sralph 	}
68713727Sroot 	if (!startdaemon(printer))
68812382Sralph 		printf("\tcouldn't start daemon\n");
68912382Sralph 	else
69012382Sralph 		printf("\tdaemon started\n");
69112382Sralph }
69212382Sralph 
69312382Sralph /*
69412382Sralph  * Print the status of each queue listed or all the queues.
69512382Sralph  */
696*55472Sbostic void
69712382Sralph status(argc, argv)
698*55472Sbostic 	int argc;
69912382Sralph 	char *argv[];
70012382Sralph {
70112382Sralph 	register int c, status;
70212382Sralph 	register char *cp1, *cp2;
70312382Sralph 	char prbuf[100];
70412382Sralph 
70512382Sralph 	if (argc == 1) {
70612382Sralph 		printer = prbuf;
70712382Sralph 		while (getprent(line) > 0) {
70812382Sralph 			cp1 = prbuf;
70912382Sralph 			cp2 = line;
71012382Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
71112382Sralph 				*cp1++ = c;
71212382Sralph 			*cp1 = '\0';
71312382Sralph 			prstat();
71412382Sralph 		}
71512382Sralph 		return;
71612382Sralph 	}
71712382Sralph 	while (--argc) {
71812382Sralph 		printer = *++argv;
71912382Sralph 		if ((status = pgetent(line, printer)) < 0) {
72012514Sralph 			printf("cannot open printer description file\n");
72112382Sralph 			continue;
72212382Sralph 		} else if (status == 0) {
72312514Sralph 			printf("unknown printer %s\n", printer);
72412382Sralph 			continue;
72512382Sralph 		}
72612382Sralph 		prstat();
72712382Sralph 	}
72812382Sralph }
72912382Sralph 
73012382Sralph /*
73112382Sralph  * Print the status of the printer queue.
73212382Sralph  */
733*55472Sbostic static void
73412382Sralph prstat()
73512382Sralph {
73612382Sralph 	struct stat stbuf;
73712382Sralph 	register int fd, i;
738*55472Sbostic 	register struct dirent *dp;
73912382Sralph 	DIR *dirp;
74012382Sralph 
74112382Sralph 	bp = pbuf;
74212382Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
74337968Sbostic 		SD = _PATH_DEFSPOOL;
74412382Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
74512382Sralph 		LO = DEFLOCK;
74612382Sralph 	if ((ST = pgetstr("st", &bp)) == NULL)
74712382Sralph 		ST = DEFSTAT;
74812382Sralph 	printf("%s:\n", printer);
74912382Sralph 	(void) sprintf(line, "%s/%s", SD, LO);
75012382Sralph 	if (stat(line, &stbuf) >= 0) {
75112382Sralph 		printf("\tqueuing is %s\n",
75212382Sralph 			(stbuf.st_mode & 010) ? "disabled" : "enabled");
75312382Sralph 		printf("\tprinting is %s\n",
75412382Sralph 			(stbuf.st_mode & 0100) ? "disabled" : "enabled");
75512382Sralph 	} else {
75612382Sralph 		printf("\tqueuing is enabled\n");
75712382Sralph 		printf("\tprinting is enabled\n");
75812382Sralph 	}
75912382Sralph 	if ((dirp = opendir(SD)) == NULL) {
76012382Sralph 		printf("\tcannot examine spool directory\n");
76112382Sralph 		return;
76212382Sralph 	}
76312382Sralph 	i = 0;
76412382Sralph 	while ((dp = readdir(dirp)) != NULL) {
76512382Sralph 		if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
76612382Sralph 			i++;
76712382Sralph 	}
76812382Sralph 	closedir(dirp);
76912382Sralph 	if (i == 0)
77012382Sralph 		printf("\tno entries\n");
77112382Sralph 	else if (i == 1)
77212382Sralph 		printf("\t1 entry in spool area\n");
77312382Sralph 	else
77412382Sralph 		printf("\t%d entries in spool area\n", i);
77513146Ssam 	fd = open(line, O_RDONLY);
77613146Ssam 	if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
77713168Sralph 		(void) close(fd);	/* unlocks as well */
77812382Sralph 		printf("\tno daemon present\n");
77912382Sralph 		return;
78012382Sralph 	}
78112382Sralph 	(void) close(fd);
78212382Sralph 	putchar('\t');
78312382Sralph 	(void) sprintf(line, "%s/%s", SD, ST);
78413146Ssam 	fd = open(line, O_RDONLY);
78513146Ssam 	if (fd >= 0) {
78613146Ssam 		(void) flock(fd, LOCK_SH);
78712382Sralph 		while ((i = read(fd, line, sizeof(line))) > 0)
78812382Sralph 			(void) fwrite(line, 1, i, stdout);
78913168Sralph 		(void) close(fd);	/* unlocks as well */
79012382Sralph 	}
79112382Sralph }
79212382Sralph 
79312382Sralph /*
79412382Sralph  * Stop the specified daemon after completing the current job and disable
79512382Sralph  * printing.
79612382Sralph  */
797*55472Sbostic void
79812382Sralph stop(argc, argv)
799*55472Sbostic 	int argc;
80012382Sralph 	char *argv[];
80112382Sralph {
80212382Sralph 	register int c, status;
80312382Sralph 	register char *cp1, *cp2;
80412382Sralph 	char prbuf[100];
80512382Sralph 
80612382Sralph 	if (argc == 1) {
80712382Sralph 		printf("Usage: stop {all | printer ...}\n");
80812382Sralph 		return;
80912382Sralph 	}
81012382Sralph 	if (argc == 2 && !strcmp(argv[1], "all")) {
81112382Sralph 		printer = prbuf;
81212382Sralph 		while (getprent(line) > 0) {
81312382Sralph 			cp1 = prbuf;
81412382Sralph 			cp2 = line;
81512382Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
81612382Sralph 				*cp1++ = c;
81712382Sralph 			*cp1 = '\0';
81812382Sralph 			stoppr();
81912382Sralph 		}
82012382Sralph 		return;
82112382Sralph 	}
82212382Sralph 	while (--argc) {
82312382Sralph 		printer = *++argv;
82412382Sralph 		if ((status = pgetent(line, printer)) < 0) {
82512514Sralph 			printf("cannot open printer description file\n");
82612382Sralph 			continue;
82712382Sralph 		} else if (status == 0) {
82812514Sralph 			printf("unknown printer %s\n", printer);
82912382Sralph 			continue;
83012382Sralph 		}
83112382Sralph 		stoppr();
83212382Sralph 	}
83312382Sralph }
83412382Sralph 
835*55472Sbostic static void
83612382Sralph stoppr()
83712382Sralph {
83812382Sralph 	register int fd;
83912382Sralph 	struct stat stbuf;
84012382Sralph 
84112382Sralph 	bp = pbuf;
84212382Sralph 	if ((SD = pgetstr("sd", &bp)) == NULL)
84337968Sbostic 		SD = _PATH_DEFSPOOL;
84412382Sralph 	if ((LO = pgetstr("lo", &bp)) == NULL)
84512382Sralph 		LO = DEFLOCK;
84612382Sralph 	(void) sprintf(line, "%s/%s", SD, LO);
84712382Sralph 	printf("%s:\n", printer);
84812382Sralph 
84912382Sralph 	/*
85012382Sralph 	 * Turn on the owner execute bit of the lock file to disable printing.
85112382Sralph 	 */
85212382Sralph 	if (stat(line, &stbuf) >= 0) {
85312382Sralph 		if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
85412382Sralph 			printf("\tcannot disable printing\n");
85538735Stef 		else {
85638735Stef 			upstat("printing disabled\n");
85712382Sralph 			printf("\tprinting disabled\n");
85838735Stef 		}
85912382Sralph 	} else if (errno == ENOENT) {
86013146Ssam 		if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
86112382Sralph 			printf("\tcannot create lock file\n");
86212382Sralph 		else {
86312382Sralph 			(void) close(fd);
86438735Stef 			upstat("printing disabled\n");
86512382Sralph 			printf("\tprinting disabled\n");
86612382Sralph 		}
86712382Sralph 	} else
86812382Sralph 		printf("\tcannot stat lock file\n");
86912382Sralph }
87013727Sroot 
87115719Sralph struct	queue **queue;
87215719Sralph int	nitems;
87315719Sralph time_t	mtime;
87415719Sralph 
87513727Sroot /*
87613727Sroot  * Put the specified jobs at the top of printer queue.
87713727Sroot  */
878*55472Sbostic void
87913727Sroot topq(argc, argv)
880*55472Sbostic 	int argc;
88113727Sroot 	char *argv[];
88213727Sroot {
883*55472Sbostic 	register int i;
88413727Sroot 	struct stat stbuf;
88515719Sralph 	int status, changed;
88613727Sroot 
88715719Sralph 	if (argc < 3) {
88813727Sroot 		printf("Usage: topq printer [jobnum ...] [user ...]\n");
88913727Sroot 		return;
89013727Sroot 	}
89113727Sroot 
89213727Sroot 	--argc;
89313727Sroot 	printer = *++argv;
89413727Sroot 	status = pgetent(line, printer);
89513727Sroot 	if (status < 0) {
89613727Sroot 		printf("cannot open printer description file\n");
89713727Sroot 		return;
89814151Sralph 	} else if (status == 0) {
89913727Sroot 		printf("%s: unknown printer\n", printer);
90013727Sroot 		return;
90113727Sroot 	}
90213727Sroot 	bp = pbuf;
90313727Sroot 	if ((SD = pgetstr("sd", &bp)) == NULL)
90437968Sbostic 		SD = _PATH_DEFSPOOL;
90513727Sroot 	if ((LO = pgetstr("lo", &bp)) == NULL)
90613727Sroot 		LO = DEFLOCK;
90713727Sroot 	printf("%s:\n", printer);
90813727Sroot 
90913727Sroot 	if (chdir(SD) < 0) {
91013727Sroot 		printf("\tcannot chdir to %s\n", SD);
91113727Sroot 		return;
91213727Sroot 	}
91313727Sroot 	nitems = getq(&queue);
91415719Sralph 	if (nitems == 0)
91515719Sralph 		return;
91615719Sralph 	changed = 0;
91715719Sralph 	mtime = queue[0]->q_time;
91815719Sralph 	for (i = argc; --i; ) {
91915719Sralph 		if (doarg(argv[i]) == 0) {
92015719Sralph 			printf("\tjob %s is not in the queue\n", argv[i]);
92113727Sroot 			continue;
92215719Sralph 		} else
92314151Sralph 			changed++;
92413727Sroot 	}
92515719Sralph 	for (i = 0; i < nitems; i++)
92615719Sralph 		free(queue[i]);
92715719Sralph 	free(queue);
92815719Sralph 	if (!changed) {
92915719Sralph 		printf("\tqueue order unchanged\n");
93015719Sralph 		return;
93113727Sroot 	}
93213727Sroot 	/*
93313727Sroot 	 * Turn on the public execute bit of the lock file to
93413727Sroot 	 * get lpd to rebuild the queue after the current job.
93513727Sroot 	 */
93614151Sralph 	if (changed && stat(LO, &stbuf) >= 0)
93714151Sralph 		(void) chmod(LO, (stbuf.st_mode & 0777) | 01);
93813727Sroot }
93913727Sroot 
94015719Sralph /*
94115719Sralph  * Reposition the job by changing the modification time of
94215719Sralph  * the control file.
94313727Sroot  */
944*55472Sbostic static int
94515719Sralph touch(q)
94615719Sralph 	struct queue *q;
94713727Sroot {
94815719Sralph 	struct timeval tvp[2];
94913727Sroot 
95015719Sralph 	tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
95115719Sralph 	tvp[0].tv_usec = tvp[1].tv_usec = 0;
95215719Sralph 	return(utimes(q->q_name, tvp));
95313727Sroot }
95413727Sroot 
95513727Sroot /*
95613727Sroot  * Checks if specified job name is in the printer's queue.
95713727Sroot  * Returns:  negative (-1) if argument name is not in the queue.
95813727Sroot  */
959*55472Sbostic static int
96015719Sralph doarg(job)
96113727Sroot 	char *job;
96213727Sroot {
96315719Sralph 	register struct queue **qq;
96415719Sralph 	register int jobnum, n;
96515719Sralph 	register char *cp, *machine;
96615719Sralph 	int cnt = 0;
96714151Sralph 	FILE *fp;
96813727Sroot 
96915719Sralph 	/*
97015719Sralph 	 * Look for a job item consisting of system name, colon, number
97115719Sralph 	 * (example: ucbarpa:114)
97215719Sralph 	 */
97315719Sralph 	if ((cp = index(job, ':')) != NULL) {
97415719Sralph 		machine = job;
97515719Sralph 		*cp++ = '\0';
97615719Sralph 		job = cp;
97715719Sralph 	} else
97815719Sralph 		machine = NULL;
97915719Sralph 
98015719Sralph 	/*
98115719Sralph 	 * Check for job specified by number (example: 112 or 235ucbarpa).
98215719Sralph 	 */
98313727Sroot 	if (isdigit(*job)) {
98413727Sroot 		jobnum = 0;
98513727Sroot 		do
98613727Sroot 			jobnum = jobnum * 10 + (*job++ - '0');
98713727Sroot 		while (isdigit(*job));
98815719Sralph 		for (qq = queue + nitems; --qq >= queue; ) {
98913727Sroot 			n = 0;
99015719Sralph 			for (cp = (*qq)->q_name+3; isdigit(*cp); )
99114151Sralph 				n = n * 10 + (*cp++ - '0');
99215719Sralph 			if (jobnum != n)
99315719Sralph 				continue;
99415719Sralph 			if (*job && strcmp(job, cp) != 0)
99515719Sralph 				continue;
99615719Sralph 			if (machine != NULL && strcmp(machine, cp) != 0)
99715719Sralph 				continue;
99815719Sralph 			if (touch(*qq) == 0) {
99915719Sralph 				printf("\tmoved %s\n", (*qq)->q_name);
100015719Sralph 				cnt++;
100115719Sralph 			}
100213727Sroot 		}
100315719Sralph 		return(cnt);
100415719Sralph 	}
100515719Sralph 	/*
100615719Sralph 	 * Process item consisting of owner's name (example: henry).
100715719Sralph 	 */
100815719Sralph 	for (qq = queue + nitems; --qq >= queue; ) {
100915719Sralph 		if ((fp = fopen((*qq)->q_name, "r")) == NULL)
101013727Sroot 			continue;
101115719Sralph 		while (getline(fp) > 0)
101215719Sralph 			if (line[0] == 'P')
101315719Sralph 				break;
101415719Sralph 		(void) fclose(fp);
101515719Sralph 		if (line[0] != 'P' || strcmp(job, line+1) != 0)
101615719Sralph 			continue;
101715719Sralph 		if (touch(*qq) == 0) {
101815719Sralph 			printf("\tmoved %s\n", (*qq)->q_name);
101915719Sralph 			cnt++;
102013727Sroot 		}
102113727Sroot 	}
102215719Sralph 	return(cnt);
102313727Sroot }
102416755Sralph 
102516755Sralph /*
102616755Sralph  * Enable everything and start printer (undo `down').
102716755Sralph  */
1028*55472Sbostic void
102916755Sralph up(argc, argv)
1030*55472Sbostic 	int argc;
103116755Sralph 	char *argv[];
103216755Sralph {
103316755Sralph 	register int c, status;
103416755Sralph 	register char *cp1, *cp2;
103516755Sralph 	char prbuf[100];
103616755Sralph 
103716755Sralph 	if (argc == 1) {
103816755Sralph 		printf("Usage: up {all | printer ...}\n");
103916755Sralph 		return;
104016755Sralph 	}
104116755Sralph 	if (argc == 2 && !strcmp(argv[1], "all")) {
104216755Sralph 		printer = prbuf;
104316755Sralph 		while (getprent(line) > 0) {
104416755Sralph 			cp1 = prbuf;
104516755Sralph 			cp2 = line;
104616755Sralph 			while ((c = *cp2++) && c != '|' && c != ':')
104716755Sralph 				*cp1++ = c;
104816755Sralph 			*cp1 = '\0';
104916755Sralph 			startpr(2);
105016755Sralph 		}
105116755Sralph 		return;
105216755Sralph 	}
105316755Sralph 	while (--argc) {
105416755Sralph 		printer = *++argv;
105516755Sralph 		if ((status = pgetent(line, printer)) < 0) {
105616755Sralph 			printf("cannot open printer description file\n");
105716755Sralph 			continue;
105816755Sralph 		} else if (status == 0) {
105916755Sralph 			printf("unknown printer %s\n", printer);
106016755Sralph 			continue;
106116755Sralph 		}
106216755Sralph 		startpr(2);
106316755Sralph 	}
106416755Sralph }
1065