xref: /netbsd/usr.sbin/lpr/lpc/cmds.c (revision 032681b7)
1*032681b7Smrg /*	$NetBSD: cmds.c,v 1.25 2016/12/16 04:45:04 mrg Exp $	*/
261f28255Scgd /*
3f881d1d4Scgd  * Copyright (c) 1983, 1993
4f881d1d4Scgd  *	The Regents of the University of California.  All rights reserved.
5f881d1d4Scgd  *
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
15326b2259Sagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
32fe7ed7ceSmrg #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
349c194566Slukem __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
359c194566Slukem  The Regents of the University of California.  All rights reserved.");
36b38a221aSmikel #if 0
37e6a91a09Smrg static char sccsid[] = "@(#)cmds.c	8.2 (Berkeley) 4/28/95";
38b38a221aSmikel #else
39*032681b7Smrg __RCSID("$NetBSD: cmds.c,v 1.25 2016/12/16 04:45:04 mrg Exp $");
40b38a221aSmikel #endif
4161f28255Scgd #endif /* not lint */
4261f28255Scgd 
4361f28255Scgd /*
4461f28255Scgd  * lpc -- line printer control program -- commands:
4561f28255Scgd  */
4661f28255Scgd 
47f881d1d4Scgd #include <sys/param.h>
4861f28255Scgd #include <sys/time.h>
49f881d1d4Scgd #include <sys/stat.h>
50e6a91a09Smrg #include <sys/file.h>
51f881d1d4Scgd 
52f881d1d4Scgd #include <signal.h>
53f881d1d4Scgd #include <fcntl.h>
54f881d1d4Scgd #include <errno.h>
55f881d1d4Scgd #include <dirent.h>
56f881d1d4Scgd #include <unistd.h>
57f881d1d4Scgd #include <stdlib.h>
58f881d1d4Scgd #include <stdio.h>
59f881d1d4Scgd #include <ctype.h>
60f881d1d4Scgd #include <string.h>
61f881d1d4Scgd #include "lp.h"
62f881d1d4Scgd #include "lp.local.h"
63f881d1d4Scgd #include "lpc.h"
64f881d1d4Scgd #include "extern.h"
6561f28255Scgd #include "pathnames.h"
6661f28255Scgd 
678e41ca80Shpeyerl extern uid_t	uid, euid;
688e41ca80Shpeyerl 
69895dc72aSwiz static void	abortpr(int);
70895dc72aSwiz static void	cleanpr(void);
71895dc72aSwiz static void	disablepr(void);
7204723c3fSchristos static int	doarg(const char *);
73895dc72aSwiz static int	doselect(const struct dirent *);
74895dc72aSwiz static void	enablepr(void);
75895dc72aSwiz static void	prstat(void);
76895dc72aSwiz static void	putmsg(int, char **);
77*032681b7Smrg static int	sortq(const struct dirent **, const struct dirent **);
78895dc72aSwiz static void	startpr(int);
79895dc72aSwiz static void	stoppr(void);
80895dc72aSwiz static int	touch(struct queue *);
8104723c3fSchristos static void	unlinkf(const char *);
8204723c3fSchristos static void	upstat(const char *);
8304723c3fSchristos static int 	getcapdesc(void);
8404723c3fSchristos static void 	getcaps(void);
85f881d1d4Scgd 
8661f28255Scgd /*
8761f28255Scgd  * kill an existing daemon and disable printing.
8861f28255Scgd  */
89f881d1d4Scgd void
doabort(int argc,char * argv[])90895dc72aSwiz doabort(int argc, char *argv[])
9161f28255Scgd {
9204723c3fSchristos 	int c;
93fe7ed7ceSmrg 	char *cp1, *cp2;
9461f28255Scgd 	char prbuf[100];
9561f28255Scgd 
9661f28255Scgd 	if (argc == 1) {
9761f28255Scgd 		printf("Usage: abort {all | printer ...}\n");
9861f28255Scgd 		return;
9961f28255Scgd 	}
10061f28255Scgd 	if (argc == 2 && !strcmp(argv[1], "all")) {
10161f28255Scgd 		printer = prbuf;
102f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
10361f28255Scgd 			cp1 = prbuf;
104f881d1d4Scgd 			cp2 = bp;
105fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
106f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
10761f28255Scgd 				*cp1++ = c;
10861f28255Scgd 			*cp1 = '\0';
10961f28255Scgd 			abortpr(1);
11061f28255Scgd 		}
11161f28255Scgd 		return;
11261f28255Scgd 	}
11361f28255Scgd 	while (--argc) {
11461f28255Scgd 		printer = *++argv;
11504723c3fSchristos 		if (!getcapdesc())
11661f28255Scgd 			continue;
11761f28255Scgd 		abortpr(1);
11861f28255Scgd 	}
11961f28255Scgd }
12061f28255Scgd 
121f881d1d4Scgd static void
abortpr(int dis)122895dc72aSwiz abortpr(int dis)
12361f28255Scgd {
124fe7ed7ceSmrg 	FILE *fp;
12561f28255Scgd 	struct stat stbuf;
126fe7ed7ceSmrg 	int pid, fd;
12761f28255Scgd 
12804723c3fSchristos 	getcaps();
12961f28255Scgd 	printf("%s:\n", printer);
13061f28255Scgd 
13161f28255Scgd 	/*
13261f28255Scgd 	 * Turn on the owner execute bit of the lock file to disable printing.
13361f28255Scgd 	 */
13461f28255Scgd 	if (dis) {
1358e41ca80Shpeyerl 		seteuid(euid);
13661f28255Scgd 		if (stat(line, &stbuf) >= 0) {
13761f28255Scgd 			if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
13861f28255Scgd 				printf("\tcannot disable printing\n");
13961f28255Scgd 			else {
14061f28255Scgd 				upstat("printing disabled\n");
14161f28255Scgd 				printf("\tprinting disabled\n");
14261f28255Scgd 			}
14361f28255Scgd 		} else if (errno == ENOENT) {
14461f28255Scgd 			if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
14561f28255Scgd 				printf("\tcannot create lock file\n");
14661f28255Scgd 			else {
14761f28255Scgd 				(void)close(fd);
14861f28255Scgd 				upstat("printing disabled\n");
14961f28255Scgd 				printf("\tprinting disabled\n");
15061f28255Scgd 				printf("\tno daemon to abort\n");
15161f28255Scgd 			}
1528e41ca80Shpeyerl 			goto out;
15361f28255Scgd 		} else {
15461f28255Scgd 			printf("\tcannot stat lock file\n");
1558e41ca80Shpeyerl 			goto out;
15661f28255Scgd 		}
15761f28255Scgd 	}
15861f28255Scgd 	/*
15961f28255Scgd 	 * Kill the current daemon to stop printing now.
16061f28255Scgd 	 */
16161f28255Scgd 	if ((fp = fopen(line, "r")) == NULL) {
16261f28255Scgd 		printf("\tcannot open lock file\n");
1638e41ca80Shpeyerl 		goto out;
16461f28255Scgd 	}
1657027866aSroy 	if (!get_line(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
16661f28255Scgd 		(void)fclose(fp);	/* unlocks as well */
16761f28255Scgd 		printf("\tno daemon to abort\n");
1688e41ca80Shpeyerl 		goto out;
16961f28255Scgd 	}
17061f28255Scgd 	(void)fclose(fp);
171fe7ed7ceSmrg 	if (kill(pid = atoi(line), SIGTERM) < 0) {
172fe7ed7ceSmrg 		if (errno == ESRCH)
173fe7ed7ceSmrg 			printf("\tno daemon to abort\n");
17461f28255Scgd 		else
175fe7ed7ceSmrg 			printf("\tWarning: daemon (pid %d) not killed\n", pid);
176fe7ed7ceSmrg 	} else
17761f28255Scgd 		printf("\tdaemon (pid %d) killed\n", pid);
1788e41ca80Shpeyerl out:
1798e41ca80Shpeyerl 	seteuid(uid);
18061f28255Scgd }
18161f28255Scgd 
18261f28255Scgd /*
18361f28255Scgd  * Write a message into the status file.
18461f28255Scgd  */
185f881d1d4Scgd static void
upstat(const char * msg)18604723c3fSchristos upstat(const char *msg)
18761f28255Scgd {
188fe7ed7ceSmrg 	int fd;
189fe7ed7ceSmrg 	char statfile[MAXPATHLEN];
19061f28255Scgd 
19104723c3fSchristos 	getcaps();
192077acf50Smrg 	(void)snprintf(statfile, sizeof(statfile), "%s/%s", SD, ST);
19361f28255Scgd 	umask(0);
19461f28255Scgd 	fd = open(statfile, O_WRONLY|O_CREAT, 0664);
19561f28255Scgd 	if (fd < 0 || flock(fd, LOCK_EX) < 0) {
19661f28255Scgd 		printf("\tcannot create status file\n");
197db1dbe6cSchristos 		if (fd >= 0)
198db1dbe6cSchristos 			(void)close(fd);
19961f28255Scgd 		return;
20061f28255Scgd 	}
20161f28255Scgd 	(void)ftruncate(fd, 0);
2024a1b3429Splunky 	if (msg == NULL)
20361f28255Scgd 		(void)write(fd, "\n", 1);
20461f28255Scgd 	else
20561f28255Scgd 		(void)write(fd, msg, strlen(msg));
20661f28255Scgd 	(void)close(fd);
20761f28255Scgd }
20861f28255Scgd 
20961f28255Scgd /*
21061f28255Scgd  * Remove all spool files and temporaries from the spooling area.
21161f28255Scgd  */
212f881d1d4Scgd void
clean(int argc,char * argv[])213895dc72aSwiz clean(int argc, char *argv[])
21461f28255Scgd {
21504723c3fSchristos 	int c;
216fe7ed7ceSmrg 	char *cp1, *cp2;
21761f28255Scgd 	char prbuf[100];
21861f28255Scgd 
21961f28255Scgd 	if (argc == 1) {
22061f28255Scgd 		printf("Usage: clean {all | printer ...}\n");
22161f28255Scgd 		return;
22261f28255Scgd 	}
22361f28255Scgd 	if (argc == 2 && !strcmp(argv[1], "all")) {
22461f28255Scgd 		printer = prbuf;
225f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
22661f28255Scgd 			cp1 = prbuf;
227f881d1d4Scgd 			cp2 = bp;
228fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
229f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
23061f28255Scgd 				*cp1++ = c;
23161f28255Scgd 			*cp1 = '\0';
23261f28255Scgd 			cleanpr();
23361f28255Scgd 		}
23461f28255Scgd 		return;
23561f28255Scgd 	}
23661f28255Scgd 	while (--argc) {
23761f28255Scgd 		printer = *++argv;
23804723c3fSchristos 		if (!getcapdesc())
23961f28255Scgd 			continue;
24061f28255Scgd 		cleanpr();
24161f28255Scgd 	}
24261f28255Scgd }
24361f28255Scgd 
244f881d1d4Scgd static int
doselect(const struct dirent * d)245895dc72aSwiz doselect(const struct dirent *d)
24661f28255Scgd {
24761f28255Scgd 	int c = d->d_name[0];
24861f28255Scgd 
24961f28255Scgd 	if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f')
25061f28255Scgd 		return(1);
25161f28255Scgd 	return(0);
25261f28255Scgd }
25361f28255Scgd 
25461f28255Scgd /*
25561f28255Scgd  * Comparison routine for scandir. Sort by job number and machine, then
25661f28255Scgd  * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z.
25761f28255Scgd  */
258f881d1d4Scgd static int
sortq(const struct dirent ** d1,const struct dirent ** d2)259*032681b7Smrg sortq(const struct dirent **d1, const struct dirent **d2)
26061f28255Scgd {
26161f28255Scgd 	int c1, c2;
26261f28255Scgd 
2630b0a21a5Smikel 	if ((c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) != 0)
26461f28255Scgd 		return(c1);
26561f28255Scgd 	c1 = (*d1)->d_name[0];
26661f28255Scgd 	c2 = (*d2)->d_name[0];
26761f28255Scgd 	if (c1 == c2)
26861f28255Scgd 		return((*d1)->d_name[2] - (*d2)->d_name[2]);
26961f28255Scgd 	if (c1 == 'c')
27061f28255Scgd 		return(-1);
27161f28255Scgd 	if (c1 == 'd' || c2 == 'c')
27261f28255Scgd 		return(1);
27361f28255Scgd 	return(-1);
27461f28255Scgd }
27561f28255Scgd 
27661f28255Scgd /*
27761f28255Scgd  * Remove incomplete jobs from spooling area.
27861f28255Scgd  */
279f881d1d4Scgd static void
cleanpr(void)280895dc72aSwiz cleanpr(void)
28161f28255Scgd {
282fe7ed7ceSmrg 	int i, n;
28304723c3fSchristos 	char *cp1, *lp, *ep;
28404723c3fSchristos 	const char *cp;
2853ccb8240Sjtc 	struct dirent **queue;
28661f28255Scgd 	int nitems;
28761f28255Scgd 
28804723c3fSchristos 	getcaps();
28961f28255Scgd 	printf("%s:\n", printer);
29061f28255Scgd 
291077acf50Smrg 	/* XXX depends on SD being non nul */
29285da8822Sitojun 	ep = line + sizeof(line);
293f5a433a7Slukem 	for (lp = line, cp = SD; (size_t)(lp - line) < sizeof(line) &&
294fe7ed7ceSmrg 	    (*lp++ = *cp++) != '\0'; )
29561f28255Scgd 		;
29661f28255Scgd 	lp[-1] = '/';
29761f28255Scgd 
2988e41ca80Shpeyerl 	seteuid(euid);
299f881d1d4Scgd 	nitems = scandir(SD, &queue, doselect, sortq);
3008e41ca80Shpeyerl 	seteuid(uid);
30161f28255Scgd 	if (nitems < 0) {
30261f28255Scgd 		printf("\tcannot examine spool directory\n");
30361f28255Scgd 		return;
30461f28255Scgd 	}
30561f28255Scgd 	if (nitems == 0)
30661f28255Scgd 		return;
30761f28255Scgd 	i = 0;
30861f28255Scgd 	do {
30961f28255Scgd 		cp = queue[i]->d_name;
31061f28255Scgd 		if (*cp == 'c') {
31161f28255Scgd 			n = 0;
31261f28255Scgd 			while (i + 1 < nitems) {
31361f28255Scgd 				cp1 = queue[i + 1]->d_name;
31461f28255Scgd 				if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3))
31561f28255Scgd 					break;
31661f28255Scgd 				i++;
31761f28255Scgd 				n++;
31861f28255Scgd 			}
31961f28255Scgd 			if (n == 0) {
32085da8822Sitojun 				strlcpy(lp, cp, ep - lp);
32161f28255Scgd 				unlinkf(line);
32261f28255Scgd 			}
32361f28255Scgd 		} else {
32461f28255Scgd 			/*
32561f28255Scgd 			 * Must be a df with no cf (otherwise, it would have
32661f28255Scgd 			 * been skipped above) or a tf file (which can always
32761f28255Scgd 			 * be removed).
32861f28255Scgd 			 */
32985da8822Sitojun 			strlcpy(lp, cp, ep - lp);
33061f28255Scgd 			unlinkf(line);
33161f28255Scgd 		}
33261f28255Scgd      	} while (++i < nitems);
33361f28255Scgd }
33461f28255Scgd 
335f881d1d4Scgd static void
unlinkf(const char * name)33604723c3fSchristos unlinkf(const char *name)
33761f28255Scgd {
3388e41ca80Shpeyerl 	seteuid(euid);
33961f28255Scgd 	if (unlink(name) < 0)
34061f28255Scgd 		printf("\tcannot remove %s\n", name);
34161f28255Scgd 	else
34261f28255Scgd 		printf("\tremoved %s\n", name);
3438e41ca80Shpeyerl 	seteuid(uid);
34461f28255Scgd }
34561f28255Scgd 
34661f28255Scgd /*
34761f28255Scgd  * Enable queuing to the printer (allow lpr's).
34861f28255Scgd  */
349f881d1d4Scgd void
enable(int argc,char * argv[])350895dc72aSwiz enable(int argc, char *argv[])
35161f28255Scgd {
35204723c3fSchristos 	int c;
353fe7ed7ceSmrg 	char *cp1, *cp2;
35461f28255Scgd 	char prbuf[100];
35561f28255Scgd 
35661f28255Scgd 	if (argc == 1) {
35761f28255Scgd 		printf("Usage: enable {all | printer ...}\n");
35861f28255Scgd 		return;
35961f28255Scgd 	}
36061f28255Scgd 	if (argc == 2 && !strcmp(argv[1], "all")) {
36161f28255Scgd 		printer = prbuf;
362f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
36361f28255Scgd 			cp1 = prbuf;
364f881d1d4Scgd 			cp2 = bp;
365fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
366f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
36761f28255Scgd 				*cp1++ = c;
36861f28255Scgd 			*cp1 = '\0';
36961f28255Scgd 			enablepr();
37061f28255Scgd 		}
37161f28255Scgd 		return;
37261f28255Scgd 	}
37361f28255Scgd 	while (--argc) {
37461f28255Scgd 		printer = *++argv;
37504723c3fSchristos 		if (!getcapdesc())
37661f28255Scgd 			continue;
37761f28255Scgd 		enablepr();
37861f28255Scgd 	}
37961f28255Scgd }
38061f28255Scgd 
38104723c3fSchristos static int
getcapdesc(void)38204723c3fSchristos getcapdesc(void)
38304723c3fSchristos {
38404723c3fSchristos 	int st;
38504723c3fSchristos 	if ((st = cgetent(&bp, printcapdb, printer)) == -2) {
38604723c3fSchristos 		printf("cannot open printer description file\n");
38704723c3fSchristos 		return 0;
38804723c3fSchristos 	} else if (st == -1) {
38904723c3fSchristos 		printf("unknown printer %s\n", printer);
39004723c3fSchristos 		return 0;
39104723c3fSchristos 	} else if (st == -3)
39204723c3fSchristos 		fatal("potential reference loop detected in printcap file");
39304723c3fSchristos 	return 1;
39404723c3fSchristos }
39504723c3fSchristos 
396f881d1d4Scgd static void
enablepr(void)397895dc72aSwiz enablepr(void)
39861f28255Scgd {
39961f28255Scgd 	struct stat stbuf;
40061f28255Scgd 
40104723c3fSchristos 	getcaps();
40261f28255Scgd 	printf("%s:\n", printer);
40361f28255Scgd 
40461f28255Scgd 	/*
40561f28255Scgd 	 * Turn off the group execute bit of the lock file to enable queuing.
40661f28255Scgd 	 */
4078e41ca80Shpeyerl 	seteuid(euid);
40861f28255Scgd 	if (stat(line, &stbuf) >= 0) {
40961f28255Scgd 		if (chmod(line, stbuf.st_mode & 0767) < 0)
41061f28255Scgd 			printf("\tcannot enable queuing\n");
41161f28255Scgd 		else
41261f28255Scgd 			printf("\tqueuing enabled\n");
41361f28255Scgd 	}
4148e41ca80Shpeyerl 	seteuid(uid);
41561f28255Scgd }
41661f28255Scgd 
41761f28255Scgd /*
41861f28255Scgd  * Disable queuing.
41961f28255Scgd  */
420f881d1d4Scgd void
disable(int argc,char * argv[])421895dc72aSwiz disable(int argc, char *argv[])
42261f28255Scgd {
42304723c3fSchristos 	int c;
424fe7ed7ceSmrg 	char *cp1, *cp2;
42561f28255Scgd 	char prbuf[100];
42661f28255Scgd 
42761f28255Scgd 	if (argc == 1) {
42861f28255Scgd 		printf("Usage: disable {all | printer ...}\n");
42961f28255Scgd 		return;
43061f28255Scgd 	}
43161f28255Scgd 	if (argc == 2 && !strcmp(argv[1], "all")) {
43261f28255Scgd 		printer = prbuf;
433f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
43461f28255Scgd 			cp1 = prbuf;
435f881d1d4Scgd 			cp2 = bp;
436fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
437f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
43861f28255Scgd 				*cp1++ = c;
43961f28255Scgd 			*cp1 = '\0';
44061f28255Scgd 			disablepr();
44161f28255Scgd 		}
44261f28255Scgd 		return;
44361f28255Scgd 	}
44461f28255Scgd 	while (--argc) {
44561f28255Scgd 		printer = *++argv;
44604723c3fSchristos 		if (!getcapdesc())
44761f28255Scgd 			continue;
44861f28255Scgd 		disablepr();
44961f28255Scgd 	}
45061f28255Scgd }
45161f28255Scgd 
452f881d1d4Scgd static void
disablepr(void)453895dc72aSwiz disablepr(void)
45461f28255Scgd {
455fe7ed7ceSmrg 	int fd;
45661f28255Scgd 	struct stat stbuf;
45761f28255Scgd 
45804723c3fSchristos 	getcaps();
45961f28255Scgd 	printf("%s:\n", printer);
46061f28255Scgd 	/*
46161f28255Scgd 	 * Turn on the group execute bit of the lock file to disable queuing.
46261f28255Scgd 	 */
4638e41ca80Shpeyerl 	seteuid(euid);
46461f28255Scgd 	if (stat(line, &stbuf) >= 0) {
46561f28255Scgd 		if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0)
46661f28255Scgd 			printf("\tcannot disable queuing\n");
46761f28255Scgd 		else
46861f28255Scgd 			printf("\tqueuing disabled\n");
46961f28255Scgd 	} else if (errno == ENOENT) {
47061f28255Scgd 		if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0)
47161f28255Scgd 			printf("\tcannot create lock file\n");
47261f28255Scgd 		else {
47361f28255Scgd 			(void)close(fd);
47461f28255Scgd 			printf("\tqueuing disabled\n");
47561f28255Scgd 		}
47661f28255Scgd 	} else
47761f28255Scgd 		printf("\tcannot stat lock file\n");
4788e41ca80Shpeyerl 	seteuid(uid);
47961f28255Scgd }
48061f28255Scgd 
48161f28255Scgd /*
48261f28255Scgd  * Disable queuing and printing and put a message into the status file
48361f28255Scgd  * (reason for being down).
48461f28255Scgd  */
485f881d1d4Scgd void
down(int argc,char * argv[])486895dc72aSwiz down(int argc, char *argv[])
48761f28255Scgd {
48804723c3fSchristos 	int c;
489fe7ed7ceSmrg 	char *cp1, *cp2;
49061f28255Scgd 	char prbuf[100];
49161f28255Scgd 
49261f28255Scgd 	if (argc == 1) {
49361f28255Scgd 		printf("Usage: down {all | printer} [message ...]\n");
49461f28255Scgd 		return;
49561f28255Scgd 	}
49661f28255Scgd 	if (!strcmp(argv[1], "all")) {
49761f28255Scgd 		printer = prbuf;
498f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
49961f28255Scgd 			cp1 = prbuf;
500f881d1d4Scgd 			cp2 = bp;
501fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
502f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
50361f28255Scgd 				*cp1++ = c;
50461f28255Scgd 			*cp1 = '\0';
50561f28255Scgd 			putmsg(argc - 2, argv + 2);
50661f28255Scgd 		}
50761f28255Scgd 		return;
50861f28255Scgd 	}
50961f28255Scgd 	printer = argv[1];
51004723c3fSchristos 	if (!getcapdesc())
51161f28255Scgd 		return;
51261f28255Scgd 	putmsg(argc - 2, argv + 2);
51361f28255Scgd }
51461f28255Scgd 
515f881d1d4Scgd static void
getcaps(void)51604723c3fSchristos getcaps(void)
51704723c3fSchristos {
51804723c3fSchristos 	char *cp;
51904723c3fSchristos 	SD = cgetstr(bp, "sd", &cp) == -1 ? _PATH_DEFSPOOL : cp;
52004723c3fSchristos 	LO = cgetstr(bp, "lo", &cp) == -1 ?  DEFLOCK : cp;
52104723c3fSchristos 	ST = cgetstr(bp, "st", &cp) == -1 ? DEFSTAT : cp;
52204723c3fSchristos 	(void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
52304723c3fSchristos }
52404723c3fSchristos 
52504723c3fSchristos static void
putmsg(int argc,char ** argv)526895dc72aSwiz putmsg(int argc, char **argv)
52761f28255Scgd {
528fe7ed7ceSmrg 	int fd;
529fe7ed7ceSmrg 	char *cp1, *cp2;
53061f28255Scgd 	char buf[1024];
53161f28255Scgd 	struct stat stbuf;
53261f28255Scgd 
53361f28255Scgd 	printf("%s:\n", printer);
53461f28255Scgd 	/*
53561f28255Scgd 	 * Turn on the group execute bit of the lock file to disable queuing and
53661f28255Scgd 	 * turn on the owner execute bit of the lock file to disable printing.
53761f28255Scgd 	 */
5388e41ca80Shpeyerl 	seteuid(euid);
53961f28255Scgd 	if (stat(line, &stbuf) >= 0) {
54061f28255Scgd 		if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0)
54161f28255Scgd 			printf("\tcannot disable queuing\n");
54261f28255Scgd 		else
54361f28255Scgd 			printf("\tprinter and queuing disabled\n");
54461f28255Scgd 	} else if (errno == ENOENT) {
54561f28255Scgd 		if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0)
54661f28255Scgd 			printf("\tcannot create lock file\n");
54761f28255Scgd 		else {
54861f28255Scgd 			(void)close(fd);
54961f28255Scgd 			printf("\tprinter and queuing disabled\n");
55061f28255Scgd 		}
5518e41ca80Shpeyerl 		seteuid(uid);
55261f28255Scgd 		return;
55361f28255Scgd 	} else
55461f28255Scgd 		printf("\tcannot stat lock file\n");
55561f28255Scgd 	/*
55661f28255Scgd 	 * Write the message into the status file.
55761f28255Scgd 	 */
558077acf50Smrg 	(void)snprintf(line, sizeof(line), "%s/%s", SD, ST);
55961f28255Scgd 	fd = open(line, O_WRONLY|O_CREAT, 0664);
56061f28255Scgd 	if (fd < 0 || flock(fd, LOCK_EX) < 0) {
56161f28255Scgd 		printf("\tcannot create status file\n");
5628e41ca80Shpeyerl 		seteuid(uid);
5633aa76316Swiz 		if (fd >= 0)
5643aa76316Swiz 			(void)close(fd);
56561f28255Scgd 		return;
56661f28255Scgd 	}
5678e41ca80Shpeyerl 	seteuid(uid);
56861f28255Scgd 	(void)ftruncate(fd, 0);
56961f28255Scgd 	if (argc <= 0) {
57061f28255Scgd 		(void)write(fd, "\n", 1);
57161f28255Scgd 		(void)close(fd);
57261f28255Scgd 		return;
57361f28255Scgd 	}
57461f28255Scgd 	cp1 = buf;
57561f28255Scgd 	while (--argc >= 0) {
57661f28255Scgd 		cp2 = *argv++;
577f5a433a7Slukem 		while ((size_t)(cp1 - buf) < sizeof(buf) && (*cp1++ = *cp2++))
57861f28255Scgd 			;
57961f28255Scgd 		cp1[-1] = ' ';
58061f28255Scgd 	}
58161f28255Scgd 	cp1[-1] = '\n';
58261f28255Scgd 	*cp1 = '\0';
58361f28255Scgd 	(void)write(fd, buf, strlen(buf));
58461f28255Scgd 	(void)close(fd);
58561f28255Scgd }
58661f28255Scgd 
58761f28255Scgd /*
58861f28255Scgd  * Exit lpc
58961f28255Scgd  */
590f881d1d4Scgd void
quit(int argc,char * argv[])591895dc72aSwiz quit(int argc, char *argv[])
59261f28255Scgd {
59361f28255Scgd 	exit(0);
59461f28255Scgd }
59561f28255Scgd 
59661f28255Scgd /*
59761f28255Scgd  * Kill and restart the daemon.
59861f28255Scgd  */
599f881d1d4Scgd void
restart(int argc,char * argv[])600895dc72aSwiz restart(int argc, char *argv[])
60161f28255Scgd {
60204723c3fSchristos 	int c;
603fe7ed7ceSmrg 	char *cp1, *cp2;
60461f28255Scgd 	char prbuf[100];
60561f28255Scgd 
60661f28255Scgd 	if (argc == 1) {
60761f28255Scgd 		printf("Usage: restart {all | printer ...}\n");
60861f28255Scgd 		return;
60961f28255Scgd 	}
61061f28255Scgd 	if (argc == 2 && !strcmp(argv[1], "all")) {
61161f28255Scgd 		printer = prbuf;
612f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
61361f28255Scgd 			cp1 = prbuf;
614f881d1d4Scgd 			cp2 = bp;
615fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
616f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
61761f28255Scgd 				*cp1++ = c;
61861f28255Scgd 			*cp1 = '\0';
61961f28255Scgd 			abortpr(0);
62061f28255Scgd 			startpr(0);
62161f28255Scgd 		}
62261f28255Scgd 		return;
62361f28255Scgd 	}
62461f28255Scgd 	while (--argc) {
62561f28255Scgd 		printer = *++argv;
62604723c3fSchristos 		if (!getcapdesc())
62761f28255Scgd 			continue;
62861f28255Scgd 		abortpr(0);
62961f28255Scgd 		startpr(0);
63061f28255Scgd 	}
63161f28255Scgd }
63261f28255Scgd 
63361f28255Scgd /*
63461f28255Scgd  * Enable printing on the specified printer and startup the daemon.
63561f28255Scgd  */
636f881d1d4Scgd void
startcmd(int argc,char * argv[])637895dc72aSwiz startcmd(int argc, char *argv[])
63861f28255Scgd {
63904723c3fSchristos 	int c;
640fe7ed7ceSmrg 	char *cp1, *cp2;
64161f28255Scgd 	char prbuf[100];
64261f28255Scgd 
64361f28255Scgd 	if (argc == 1) {
64461f28255Scgd 		printf("Usage: start {all | printer ...}\n");
64561f28255Scgd 		return;
64661f28255Scgd 	}
64761f28255Scgd 	if (argc == 2 && !strcmp(argv[1], "all")) {
64861f28255Scgd 		printer = prbuf;
649f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
65061f28255Scgd 			cp1 = prbuf;
651f881d1d4Scgd 			cp2 = bp;
652fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
653f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
65461f28255Scgd 				*cp1++ = c;
65561f28255Scgd 			*cp1 = '\0';
65661f28255Scgd 			startpr(1);
65761f28255Scgd 		}
65861f28255Scgd 		return;
65961f28255Scgd 	}
66061f28255Scgd 	while (--argc) {
66161f28255Scgd 		printer = *++argv;
66204723c3fSchristos 		if (!getcapdesc())
66361f28255Scgd 			continue;
66461f28255Scgd 		startpr(1);
66561f28255Scgd 	}
66661f28255Scgd }
66761f28255Scgd 
668f881d1d4Scgd static void
startpr(int ena)66904723c3fSchristos startpr(int ena)
67061f28255Scgd {
67161f28255Scgd 	struct stat stbuf;
67261f28255Scgd 
67304723c3fSchristos 	getcaps();
67461f28255Scgd 	printf("%s:\n", printer);
67561f28255Scgd 
67661f28255Scgd 	/*
67761f28255Scgd 	 * Turn off the owner execute bit of the lock file to enable printing.
67861f28255Scgd 	 */
6798e41ca80Shpeyerl 	seteuid(euid);
68004723c3fSchristos 	if (ena && stat(line, &stbuf) >= 0) {
68104723c3fSchristos 		if (chmod(line, stbuf.st_mode & (ena == 2 ? 0666 : 0677)) < 0)
68261f28255Scgd 			printf("\tcannot enable printing\n");
68361f28255Scgd 		else
68461f28255Scgd 			printf("\tprinting enabled\n");
68561f28255Scgd 	}
68661f28255Scgd 	if (!startdaemon(printer))
68761f28255Scgd 		printf("\tcouldn't start daemon\n");
68861f28255Scgd 	else
68961f28255Scgd 		printf("\tdaemon started\n");
6908e41ca80Shpeyerl 	seteuid(uid);
69161f28255Scgd }
69261f28255Scgd 
69361f28255Scgd /*
69461f28255Scgd  * Print the status of each queue listed or all the queues.
69561f28255Scgd  */
696f881d1d4Scgd void
status(int argc,char * argv[])697895dc72aSwiz status(int argc, char *argv[])
69861f28255Scgd {
69904723c3fSchristos 	int c;
700fe7ed7ceSmrg 	char *cp1, *cp2;
70161f28255Scgd 	char prbuf[100];
70261f28255Scgd 
703fe7ed7ceSmrg 	if (argc == 1 || (argc == 2 && strcmp(argv[1], "all") == 0)) {
70461f28255Scgd 		printer = prbuf;
705f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
70661f28255Scgd 			cp1 = prbuf;
707f881d1d4Scgd 			cp2 = bp;
708fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
709f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
71061f28255Scgd 				*cp1++ = c;
71161f28255Scgd 			*cp1 = '\0';
71261f28255Scgd 			prstat();
71361f28255Scgd 		}
71461f28255Scgd 		return;
71561f28255Scgd 	}
71661f28255Scgd 	while (--argc) {
71761f28255Scgd 		printer = *++argv;
71804723c3fSchristos 		if (!getcapdesc())
71961f28255Scgd 			continue;
72061f28255Scgd 		prstat();
72161f28255Scgd 	}
72261f28255Scgd }
72361f28255Scgd 
72461f28255Scgd /*
72561f28255Scgd  * Print the status of the printer queue.
72661f28255Scgd  */
727f881d1d4Scgd static void
prstat(void)728895dc72aSwiz prstat(void)
72961f28255Scgd {
73061f28255Scgd 	struct stat stbuf;
731fe7ed7ceSmrg 	int fd, i;
732fe7ed7ceSmrg 	struct dirent *dp;
73361f28255Scgd 	DIR *dirp;
73461f28255Scgd 
73504723c3fSchristos 	getcaps();
73661f28255Scgd 	printf("%s:\n", printer);
73761f28255Scgd 	if (stat(line, &stbuf) >= 0) {
73861f28255Scgd 		printf("\tqueuing is %s\n",
73961f28255Scgd 			(stbuf.st_mode & 010) ? "disabled" : "enabled");
74061f28255Scgd 		printf("\tprinting is %s\n",
74161f28255Scgd 			(stbuf.st_mode & 0100) ? "disabled" : "enabled");
74261f28255Scgd 	} else {
74361f28255Scgd 		printf("\tqueuing is enabled\n");
74461f28255Scgd 		printf("\tprinting is enabled\n");
74561f28255Scgd 	}
74661f28255Scgd 	if ((dirp = opendir(SD)) == NULL) {
74761f28255Scgd 		printf("\tcannot examine spool directory\n");
74861f28255Scgd 		return;
74961f28255Scgd 	}
75061f28255Scgd 	i = 0;
75161f28255Scgd 	while ((dp = readdir(dirp)) != NULL) {
75261f28255Scgd 		if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
75361f28255Scgd 			i++;
75461f28255Scgd 	}
75561f28255Scgd 	closedir(dirp);
75661f28255Scgd 	if (i == 0)
75761f28255Scgd 		printf("\tno entries\n");
75861f28255Scgd 	else if (i == 1)
75961f28255Scgd 		printf("\t1 entry in spool area\n");
76061f28255Scgd 	else
76161f28255Scgd 		printf("\t%d entries in spool area\n", i);
76261f28255Scgd 	fd = open(line, O_RDONLY);
76361f28255Scgd 	if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
764db1dbe6cSchristos 		if (fd >= 0)
76561f28255Scgd 			(void)close(fd);	/* unlocks as well */
7668c4481f8Shpeyerl 		printf("\tprinter idle\n");
76761f28255Scgd 		return;
76861f28255Scgd 	}
76961f28255Scgd 	(void)close(fd);
770077acf50Smrg 	(void)snprintf(line, sizeof(line), "%s/%s", SD, ST);
77161f28255Scgd 	fd = open(line, O_RDONLY);
77261f28255Scgd 	if (fd >= 0) {
77361f28255Scgd 		(void)flock(fd, LOCK_SH);
774fe7ed7ceSmrg 		(void)fstat(fd, &stbuf);
775fe7ed7ceSmrg 		if (stbuf.st_size > 0) {
776fe7ed7ceSmrg 			putchar('\t');
77761f28255Scgd 			while ((i = read(fd, line, sizeof(line))) > 0)
77861f28255Scgd 				(void)fwrite(line, 1, i, stdout);
779fe7ed7ceSmrg 		}
78061f28255Scgd 		(void)close(fd);	/* unlocks as well */
78161f28255Scgd 	}
78261f28255Scgd }
78361f28255Scgd 
78461f28255Scgd /*
78561f28255Scgd  * Stop the specified daemon after completing the current job and disable
78661f28255Scgd  * printing.
78761f28255Scgd  */
788f881d1d4Scgd void
stop(int argc,char * argv[])789895dc72aSwiz stop(int argc, char *argv[])
79061f28255Scgd {
79104723c3fSchristos 	int c;
792fe7ed7ceSmrg 	char *cp1, *cp2;
79361f28255Scgd 	char prbuf[100];
79461f28255Scgd 
79561f28255Scgd 	if (argc == 1) {
79661f28255Scgd 		printf("Usage: stop {all | printer ...}\n");
79761f28255Scgd 		return;
79861f28255Scgd 	}
79961f28255Scgd 	if (argc == 2 && !strcmp(argv[1], "all")) {
80061f28255Scgd 		printer = prbuf;
801f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
80261f28255Scgd 			cp1 = prbuf;
803f881d1d4Scgd 			cp2 = bp;
804fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
805f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
80661f28255Scgd 				*cp1++ = c;
80761f28255Scgd 			*cp1 = '\0';
80861f28255Scgd 			stoppr();
80961f28255Scgd 		}
81061f28255Scgd 		return;
81161f28255Scgd 	}
81261f28255Scgd 	while (--argc) {
81361f28255Scgd 		printer = *++argv;
81404723c3fSchristos 		if (!getcapdesc())
81561f28255Scgd 			continue;
81661f28255Scgd 		stoppr();
81761f28255Scgd 	}
81861f28255Scgd }
81961f28255Scgd 
820f881d1d4Scgd static void
stoppr(void)821895dc72aSwiz stoppr(void)
82261f28255Scgd {
823fe7ed7ceSmrg 	int fd;
82461f28255Scgd 	struct stat stbuf;
82561f28255Scgd 
82604723c3fSchristos 	getcaps();
82761f28255Scgd 	printf("%s:\n", printer);
82861f28255Scgd 
82961f28255Scgd 	/*
83061f28255Scgd 	 * Turn on the owner execute bit of the lock file to disable printing.
83161f28255Scgd 	 */
8328e41ca80Shpeyerl 	seteuid(euid);
83361f28255Scgd 	if (stat(line, &stbuf) >= 0) {
83461f28255Scgd 		if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0)
83561f28255Scgd 			printf("\tcannot disable printing\n");
83661f28255Scgd 		else {
83761f28255Scgd 			upstat("printing disabled\n");
83861f28255Scgd 			printf("\tprinting disabled\n");
83961f28255Scgd 		}
84061f28255Scgd 	} else if (errno == ENOENT) {
84161f28255Scgd 		if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0)
84261f28255Scgd 			printf("\tcannot create lock file\n");
84361f28255Scgd 		else {
84461f28255Scgd 			(void)close(fd);
84561f28255Scgd 			upstat("printing disabled\n");
84661f28255Scgd 			printf("\tprinting disabled\n");
84761f28255Scgd 		}
84861f28255Scgd 	} else
84961f28255Scgd 		printf("\tcannot stat lock file\n");
8508e41ca80Shpeyerl 	seteuid(uid);
85161f28255Scgd }
85261f28255Scgd 
85361f28255Scgd struct	queue **queue;
85461f28255Scgd int	nitems;
85561f28255Scgd time_t	mtime;
85661f28255Scgd 
85761f28255Scgd /*
85861f28255Scgd  * Put the specified jobs at the top of printer queue.
85961f28255Scgd  */
860f881d1d4Scgd void
topq(int argc,char * argv[])861895dc72aSwiz topq(int argc, char *argv[])
86261f28255Scgd {
863fe7ed7ceSmrg 	int i;
86461f28255Scgd 	struct stat stbuf;
86504723c3fSchristos 	int changed;
86661f28255Scgd 
86761f28255Scgd 	if (argc < 3) {
86861f28255Scgd 		printf("Usage: topq printer [jobnum ...] [user ...]\n");
86961f28255Scgd 		return;
87061f28255Scgd 	}
87161f28255Scgd 
87261f28255Scgd 	--argc;
87361f28255Scgd 	printer = *++argv;
87404723c3fSchristos 	if (!getcapdesc())
87561f28255Scgd 		return;
876f881d1d4Scgd 
87704723c3fSchristos 	getcaps();
87861f28255Scgd 	printf("%s:\n", printer);
87961f28255Scgd 
8808e41ca80Shpeyerl 	seteuid(euid);
88161f28255Scgd 	if (chdir(SD) < 0) {
88261f28255Scgd 		printf("\tcannot chdir to %s\n", SD);
8838e41ca80Shpeyerl 		goto out;
88461f28255Scgd 	}
8858e41ca80Shpeyerl 	seteuid(uid);
88661f28255Scgd 	nitems = getq(&queue);
88761f28255Scgd 	if (nitems == 0)
88861f28255Scgd 		return;
88961f28255Scgd 	changed = 0;
89061f28255Scgd 	mtime = queue[0]->q_time;
89161f28255Scgd 	for (i = argc; --i; ) {
89261f28255Scgd 		if (doarg(argv[i]) == 0) {
89361f28255Scgd 			printf("\tjob %s is not in the queue\n", argv[i]);
89461f28255Scgd 			continue;
89561f28255Scgd 		} else
89661f28255Scgd 			changed++;
89761f28255Scgd 	}
89861f28255Scgd 	for (i = 0; i < nitems; i++)
89961f28255Scgd 		free(queue[i]);
90061f28255Scgd 	free(queue);
90161f28255Scgd 	if (!changed) {
90261f28255Scgd 		printf("\tqueue order unchanged\n");
90361f28255Scgd 		return;
90461f28255Scgd 	}
90561f28255Scgd 	/*
90661f28255Scgd 	 * Turn on the public execute bit of the lock file to
90761f28255Scgd 	 * get lpd to rebuild the queue after the current job.
90861f28255Scgd 	 */
9098e41ca80Shpeyerl 	seteuid(euid);
91061f28255Scgd 	if (changed && stat(LO, &stbuf) >= 0)
91161f28255Scgd 		(void)chmod(LO, (stbuf.st_mode & 0777) | 01);
9128e41ca80Shpeyerl 
9138e41ca80Shpeyerl out:
9148e41ca80Shpeyerl 	seteuid(uid);
91561f28255Scgd }
91661f28255Scgd 
91761f28255Scgd /*
91861f28255Scgd  * Reposition the job by changing the modification time of
91961f28255Scgd  * the control file.
92061f28255Scgd  */
921f881d1d4Scgd static int
touch(struct queue * q)922895dc72aSwiz touch(struct queue *q)
92361f28255Scgd {
92461f28255Scgd 	struct timeval tvp[2];
9258e41ca80Shpeyerl 	int ret;
92661f28255Scgd 
92761f28255Scgd 	tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
92861f28255Scgd 	tvp[0].tv_usec = tvp[1].tv_usec = 0;
9298e41ca80Shpeyerl 	seteuid(euid);
9308e41ca80Shpeyerl 	ret = utimes(q->q_name, tvp);
9318e41ca80Shpeyerl 	seteuid(uid);
9328e41ca80Shpeyerl 	return (ret);
93361f28255Scgd }
93461f28255Scgd 
93561f28255Scgd /*
93661f28255Scgd  * Checks if specified job name is in the printer's queue.
93761f28255Scgd  * Returns:  negative (-1) if argument name is not in the queue.
93861f28255Scgd  */
939f881d1d4Scgd static int
doarg(const char * job)94004723c3fSchristos doarg(const char *job)
94161f28255Scgd {
942fe7ed7ceSmrg 	struct queue **qq;
943fe7ed7ceSmrg 	int jobnum, n;
94404723c3fSchristos 	char *cp;
94504723c3fSchristos 	const char *machine;
94661f28255Scgd 	int cnt = 0;
94761f28255Scgd 	FILE *fp;
94861f28255Scgd 
94961f28255Scgd 	/*
95061f28255Scgd 	 * Look for a job item consisting of system name, colon, number
95161f28255Scgd 	 * (example: ucbarpa:114)
95261f28255Scgd 	 */
953fe7ed7ceSmrg 	if ((cp = strchr(job, ':')) != NULL) {
95461f28255Scgd 		machine = job;
95561f28255Scgd 		*cp++ = '\0';
95661f28255Scgd 		job = cp;
95761f28255Scgd 	} else
95861f28255Scgd 		machine = NULL;
95961f28255Scgd 
96061f28255Scgd 	/*
96161f28255Scgd 	 * Check for job specified by number (example: 112 or 235ucbarpa).
96261f28255Scgd 	 */
96375ba9fc7Sdsl 	if (isdigit((unsigned char)*job)) {
96461f28255Scgd 		jobnum = 0;
96561f28255Scgd 		do
96661f28255Scgd 			jobnum = jobnum * 10 + (*job++ - '0');
96775ba9fc7Sdsl 		while (isdigit((unsigned char)*job));
96861f28255Scgd 		for (qq = queue + nitems; --qq >= queue; ) {
96961f28255Scgd 			n = 0;
97075ba9fc7Sdsl 			for (cp = (*qq)->q_name+3; isdigit((unsigned char)*cp); )
97161f28255Scgd 				n = n * 10 + (*cp++ - '0');
97261f28255Scgd 			if (jobnum != n)
97361f28255Scgd 				continue;
97461f28255Scgd 			if (*job && strcmp(job, cp) != 0)
97561f28255Scgd 				continue;
97661f28255Scgd 			if (machine != NULL && strcmp(machine, cp) != 0)
97761f28255Scgd 				continue;
97861f28255Scgd 			if (touch(*qq) == 0) {
97961f28255Scgd 				printf("\tmoved %s\n", (*qq)->q_name);
98061f28255Scgd 				cnt++;
98161f28255Scgd 			}
98261f28255Scgd 		}
98361f28255Scgd 		return(cnt);
98461f28255Scgd 	}
98561f28255Scgd 	/*
98661f28255Scgd 	 * Process item consisting of owner's name (example: henry).
98761f28255Scgd 	 */
98861f28255Scgd 	for (qq = queue + nitems; --qq >= queue; ) {
9898e41ca80Shpeyerl 		seteuid(euid);
9908e41ca80Shpeyerl 		fp = fopen((*qq)->q_name, "r");
9918e41ca80Shpeyerl 		seteuid(uid);
9928e41ca80Shpeyerl 		if (fp == NULL)
99361f28255Scgd 			continue;
9947027866aSroy 		while (get_line(fp) > 0)
99561f28255Scgd 			if (line[0] == 'P')
99661f28255Scgd 				break;
99761f28255Scgd 		(void)fclose(fp);
99861f28255Scgd 		if (line[0] != 'P' || strcmp(job, line+1) != 0)
99961f28255Scgd 			continue;
100061f28255Scgd 		if (touch(*qq) == 0) {
100161f28255Scgd 			printf("\tmoved %s\n", (*qq)->q_name);
100261f28255Scgd 			cnt++;
100361f28255Scgd 		}
100461f28255Scgd 	}
100561f28255Scgd 	return(cnt);
100661f28255Scgd }
100761f28255Scgd 
100861f28255Scgd /*
100961f28255Scgd  * Enable everything and start printer (undo `down').
101061f28255Scgd  */
1011f881d1d4Scgd void
up(int argc,char * argv[])1012895dc72aSwiz up(int argc, char *argv[])
101361f28255Scgd {
101404723c3fSchristos 	int c;
1015fe7ed7ceSmrg 	char *cp1, *cp2;
101661f28255Scgd 	char prbuf[100];
101761f28255Scgd 
101861f28255Scgd 	if (argc == 1) {
101961f28255Scgd 		printf("Usage: up {all | printer ...}\n");
102061f28255Scgd 		return;
102161f28255Scgd 	}
102261f28255Scgd 	if (argc == 2 && !strcmp(argv[1], "all")) {
102361f28255Scgd 		printer = prbuf;
1024f881d1d4Scgd 		while (cgetnext(&bp, printcapdb) > 0) {
102561f28255Scgd 			cp1 = prbuf;
1026f881d1d4Scgd 			cp2 = bp;
1027fe7ed7ceSmrg 			while ((c = *cp2++) && c != '|' && c != ':' &&
1028f5a433a7Slukem 			    (size_t)(cp1 - prbuf) < sizeof(prbuf))
102961f28255Scgd 				*cp1++ = c;
103061f28255Scgd 			*cp1 = '\0';
103161f28255Scgd 			startpr(2);
103261f28255Scgd 		}
103361f28255Scgd 		return;
103461f28255Scgd 	}
103561f28255Scgd 	while (--argc) {
103661f28255Scgd 		printer = *++argv;
103704723c3fSchristos 		if (!getcapdesc())
103861f28255Scgd 			continue;
103961f28255Scgd 		startpr(2);
104061f28255Scgd 	}
104161f28255Scgd }
1042