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