1*f4147939Sguenther /* $OpenBSD: cmds.c,v 1.28 2018/04/26 12:42:51 guenther Exp $ */
2a7643117Smillert /* $NetBSD: cmds.c,v 1.12 1997/10/05 15:12:06 mrg Exp $ */
3ca5d3c4eSmillert
4df930be7Sderaadt /*
5df930be7Sderaadt * Copyright (c) 1983, 1993
6df930be7Sderaadt * The Regents of the University of California. All rights reserved.
7df930be7Sderaadt *
8df930be7Sderaadt *
9df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
10df930be7Sderaadt * modification, are permitted provided that the following conditions
11df930be7Sderaadt * are met:
12df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
13df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
14df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
15df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
16df930be7Sderaadt * documentation and/or other materials provided with the distribution.
1729295d1cSmillert * 3. Neither the name of the University nor the names of its contributors
18df930be7Sderaadt * may be used to endorse or promote products derived from this software
19df930be7Sderaadt * without specific prior written permission.
20df930be7Sderaadt *
21df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31df930be7Sderaadt * SUCH DAMAGE.
32df930be7Sderaadt */
33df930be7Sderaadt
34df930be7Sderaadt /*
35df930be7Sderaadt * lpc -- line printer control program -- commands:
36df930be7Sderaadt */
37df930be7Sderaadt
38df930be7Sderaadt #include <sys/time.h>
39df930be7Sderaadt #include <sys/stat.h>
40df930be7Sderaadt
41df930be7Sderaadt #include <signal.h>
42df930be7Sderaadt #include <fcntl.h>
43df930be7Sderaadt #include <errno.h>
44df930be7Sderaadt #include <dirent.h>
45df930be7Sderaadt #include <unistd.h>
46b9fc9a72Sderaadt #include <limits.h>
47df930be7Sderaadt #include <stdlib.h>
48df930be7Sderaadt #include <stdio.h>
49df930be7Sderaadt #include <ctype.h>
50df930be7Sderaadt #include <string.h>
51df930be7Sderaadt #include "lp.h"
52df930be7Sderaadt #include "lp.local.h"
53df930be7Sderaadt #include "lpc.h"
54df930be7Sderaadt #include "extern.h"
55df930be7Sderaadt #include "pathnames.h"
56df930be7Sderaadt
57a7643117Smillert static void abortpr(int);
58a7643117Smillert static void cleanpr(void);
59a7643117Smillert static void disablepr(void);
60a7643117Smillert static int doarg(char *);
61a737da78Sguenther static int doselect(const struct dirent *);
62a7643117Smillert static void enablepr(void);
63a7643117Smillert static void prstat(void);
64a7643117Smillert static void putmsg(int, char **);
659142ec07Sguenther static int sortq(const struct dirent **, const struct dirent **);
66a7643117Smillert static void startpr(int);
67a7643117Smillert static void stoppr(void);
68a7643117Smillert static int touch(struct queue *);
69a7643117Smillert static void unlinkf(char *);
70a7643117Smillert static void upstat(char *);
71df930be7Sderaadt
72df930be7Sderaadt /*
73df930be7Sderaadt * kill an existing daemon and disable printing.
74df930be7Sderaadt */
75df930be7Sderaadt void
doabort(int argc,char ** argv)76a7643117Smillert doabort(int argc, char **argv)
77df930be7Sderaadt {
78c1624b2fSmillert int c, status;
79c1624b2fSmillert char *cp1, *cp2;
80df930be7Sderaadt char prbuf[100];
81df930be7Sderaadt
82df930be7Sderaadt if (argc == 1) {
831d8c2aacSsobrado printf("usage: abort {all | printer ...}\n");
84df930be7Sderaadt return;
85df930be7Sderaadt }
86a7643117Smillert if (argc == 2 && strcmp(argv[1], "all") == 0) {
87df930be7Sderaadt printer = prbuf;
88df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
89df930be7Sderaadt cp1 = prbuf;
90df930be7Sderaadt cp2 = bp;
917416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
92c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
93df930be7Sderaadt *cp1++ = c;
94df930be7Sderaadt *cp1 = '\0';
95df930be7Sderaadt abortpr(1);
96df930be7Sderaadt }
97df930be7Sderaadt return;
98df930be7Sderaadt }
99df930be7Sderaadt while (--argc) {
100df930be7Sderaadt printer = *++argv;
101df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
102df930be7Sderaadt printf("cannot open printer description file\n");
103df930be7Sderaadt continue;
104df930be7Sderaadt } else if (status == -1) {
105df930be7Sderaadt printf("unknown printer %s\n", printer);
106df930be7Sderaadt continue;
107df930be7Sderaadt } else if (status == -3)
108df930be7Sderaadt fatal("potential reference loop detected in printcap file");
109df930be7Sderaadt abortpr(1);
110df930be7Sderaadt }
111df930be7Sderaadt }
112df930be7Sderaadt
113a7643117Smillert static void
abortpr(int dis)114a7643117Smillert abortpr(int dis)
115df930be7Sderaadt {
116c1624b2fSmillert FILE *fp;
117df930be7Sderaadt struct stat stbuf;
118c9e7a8b4Sderaadt int pid, fd;
119df930be7Sderaadt
120df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
121df930be7Sderaadt SD = _PATH_DEFSPOOL;
122df930be7Sderaadt if (cgetstr(bp, "lo", &LO) == -1)
123df930be7Sderaadt LO = DEFLOCK;
1247416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
125df930be7Sderaadt printf("%s:\n", printer);
126df930be7Sderaadt
1276468ba68Smillert PRIV_START;
128df930be7Sderaadt /*
129df930be7Sderaadt * Turn on the owner execute bit of the lock file to disable printing.
130df930be7Sderaadt */
131df930be7Sderaadt if (dis) {
132df930be7Sderaadt if (stat(line, &stbuf) >= 0) {
1336468ba68Smillert stbuf.st_mode |= S_IXUSR;
1346468ba68Smillert if (chmod(line, stbuf.st_mode & 0777) < 0)
135df930be7Sderaadt printf("\tcannot disable printing\n");
136df930be7Sderaadt else {
137df930be7Sderaadt upstat("printing disabled\n");
138df930be7Sderaadt printf("\tprinting disabled\n");
139df930be7Sderaadt }
140df930be7Sderaadt } else if (errno == ENOENT) {
1416468ba68Smillert if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW,
1426468ba68Smillert 0760)) < 0)
143df930be7Sderaadt printf("\tcannot create lock file\n");
144df930be7Sderaadt else {
1456468ba68Smillert (void)fchown(fd, DEFUID, -1);
146df930be7Sderaadt (void)close(fd);
147df930be7Sderaadt upstat("printing disabled\n");
148df930be7Sderaadt printf("\tprinting disabled\n");
149df930be7Sderaadt printf("\tno daemon to abort\n");
150df930be7Sderaadt }
151df930be7Sderaadt goto out;
152df930be7Sderaadt } else {
153df930be7Sderaadt printf("\tcannot stat lock file\n");
154df930be7Sderaadt goto out;
155df930be7Sderaadt }
156df930be7Sderaadt }
157df930be7Sderaadt /*
158df930be7Sderaadt * Kill the current daemon to stop printing now.
159df930be7Sderaadt */
1606468ba68Smillert fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0);
1616468ba68Smillert if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) {
1626468ba68Smillert if (fd >= 0)
1636468ba68Smillert close(fd);
164df930be7Sderaadt printf("\tcannot open lock file\n");
165df930be7Sderaadt goto out;
166df930be7Sderaadt }
167f9bbbf45Sfgsch if (!get_line(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) {
168df930be7Sderaadt (void)fclose(fp); /* unlocks as well */
169df930be7Sderaadt printf("\tno daemon to abort\n");
170df930be7Sderaadt goto out;
171df930be7Sderaadt }
172df930be7Sderaadt (void)fclose(fp);
17320a848d0Smillert if (kill(pid = atoi(line), SIGTERM) < 0) {
17420a848d0Smillert if (errno == ESRCH)
17520a848d0Smillert printf("\tno daemon to abort\n");
176df930be7Sderaadt else
17720a848d0Smillert printf("\tWarning: daemon (pid %d) not killed\n", pid);
17820a848d0Smillert } else
179df930be7Sderaadt printf("\tdaemon (pid %d) killed\n", pid);
180df930be7Sderaadt out:
1816468ba68Smillert PRIV_END;
182df930be7Sderaadt }
183df930be7Sderaadt
184df930be7Sderaadt /*
1856468ba68Smillert * Write a message into the status file (assumes PRIV_START already called)
186df930be7Sderaadt */
187a7643117Smillert static void
upstat(char * msg)188a7643117Smillert upstat(char *msg)
189df930be7Sderaadt {
190c1624b2fSmillert int fd;
191b9fc9a72Sderaadt char statfile[PATH_MAX];
192df930be7Sderaadt
193df930be7Sderaadt if (cgetstr(bp, "st", &ST) == -1)
194df930be7Sderaadt ST = DEFSTAT;
1957416c11cSmillert (void)snprintf(statfile, sizeof(statfile), "%s/%s", SD, ST);
1966468ba68Smillert fd = safe_open(statfile, O_WRONLY|O_CREAT|O_NOFOLLOW, 0660);
197df930be7Sderaadt if (fd < 0 || flock(fd, LOCK_EX) < 0) {
198df930be7Sderaadt printf("\tcannot create status file\n");
19995cb4a2fSkrw if (fd >= 0)
20095cb4a2fSkrw (void)close(fd); /* unlocks as well */
201df930be7Sderaadt return;
202df930be7Sderaadt }
2036468ba68Smillert (void)fchown(fd, DEFUID, -1);
204df930be7Sderaadt (void)ftruncate(fd, 0);
205df930be7Sderaadt if (msg == (char *)NULL)
206df930be7Sderaadt (void)write(fd, "\n", 1);
207df930be7Sderaadt else
208df930be7Sderaadt (void)write(fd, msg, strlen(msg));
209df930be7Sderaadt (void)close(fd);
210df930be7Sderaadt }
211df930be7Sderaadt
212df930be7Sderaadt /*
213df930be7Sderaadt * Remove all spool files and temporaries from the spooling area.
214df930be7Sderaadt */
215df930be7Sderaadt void
clean(int argc,char ** argv)216a7643117Smillert clean(int argc, char **argv)
217df930be7Sderaadt {
218c1624b2fSmillert int c, status;
219c1624b2fSmillert char *cp1, *cp2;
220df930be7Sderaadt char prbuf[100];
221df930be7Sderaadt
222df930be7Sderaadt if (argc == 1) {
2231d8c2aacSsobrado printf("usage: clean {all | printer ...}\n");
224df930be7Sderaadt return;
225df930be7Sderaadt }
226a7643117Smillert if (argc == 2 && strcmp(argv[1], "all") == 0) {
227df930be7Sderaadt printer = prbuf;
228df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
229df930be7Sderaadt cp1 = prbuf;
230df930be7Sderaadt cp2 = bp;
2317416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
232c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
233df930be7Sderaadt *cp1++ = c;
234df930be7Sderaadt *cp1 = '\0';
235df930be7Sderaadt cleanpr();
236df930be7Sderaadt }
237df930be7Sderaadt return;
238df930be7Sderaadt }
239df930be7Sderaadt while (--argc) {
240df930be7Sderaadt printer = *++argv;
241df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
242df930be7Sderaadt printf("cannot open printer description file\n");
243df930be7Sderaadt continue;
244df930be7Sderaadt } else if (status == -1) {
245df930be7Sderaadt printf("unknown printer %s\n", printer);
246df930be7Sderaadt continue;
247df930be7Sderaadt } else if (status == -3)
248df930be7Sderaadt fatal("potential reference loop detected in printcap file");
249df930be7Sderaadt
250df930be7Sderaadt cleanpr();
251df930be7Sderaadt }
252df930be7Sderaadt }
253df930be7Sderaadt
254a7643117Smillert static int
doselect(const struct dirent * d)255a737da78Sguenther doselect(const struct dirent *d)
256df930be7Sderaadt {
257df930be7Sderaadt int c = d->d_name[0];
258df930be7Sderaadt
259df930be7Sderaadt if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f')
260df930be7Sderaadt return(1);
261df930be7Sderaadt return(0);
262df930be7Sderaadt }
263df930be7Sderaadt
264df930be7Sderaadt /*
265df930be7Sderaadt * Comparison routine for scandir. Sort by job number and machine, then
266df930be7Sderaadt * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z.
267df930be7Sderaadt */
268a7643117Smillert static int
sortq(const struct dirent ** d1,const struct dirent ** d2)2699142ec07Sguenther sortq(const struct dirent **d1, const struct dirent **d2)
270df930be7Sderaadt {
271df930be7Sderaadt int c1, c2;
272df930be7Sderaadt
273a7643117Smillert if ((c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) != 0)
274df930be7Sderaadt return(c1);
275df930be7Sderaadt c1 = (*d1)->d_name[0];
276df930be7Sderaadt c2 = (*d2)->d_name[0];
277df930be7Sderaadt if (c1 == c2)
278df930be7Sderaadt return((*d1)->d_name[2] - (*d2)->d_name[2]);
279df930be7Sderaadt if (c1 == 'c')
280df930be7Sderaadt return(-1);
281df930be7Sderaadt if (c1 == 'd' || c2 == 'c')
282df930be7Sderaadt return(1);
283df930be7Sderaadt return(-1);
284df930be7Sderaadt }
285df930be7Sderaadt
286df930be7Sderaadt /*
287df930be7Sderaadt * Remove incomplete jobs from spooling area.
288df930be7Sderaadt */
289a7643117Smillert static void
cleanpr(void)290a7643117Smillert cleanpr(void)
291df930be7Sderaadt {
292c1624b2fSmillert int i, n;
293c1624b2fSmillert char *cp, *cp1, *lp;
294df930be7Sderaadt struct dirent **queue;
295df930be7Sderaadt int nitems;
296df930be7Sderaadt
297df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
298df930be7Sderaadt SD = _PATH_DEFSPOOL;
299df930be7Sderaadt printf("%s:\n", printer);
300df930be7Sderaadt
301a7643117Smillert /* XXX depends on SD being non-NUL */
302a7643117Smillert for (lp = line, cp = SD; (lp - line) < sizeof(line) &&
303a7643117Smillert (*lp++ = *cp++) != '\0'; )
304df930be7Sderaadt ;
305df930be7Sderaadt lp[-1] = '/';
30673a94c6dSpjanzen if (lp - line >= sizeof(line)) {
30773a94c6dSpjanzen printf("\tspool directory name too long\n");
30873a94c6dSpjanzen return;
30973a94c6dSpjanzen }
310df930be7Sderaadt
3116468ba68Smillert PRIV_START;
312df930be7Sderaadt nitems = scandir(SD, &queue, doselect, sortq);
3136468ba68Smillert PRIV_END;
314df930be7Sderaadt if (nitems < 0) {
315df930be7Sderaadt printf("\tcannot examine spool directory\n");
316df930be7Sderaadt return;
317df930be7Sderaadt }
318df930be7Sderaadt if (nitems == 0)
319df930be7Sderaadt return;
320df930be7Sderaadt i = 0;
321df930be7Sderaadt do {
322df930be7Sderaadt cp = queue[i]->d_name;
323df930be7Sderaadt if (*cp == 'c') {
324df930be7Sderaadt n = 0;
325df930be7Sderaadt while (i + 1 < nitems) {
326df930be7Sderaadt cp1 = queue[i + 1]->d_name;
327df930be7Sderaadt if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3))
328df930be7Sderaadt break;
329df930be7Sderaadt i++;
330df930be7Sderaadt n++;
331df930be7Sderaadt }
332df930be7Sderaadt if (n == 0) {
333a7643117Smillert if (strlcpy(lp, cp, sizeof(line) - (lp - line))
334a7643117Smillert >= sizeof(line) - (lp - line))
33573a94c6dSpjanzen printf("\tpath too long, %s/%s", SD, cp);
33673a94c6dSpjanzen else
337df930be7Sderaadt unlinkf(line);
338df930be7Sderaadt }
339df930be7Sderaadt } else {
340df930be7Sderaadt /*
341df930be7Sderaadt * Must be a df with no cf (otherwise, it would have
342df930be7Sderaadt * been skipped above) or a tf file (which can always
343df930be7Sderaadt * be removed).
344df930be7Sderaadt */
34573a94c6dSpjanzen if (strlcpy(lp, cp, sizeof(line) - (lp - line)) >=
34673a94c6dSpjanzen sizeof(line) - (lp - line))
34773a94c6dSpjanzen printf("\tpath too long, %s/%s", SD, cp);
34873a94c6dSpjanzen else
349df930be7Sderaadt unlinkf(line);
350df930be7Sderaadt }
351df930be7Sderaadt } while (++i < nitems);
352df930be7Sderaadt }
353df930be7Sderaadt
354a7643117Smillert static void
unlinkf(char * name)355a7643117Smillert unlinkf(char *name)
356df930be7Sderaadt {
3576468ba68Smillert PRIV_START;
358df930be7Sderaadt if (unlink(name) < 0)
359df930be7Sderaadt printf("\tcannot remove %s\n", name);
360df930be7Sderaadt else
361df930be7Sderaadt printf("\tremoved %s\n", name);
3626468ba68Smillert PRIV_END;
363df930be7Sderaadt }
364df930be7Sderaadt
365df930be7Sderaadt /*
366df930be7Sderaadt * Enable queuing to the printer (allow lpr's).
367df930be7Sderaadt */
368df930be7Sderaadt void
enable(int argc,char ** argv)369a7643117Smillert enable(int argc, char **argv)
370df930be7Sderaadt {
371c1624b2fSmillert int c, status;
372c1624b2fSmillert char *cp1, *cp2;
373df930be7Sderaadt char prbuf[100];
374df930be7Sderaadt
375df930be7Sderaadt if (argc == 1) {
3761d8c2aacSsobrado printf("usage: enable {all | printer ...}\n");
377df930be7Sderaadt return;
378df930be7Sderaadt }
379a7643117Smillert if (argc == 2 && strcmp(argv[1], "all") == 0) {
380df930be7Sderaadt printer = prbuf;
381df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
382df930be7Sderaadt cp1 = prbuf;
383df930be7Sderaadt cp2 = bp;
3847416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
385c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
386df930be7Sderaadt *cp1++ = c;
387df930be7Sderaadt *cp1 = '\0';
388df930be7Sderaadt enablepr();
389df930be7Sderaadt }
390df930be7Sderaadt return;
391df930be7Sderaadt }
392df930be7Sderaadt while (--argc) {
393df930be7Sderaadt printer = *++argv;
394df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
395df930be7Sderaadt printf("cannot open printer description file\n");
396df930be7Sderaadt continue;
397df930be7Sderaadt } else if (status == -1) {
398df930be7Sderaadt printf("unknown printer %s\n", printer);
399df930be7Sderaadt continue;
400df930be7Sderaadt } else if (status == -3)
401df930be7Sderaadt fatal("potential reference loop detected in printcap file");
402df930be7Sderaadt
403df930be7Sderaadt enablepr();
404df930be7Sderaadt }
405df930be7Sderaadt }
406df930be7Sderaadt
407a7643117Smillert static void
enablepr(void)408a7643117Smillert enablepr(void)
409df930be7Sderaadt {
410df930be7Sderaadt struct stat stbuf;
411df930be7Sderaadt
412df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
413df930be7Sderaadt SD = _PATH_DEFSPOOL;
414df930be7Sderaadt if (cgetstr(bp, "lo", &LO) == -1)
415df930be7Sderaadt LO = DEFLOCK;
4167416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
417df930be7Sderaadt printf("%s:\n", printer);
418df930be7Sderaadt
419df930be7Sderaadt /*
420df930be7Sderaadt * Turn off the group execute bit of the lock file to enable queuing.
421df930be7Sderaadt */
4226468ba68Smillert PRIV_START;
423df930be7Sderaadt if (stat(line, &stbuf) >= 0) {
4246468ba68Smillert stbuf.st_mode &= ~S_IXGRP;
4256468ba68Smillert if (chmod(line, stbuf.st_mode & 0777) < 0)
426df930be7Sderaadt printf("\tcannot enable queuing\n");
427df930be7Sderaadt else
428df930be7Sderaadt printf("\tqueuing enabled\n");
429df930be7Sderaadt }
4306468ba68Smillert PRIV_END;
431df930be7Sderaadt }
432df930be7Sderaadt
433df930be7Sderaadt /*
434df930be7Sderaadt * Disable queuing.
435df930be7Sderaadt */
436df930be7Sderaadt void
disable(int argc,char ** argv)437a7643117Smillert disable(int argc, char **argv)
438df930be7Sderaadt {
439c1624b2fSmillert int c, status;
440c1624b2fSmillert char *cp1, *cp2;
441df930be7Sderaadt char prbuf[100];
442df930be7Sderaadt
443df930be7Sderaadt if (argc == 1) {
4441d8c2aacSsobrado printf("usage: disable {all | printer ...}\n");
445df930be7Sderaadt return;
446df930be7Sderaadt }
447a7643117Smillert if (argc == 2 && strcmp(argv[1], "all") == 0) {
448df930be7Sderaadt printer = prbuf;
449df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
450df930be7Sderaadt cp1 = prbuf;
451df930be7Sderaadt cp2 = bp;
4527416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
453c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
454df930be7Sderaadt *cp1++ = c;
455df930be7Sderaadt *cp1 = '\0';
456df930be7Sderaadt disablepr();
457df930be7Sderaadt }
458df930be7Sderaadt return;
459df930be7Sderaadt }
460df930be7Sderaadt while (--argc) {
461df930be7Sderaadt printer = *++argv;
462df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
463df930be7Sderaadt printf("cannot open printer description file\n");
464df930be7Sderaadt continue;
465df930be7Sderaadt } else if (status == -1) {
466df930be7Sderaadt printf("unknown printer %s\n", printer);
467df930be7Sderaadt continue;
468df930be7Sderaadt } else if (status == -3)
469df930be7Sderaadt fatal("potential reference loop detected in printcap file");
470df930be7Sderaadt
471df930be7Sderaadt disablepr();
472df930be7Sderaadt }
473df930be7Sderaadt }
474df930be7Sderaadt
475a7643117Smillert static void
disablepr(void)476a7643117Smillert disablepr(void)
477df930be7Sderaadt {
478c1624b2fSmillert int fd;
479df930be7Sderaadt struct stat stbuf;
480df930be7Sderaadt
481df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
482df930be7Sderaadt SD = _PATH_DEFSPOOL;
483df930be7Sderaadt if (cgetstr(bp, "lo", &LO) == -1)
484df930be7Sderaadt LO = DEFLOCK;
4857416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
486df930be7Sderaadt printf("%s:\n", printer);
487df930be7Sderaadt /*
488df930be7Sderaadt * Turn on the group execute bit of the lock file to disable queuing.
489df930be7Sderaadt */
4906468ba68Smillert PRIV_START;
491df930be7Sderaadt if (stat(line, &stbuf) >= 0) {
4926468ba68Smillert stbuf.st_mode |= S_IXGRP;
4936468ba68Smillert if (chmod(line, stbuf.st_mode & 0777) < 0)
494df930be7Sderaadt printf("\tcannot disable queuing\n");
495df930be7Sderaadt else
496df930be7Sderaadt printf("\tqueuing disabled\n");
497df930be7Sderaadt } else if (errno == ENOENT) {
4986468ba68Smillert if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0670)) < 0)
499df930be7Sderaadt printf("\tcannot create lock file\n");
500df930be7Sderaadt else {
5016468ba68Smillert (void)fchown(fd, DEFUID, -1);
502df930be7Sderaadt (void)close(fd);
503df930be7Sderaadt printf("\tqueuing disabled\n");
504df930be7Sderaadt }
505df930be7Sderaadt } else
506df930be7Sderaadt printf("\tcannot stat lock file\n");
5076468ba68Smillert PRIV_END;
508df930be7Sderaadt }
509df930be7Sderaadt
510df930be7Sderaadt /*
511df930be7Sderaadt * Disable queuing and printing and put a message into the status file
512df930be7Sderaadt * (reason for being down).
513df930be7Sderaadt */
514df930be7Sderaadt void
down(int argc,char ** argv)515a7643117Smillert down(int argc, char **argv)
516df930be7Sderaadt {
517c1624b2fSmillert int c, status;
518c1624b2fSmillert char *cp1, *cp2;
519df930be7Sderaadt char prbuf[100];
520df930be7Sderaadt
521df930be7Sderaadt if (argc == 1) {
5221d8c2aacSsobrado printf("usage: down {all | printer} [message ...]\n");
523df930be7Sderaadt return;
524df930be7Sderaadt }
525a7643117Smillert if (strcmp(argv[1], "all") == 0) {
526df930be7Sderaadt printer = prbuf;
527df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
528df930be7Sderaadt cp1 = prbuf;
529df930be7Sderaadt cp2 = bp;
5307416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
531c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
532df930be7Sderaadt *cp1++ = c;
533df930be7Sderaadt *cp1 = '\0';
534df930be7Sderaadt putmsg(argc - 2, argv + 2);
535df930be7Sderaadt }
536df930be7Sderaadt return;
537df930be7Sderaadt }
538df930be7Sderaadt printer = argv[1];
539df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
540df930be7Sderaadt printf("cannot open printer description file\n");
541df930be7Sderaadt return;
542df930be7Sderaadt } else if (status == -1) {
543df930be7Sderaadt printf("unknown printer %s\n", printer);
544df930be7Sderaadt return;
545df930be7Sderaadt } else if (status == -3)
546df930be7Sderaadt fatal("potential reference loop detected in printcap file");
547df930be7Sderaadt
548df930be7Sderaadt putmsg(argc - 2, argv + 2);
549df930be7Sderaadt }
550df930be7Sderaadt
551a7643117Smillert static void
putmsg(int argc,char ** argv)552a7643117Smillert putmsg(int argc, char **argv)
553df930be7Sderaadt {
554c1624b2fSmillert int fd;
555c1624b2fSmillert char *cp1, *cp2;
556df930be7Sderaadt char buf[1024];
557df930be7Sderaadt struct stat stbuf;
558df930be7Sderaadt
559df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
560df930be7Sderaadt SD = _PATH_DEFSPOOL;
561df930be7Sderaadt if (cgetstr(bp, "lo", &LO) == -1)
562df930be7Sderaadt LO = DEFLOCK;
563df930be7Sderaadt if (cgetstr(bp, "st", &ST) == -1)
564df930be7Sderaadt ST = DEFSTAT;
565df930be7Sderaadt printf("%s:\n", printer);
566df930be7Sderaadt /*
567df930be7Sderaadt * Turn on the group execute bit of the lock file to disable queuing and
568df930be7Sderaadt * turn on the owner execute bit of the lock file to disable printing.
569df930be7Sderaadt */
5707416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
5716468ba68Smillert PRIV_START;
572df930be7Sderaadt if (stat(line, &stbuf) >= 0) {
5736468ba68Smillert stbuf.st_mode |= (S_IXGRP|S_IXUSR);
5746468ba68Smillert if (chmod(line, stbuf.st_mode & 0777) < 0)
575df930be7Sderaadt printf("\tcannot disable queuing\n");
576df930be7Sderaadt else
577df930be7Sderaadt printf("\tprinter and queuing disabled\n");
578df930be7Sderaadt } else if (errno == ENOENT) {
5796468ba68Smillert if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0770)) < 0)
580df930be7Sderaadt printf("\tcannot create lock file\n");
581df930be7Sderaadt else {
5826468ba68Smillert (void)fchown(fd, DEFUID, -1);
583df930be7Sderaadt (void)close(fd);
584df930be7Sderaadt printf("\tprinter and queuing disabled\n");
585df930be7Sderaadt }
5866468ba68Smillert PRIV_END;
587df930be7Sderaadt return;
588df930be7Sderaadt } else
589df930be7Sderaadt printf("\tcannot stat lock file\n");
590df930be7Sderaadt /*
591df930be7Sderaadt * Write the message into the status file.
592df930be7Sderaadt */
5937416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, ST);
5946468ba68Smillert fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0660);
595df930be7Sderaadt if (fd < 0 || flock(fd, LOCK_EX) < 0) {
596df930be7Sderaadt printf("\tcannot create status file\n");
59795cb4a2fSkrw if (fd >= 0)
59895cb4a2fSkrw (void)close(fd); /* unlocks as well */
5996468ba68Smillert PRIV_END;
600df930be7Sderaadt return;
601df930be7Sderaadt }
6026468ba68Smillert PRIV_END;
6036468ba68Smillert (void)fchown(fd, DEFUID, -1);
604df930be7Sderaadt (void)ftruncate(fd, 0);
605df930be7Sderaadt if (argc <= 0) {
606df930be7Sderaadt (void)write(fd, "\n", 1);
607df930be7Sderaadt (void)close(fd);
608df930be7Sderaadt return;
609df930be7Sderaadt }
610df930be7Sderaadt cp1 = buf;
611df930be7Sderaadt while (--argc >= 0) {
612df930be7Sderaadt cp2 = *argv++;
613c9e7d913Spjanzen while ((cp1 - buf) < sizeof(buf) - 1 && (*cp1++ = *cp2++))
614df930be7Sderaadt ;
615df930be7Sderaadt cp1[-1] = ' ';
616df930be7Sderaadt }
617df930be7Sderaadt cp1[-1] = '\n';
618df930be7Sderaadt *cp1 = '\0';
619df930be7Sderaadt (void)write(fd, buf, strlen(buf));
620df930be7Sderaadt (void)close(fd);
621df930be7Sderaadt }
622df930be7Sderaadt
623df930be7Sderaadt /*
624df930be7Sderaadt * Exit lpc
625df930be7Sderaadt */
626df930be7Sderaadt void
quit(int argc,char ** argv)627a7643117Smillert quit(int argc, char **argv)
628df930be7Sderaadt {
629df930be7Sderaadt exit(0);
630df930be7Sderaadt }
631df930be7Sderaadt
632df930be7Sderaadt /*
633df930be7Sderaadt * Kill and restart the daemon.
634df930be7Sderaadt */
635df930be7Sderaadt void
restart(int argc,char ** argv)636a7643117Smillert restart(int argc, char **argv)
637df930be7Sderaadt {
638c1624b2fSmillert int c, status;
639c1624b2fSmillert char *cp1, *cp2;
640df930be7Sderaadt char prbuf[100];
641df930be7Sderaadt
642df930be7Sderaadt if (argc == 1) {
6431d8c2aacSsobrado printf("usage: restart {all | printer ...}\n");
644df930be7Sderaadt return;
645df930be7Sderaadt }
646a7643117Smillert if (argc == 2 && strcmp(argv[1], "all") == 0) {
647df930be7Sderaadt printer = prbuf;
648df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
649df930be7Sderaadt cp1 = prbuf;
650df930be7Sderaadt cp2 = bp;
6517416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
652c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
653df930be7Sderaadt *cp1++ = c;
654df930be7Sderaadt *cp1 = '\0';
655df930be7Sderaadt abortpr(0);
656df930be7Sderaadt startpr(0);
657df930be7Sderaadt }
658df930be7Sderaadt return;
659df930be7Sderaadt }
660df930be7Sderaadt while (--argc) {
661df930be7Sderaadt printer = *++argv;
662df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
663df930be7Sderaadt printf("cannot open printer description file\n");
664df930be7Sderaadt continue;
665df930be7Sderaadt } else if (status == -1) {
666df930be7Sderaadt printf("unknown printer %s\n", printer);
667df930be7Sderaadt continue;
668df930be7Sderaadt } else if (status == -3)
669df930be7Sderaadt fatal("potential reference loop detected in printcap file");
670df930be7Sderaadt
671df930be7Sderaadt abortpr(0);
672df930be7Sderaadt startpr(0);
673df930be7Sderaadt }
674df930be7Sderaadt }
675df930be7Sderaadt
676df930be7Sderaadt /*
677df930be7Sderaadt * Enable printing on the specified printer and startup the daemon.
678df930be7Sderaadt */
679df930be7Sderaadt void
startcmd(int argc,char ** argv)680a7643117Smillert startcmd(int argc, char **argv)
681df930be7Sderaadt {
682c1624b2fSmillert int c, status;
683c1624b2fSmillert char *cp1, *cp2;
684df930be7Sderaadt char prbuf[100];
685df930be7Sderaadt
686df930be7Sderaadt if (argc == 1) {
6871d8c2aacSsobrado printf("usage: start {all | printer ...}\n");
688df930be7Sderaadt return;
689df930be7Sderaadt }
690a7643117Smillert if (argc == 2 && strcmp(argv[1], "all") == 0) {
691df930be7Sderaadt printer = prbuf;
692df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
693df930be7Sderaadt cp1 = prbuf;
694df930be7Sderaadt cp2 = bp;
6957416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
696c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
697df930be7Sderaadt *cp1++ = c;
698df930be7Sderaadt *cp1 = '\0';
699df930be7Sderaadt startpr(1);
700df930be7Sderaadt }
701df930be7Sderaadt return;
702df930be7Sderaadt }
703df930be7Sderaadt while (--argc) {
704df930be7Sderaadt printer = *++argv;
705df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
706df930be7Sderaadt printf("cannot open printer description file\n");
707df930be7Sderaadt continue;
708df930be7Sderaadt } else if (status == -1) {
709df930be7Sderaadt printf("unknown printer %s\n", printer);
710df930be7Sderaadt continue;
711df930be7Sderaadt } else if (status == -3)
712df930be7Sderaadt fatal("potential reference loop detected in printcap file");
713df930be7Sderaadt
714df930be7Sderaadt startpr(1);
715df930be7Sderaadt }
716df930be7Sderaadt }
717df930be7Sderaadt
718a7643117Smillert static void
startpr(int enable)719a7643117Smillert startpr(int enable)
720df930be7Sderaadt {
721df930be7Sderaadt struct stat stbuf;
722df930be7Sderaadt
723df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
724df930be7Sderaadt SD = _PATH_DEFSPOOL;
725df930be7Sderaadt if (cgetstr(bp, "lo", &LO) == -1)
726df930be7Sderaadt LO = DEFLOCK;
7277416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
728df930be7Sderaadt printf("%s:\n", printer);
729df930be7Sderaadt
730df930be7Sderaadt /*
731df930be7Sderaadt * Turn off the owner execute bit of the lock file to enable printing.
7326468ba68Smillert * If we are marking the printer "up" also turn off group execute bit.
733df930be7Sderaadt */
7346468ba68Smillert PRIV_START;
735df930be7Sderaadt if (enable && stat(line, &stbuf) >= 0) {
7366468ba68Smillert if (enable == 2)
7376468ba68Smillert stbuf.st_mode &= ~(S_IXUSR|S_IXGRP);
7386468ba68Smillert else
7396468ba68Smillert stbuf.st_mode &= ~S_IXUSR;
7406468ba68Smillert if (chmod(line, stbuf.st_mode & 0777) < 0)
741df930be7Sderaadt printf("\tcannot enable printing\n");
742df930be7Sderaadt else
743df930be7Sderaadt printf("\tprinting enabled\n");
744df930be7Sderaadt }
7456468ba68Smillert PRIV_END;
746df930be7Sderaadt if (!startdaemon(printer))
747df930be7Sderaadt printf("\tcouldn't start daemon\n");
748df930be7Sderaadt else
749df930be7Sderaadt printf("\tdaemon started\n");
750df930be7Sderaadt }
751df930be7Sderaadt
752df930be7Sderaadt /*
753df930be7Sderaadt * Print the status of each queue listed or all the queues.
754df930be7Sderaadt */
755df930be7Sderaadt void
status(int argc,char ** argv)756a7643117Smillert status(int argc, char **argv)
757df930be7Sderaadt {
758c1624b2fSmillert int c, status;
759c1624b2fSmillert char *cp1, *cp2;
760df930be7Sderaadt char prbuf[100];
761df930be7Sderaadt
762a7643117Smillert if (argc == 1 || (argc == 2 && strcmp(argv[1], "all") == 0)) {
763df930be7Sderaadt printer = prbuf;
764df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
765df930be7Sderaadt cp1 = prbuf;
766df930be7Sderaadt cp2 = bp;
7677416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
768c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
769df930be7Sderaadt *cp1++ = c;
770df930be7Sderaadt *cp1 = '\0';
771df930be7Sderaadt prstat();
772df930be7Sderaadt }
773df930be7Sderaadt return;
774df930be7Sderaadt }
775df930be7Sderaadt while (--argc) {
776df930be7Sderaadt printer = *++argv;
777df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
778df930be7Sderaadt printf("cannot open printer description file\n");
779df930be7Sderaadt continue;
780df930be7Sderaadt } else if (status == -1) {
781df930be7Sderaadt printf("unknown printer %s\n", printer);
782df930be7Sderaadt continue;
783df930be7Sderaadt } else if (status == -3)
784df930be7Sderaadt fatal("potential reference loop detected in printcap file");
785df930be7Sderaadt
786df930be7Sderaadt prstat();
787df930be7Sderaadt }
788df930be7Sderaadt }
789df930be7Sderaadt
790df930be7Sderaadt /*
791df930be7Sderaadt * Print the status of the printer queue.
792df930be7Sderaadt */
793a7643117Smillert static void
prstat(void)794a7643117Smillert prstat(void)
795df930be7Sderaadt {
796df930be7Sderaadt struct stat stbuf;
797c1624b2fSmillert int fd, i;
798c1624b2fSmillert struct dirent *dp;
799df930be7Sderaadt DIR *dirp;
800df930be7Sderaadt
801df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
802df930be7Sderaadt SD = _PATH_DEFSPOOL;
803df930be7Sderaadt if (cgetstr(bp, "lo", &LO) == -1)
804df930be7Sderaadt LO = DEFLOCK;
805df930be7Sderaadt if (cgetstr(bp, "st", &ST) == -1)
806df930be7Sderaadt ST = DEFSTAT;
807df930be7Sderaadt printf("%s:\n", printer);
8087416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
8096468ba68Smillert PRIV_START;
8106468ba68Smillert i = stat(line, &stbuf);
8116468ba68Smillert PRIV_END;
8126468ba68Smillert if (i >= 0) {
813df930be7Sderaadt printf("\tqueuing is %s\n",
814df930be7Sderaadt (stbuf.st_mode & 010) ? "disabled" : "enabled");
815df930be7Sderaadt printf("\tprinting is %s\n",
816df930be7Sderaadt (stbuf.st_mode & 0100) ? "disabled" : "enabled");
817df930be7Sderaadt } else {
818df930be7Sderaadt printf("\tqueuing is enabled\n");
819df930be7Sderaadt printf("\tprinting is enabled\n");
820df930be7Sderaadt }
8216468ba68Smillert PRIV_START;
8226468ba68Smillert dirp = opendir(SD);
8236468ba68Smillert PRIV_END;
8246468ba68Smillert if (dirp == NULL) {
825df930be7Sderaadt printf("\tcannot examine spool directory\n");
826df930be7Sderaadt return;
827df930be7Sderaadt }
828df930be7Sderaadt i = 0;
829df930be7Sderaadt while ((dp = readdir(dirp)) != NULL) {
830df930be7Sderaadt if (*dp->d_name == 'c' && dp->d_name[1] == 'f')
831df930be7Sderaadt i++;
832df930be7Sderaadt }
833df930be7Sderaadt closedir(dirp);
834df930be7Sderaadt if (i == 0)
835df930be7Sderaadt printf("\tno entries\n");
836df930be7Sderaadt else if (i == 1)
837df930be7Sderaadt printf("\t1 entry in spool area\n");
838df930be7Sderaadt else
839df930be7Sderaadt printf("\t%d entries in spool area\n", i);
8406468ba68Smillert PRIV_START;
8416468ba68Smillert fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0);
8426468ba68Smillert PRIV_END;
843df930be7Sderaadt if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) {
8448d476b29Sderaadt printf("\tprinter idle\n");
84595cb4a2fSkrw if (fd >= 0)
84695cb4a2fSkrw (void)close(fd); /* unlocks as well */
847df930be7Sderaadt return;
848df930be7Sderaadt }
849df930be7Sderaadt (void)close(fd);
8507416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, ST);
8516468ba68Smillert PRIV_START;
8526468ba68Smillert fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0);
8536468ba68Smillert PRIV_END;
854df930be7Sderaadt if (fd >= 0) {
855df930be7Sderaadt (void)flock(fd, LOCK_SH);
856a7643117Smillert if (fstat(fd, &stbuf) == 0 && stbuf.st_size > 0) {
857a7643117Smillert putchar('\t');
858df930be7Sderaadt while ((i = read(fd, line, sizeof(line))) > 0)
859df930be7Sderaadt (void)fwrite(line, 1, i, stdout);
860a7643117Smillert }
861df930be7Sderaadt (void)close(fd); /* unlocks as well */
862df930be7Sderaadt }
863df930be7Sderaadt }
864df930be7Sderaadt
865df930be7Sderaadt /*
866df930be7Sderaadt * Stop the specified daemon after completing the current job and disable
867df930be7Sderaadt * printing.
868df930be7Sderaadt */
869df930be7Sderaadt void
stop(int argc,char ** argv)870a7643117Smillert stop(int argc, char **argv)
871df930be7Sderaadt {
872c1624b2fSmillert int c, status;
873c1624b2fSmillert char *cp1, *cp2;
874df930be7Sderaadt char prbuf[100];
875df930be7Sderaadt
876df930be7Sderaadt if (argc == 1) {
8771d8c2aacSsobrado printf("usage: stop {all | printer ...}\n");
878df930be7Sderaadt return;
879df930be7Sderaadt }
880a7643117Smillert if (argc == 2 && strcmp(argv[1], "all") == 0) {
881df930be7Sderaadt printer = prbuf;
882df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
883df930be7Sderaadt cp1 = prbuf;
884df930be7Sderaadt cp2 = bp;
8857416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
886c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
887df930be7Sderaadt *cp1++ = c;
888df930be7Sderaadt *cp1 = '\0';
889df930be7Sderaadt stoppr();
890df930be7Sderaadt }
891df930be7Sderaadt return;
892df930be7Sderaadt }
893df930be7Sderaadt while (--argc) {
894df930be7Sderaadt printer = *++argv;
895df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
896df930be7Sderaadt printf("cannot open printer description file\n");
897df930be7Sderaadt continue;
898df930be7Sderaadt } else if (status == -1) {
899df930be7Sderaadt printf("unknown printer %s\n", printer);
900df930be7Sderaadt continue;
901df930be7Sderaadt } else if (status == -3)
902df930be7Sderaadt fatal("potential reference loop detected in printcap file");
903df930be7Sderaadt
904df930be7Sderaadt stoppr();
905df930be7Sderaadt }
906df930be7Sderaadt }
907df930be7Sderaadt
908a7643117Smillert static void
stoppr(void)909a7643117Smillert stoppr(void)
910df930be7Sderaadt {
911c1624b2fSmillert int fd;
912df930be7Sderaadt struct stat stbuf;
913df930be7Sderaadt
914df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
915df930be7Sderaadt SD = _PATH_DEFSPOOL;
916df930be7Sderaadt if (cgetstr(bp, "lo", &LO) == -1)
917df930be7Sderaadt LO = DEFLOCK;
9187416c11cSmillert (void)snprintf(line, sizeof(line), "%s/%s", SD, LO);
919df930be7Sderaadt printf("%s:\n", printer);
920df930be7Sderaadt
921df930be7Sderaadt /*
922df930be7Sderaadt * Turn on the owner execute bit of the lock file to disable printing.
923df930be7Sderaadt */
9246468ba68Smillert PRIV_START;
925df930be7Sderaadt if (stat(line, &stbuf) >= 0) {
9266468ba68Smillert stbuf.st_mode |= S_IXUSR;
9276468ba68Smillert if (chmod(line, stbuf.st_mode & 0777) < 0)
928df930be7Sderaadt printf("\tcannot disable printing\n");
929df930be7Sderaadt else {
930df930be7Sderaadt upstat("printing disabled\n");
931df930be7Sderaadt printf("\tprinting disabled\n");
932df930be7Sderaadt }
933df930be7Sderaadt } else if (errno == ENOENT) {
9346468ba68Smillert if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0760)) < 0)
935df930be7Sderaadt printf("\tcannot create lock file\n");
936df930be7Sderaadt else {
9376468ba68Smillert (void)fchown(fd, DEFUID, -1);
938df930be7Sderaadt (void)close(fd);
939df930be7Sderaadt upstat("printing disabled\n");
940df930be7Sderaadt printf("\tprinting disabled\n");
941df930be7Sderaadt }
942df930be7Sderaadt } else
943df930be7Sderaadt printf("\tcannot stat lock file\n");
9446468ba68Smillert PRIV_END;
945df930be7Sderaadt }
946df930be7Sderaadt
947df930be7Sderaadt struct queue **queue;
948df930be7Sderaadt int nitems;
949df930be7Sderaadt time_t mtime;
950df930be7Sderaadt
951df930be7Sderaadt /*
952df930be7Sderaadt * Put the specified jobs at the top of printer queue.
953df930be7Sderaadt */
954df930be7Sderaadt void
topq(int argc,char ** argv)955a7643117Smillert topq(int argc, char **argv)
956df930be7Sderaadt {
957c1624b2fSmillert int i;
958df930be7Sderaadt struct stat stbuf;
959df930be7Sderaadt int status, changed;
960df930be7Sderaadt
961df930be7Sderaadt if (argc < 3) {
9621d8c2aacSsobrado printf("usage: topq printer [jobnum ...] [user ...]\n");
963df930be7Sderaadt return;
964df930be7Sderaadt }
965df930be7Sderaadt
966df930be7Sderaadt --argc;
967df930be7Sderaadt printer = *++argv;
968df930be7Sderaadt status = cgetent(&bp, printcapdb, printer);
969df930be7Sderaadt if (status == -2) {
970df930be7Sderaadt printf("cannot open printer description file\n");
971df930be7Sderaadt return;
972df930be7Sderaadt } else if (status == -1) {
973df930be7Sderaadt printf("%s: unknown printer\n", printer);
974df930be7Sderaadt return;
975df930be7Sderaadt } else if (status == -3)
976df930be7Sderaadt fatal("potential reference loop detected in printcap file");
977df930be7Sderaadt
978df930be7Sderaadt if (cgetstr(bp, "sd", &SD) == -1)
979df930be7Sderaadt SD = _PATH_DEFSPOOL;
980df930be7Sderaadt if (cgetstr(bp, "lo", &LO) == -1)
981df930be7Sderaadt LO = DEFLOCK;
982df930be7Sderaadt printf("%s:\n", printer);
983df930be7Sderaadt
9846468ba68Smillert PRIV_START;
985df930be7Sderaadt if (chdir(SD) < 0) {
986df930be7Sderaadt printf("\tcannot chdir to %s\n", SD);
987df930be7Sderaadt goto out;
988df930be7Sderaadt }
9896468ba68Smillert PRIV_END;
990df930be7Sderaadt nitems = getq(&queue);
991df930be7Sderaadt if (nitems == 0)
992df930be7Sderaadt return;
993df930be7Sderaadt changed = 0;
994df930be7Sderaadt mtime = queue[0]->q_time;
995df930be7Sderaadt for (i = argc; --i; ) {
996df930be7Sderaadt if (doarg(argv[i]) == 0) {
997df930be7Sderaadt printf("\tjob %s is not in the queue\n", argv[i]);
998df930be7Sderaadt continue;
999df930be7Sderaadt } else
1000df930be7Sderaadt changed++;
1001df930be7Sderaadt }
1002df930be7Sderaadt for (i = 0; i < nitems; i++)
1003df930be7Sderaadt free(queue[i]);
1004df930be7Sderaadt free(queue);
1005df930be7Sderaadt if (!changed) {
1006df930be7Sderaadt printf("\tqueue order unchanged\n");
1007df930be7Sderaadt return;
1008df930be7Sderaadt }
1009df930be7Sderaadt /*
1010df930be7Sderaadt * Turn on the public execute bit of the lock file to
1011df930be7Sderaadt * get lpd to rebuild the queue after the current job.
1012df930be7Sderaadt */
10136468ba68Smillert PRIV_START;
10146468ba68Smillert if (changed && stat(LO, &stbuf) >= 0) {
10156468ba68Smillert stbuf.st_mode |= S_IXOTH;
10166468ba68Smillert (void)chmod(LO, stbuf.st_mode & 0777);
10176468ba68Smillert }
1018df930be7Sderaadt
1019df930be7Sderaadt out:
10206468ba68Smillert PRIV_END;
1021df930be7Sderaadt }
1022df930be7Sderaadt
1023df930be7Sderaadt /*
1024df930be7Sderaadt * Reposition the job by changing the modification time of
1025df930be7Sderaadt * the control file.
1026df930be7Sderaadt */
1027a7643117Smillert static int
touch(struct queue * q)1028a7643117Smillert touch(struct queue *q)
1029df930be7Sderaadt {
1030df930be7Sderaadt struct timeval tvp[2];
1031df930be7Sderaadt int ret;
1032df930be7Sderaadt
1033df930be7Sderaadt tvp[0].tv_sec = tvp[1].tv_sec = --mtime;
1034df930be7Sderaadt tvp[0].tv_usec = tvp[1].tv_usec = 0;
10356468ba68Smillert PRIV_START;
1036df930be7Sderaadt ret = utimes(q->q_name, tvp);
10376468ba68Smillert PRIV_END;
1038df930be7Sderaadt return (ret);
1039df930be7Sderaadt }
1040df930be7Sderaadt
1041df930be7Sderaadt /*
1042df930be7Sderaadt * Checks if specified job name is in the printer's queue.
1043df930be7Sderaadt * Returns: negative (-1) if argument name is not in the queue.
1044df930be7Sderaadt */
10450321e45eSderaadt int
doarg(char * job)1046a7643117Smillert doarg(char *job)
1047df930be7Sderaadt {
1048c1624b2fSmillert struct queue **qq;
10496468ba68Smillert int jobnum, fd, n;
1050c1624b2fSmillert char *cp, *machine;
1051df930be7Sderaadt int cnt = 0;
1052df930be7Sderaadt FILE *fp;
1053df930be7Sderaadt
1054df930be7Sderaadt /*
1055df930be7Sderaadt * Look for a job item consisting of system name, colon, number
1056df930be7Sderaadt * (example: ucbarpa:114)
1057df930be7Sderaadt */
105820a848d0Smillert if ((cp = strchr(job, ':')) != NULL) {
1059df930be7Sderaadt machine = job;
1060df930be7Sderaadt *cp++ = '\0';
1061df930be7Sderaadt job = cp;
1062df930be7Sderaadt } else
1063df930be7Sderaadt machine = NULL;
1064df930be7Sderaadt
1065df930be7Sderaadt /*
1066df930be7Sderaadt * Check for job specified by number (example: 112 or 235ucbarpa).
1067df930be7Sderaadt */
10680c4db8c1Sderaadt if (isdigit((unsigned char)*job)) {
1069df930be7Sderaadt jobnum = 0;
1070df930be7Sderaadt do
1071df930be7Sderaadt jobnum = jobnum * 10 + (*job++ - '0');
10720c4db8c1Sderaadt while (isdigit((unsigned char)*job));
1073df930be7Sderaadt for (qq = queue + nitems; --qq >= queue; ) {
1074df930be7Sderaadt n = 0;
10750c4db8c1Sderaadt for (cp = (*qq)->q_name+3; isdigit((unsigned char)*cp); )
1076df930be7Sderaadt n = n * 10 + (*cp++ - '0');
1077df930be7Sderaadt if (jobnum != n)
1078df930be7Sderaadt continue;
1079df930be7Sderaadt if (*job && strcmp(job, cp) != 0)
1080df930be7Sderaadt continue;
1081df930be7Sderaadt if (machine != NULL && strcmp(machine, cp) != 0)
1082df930be7Sderaadt continue;
1083df930be7Sderaadt if (touch(*qq) == 0) {
1084df930be7Sderaadt printf("\tmoved %s\n", (*qq)->q_name);
1085df930be7Sderaadt cnt++;
1086df930be7Sderaadt }
1087df930be7Sderaadt }
1088df930be7Sderaadt return(cnt);
1089df930be7Sderaadt }
1090df930be7Sderaadt /*
1091df930be7Sderaadt * Process item consisting of owner's name (example: henry).
1092df930be7Sderaadt */
1093df930be7Sderaadt for (qq = queue + nitems; --qq >= queue; ) {
10946468ba68Smillert PRIV_START;
10956468ba68Smillert fd = safe_open((*qq)->q_name, O_RDONLY|O_NOFOLLOW, 0);
10966468ba68Smillert PRIV_END;
10976468ba68Smillert if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) {
10986468ba68Smillert if (fd >= 0)
10996468ba68Smillert close(fd);
1100df930be7Sderaadt continue;
11016468ba68Smillert }
1102f9bbbf45Sfgsch while (get_line(fp) > 0)
1103df930be7Sderaadt if (line[0] == 'P')
1104df930be7Sderaadt break;
1105df930be7Sderaadt (void)fclose(fp);
1106df930be7Sderaadt if (line[0] != 'P' || strcmp(job, line+1) != 0)
1107df930be7Sderaadt continue;
1108df930be7Sderaadt if (touch(*qq) == 0) {
1109df930be7Sderaadt printf("\tmoved %s\n", (*qq)->q_name);
1110df930be7Sderaadt cnt++;
1111df930be7Sderaadt }
1112df930be7Sderaadt }
1113df930be7Sderaadt return(cnt);
1114df930be7Sderaadt }
1115df930be7Sderaadt
1116df930be7Sderaadt /*
1117df930be7Sderaadt * Enable everything and start printer (undo `down').
1118df930be7Sderaadt */
1119df930be7Sderaadt void
up(int argc,char ** argv)1120a7643117Smillert up(int argc, char **argv)
1121df930be7Sderaadt {
1122c1624b2fSmillert int c, status;
1123c1624b2fSmillert char *cp1, *cp2;
1124df930be7Sderaadt char prbuf[100];
1125df930be7Sderaadt
1126df930be7Sderaadt if (argc == 1) {
11271d8c2aacSsobrado printf("usage: up {all | printer ...}\n");
1128df930be7Sderaadt return;
1129df930be7Sderaadt }
1130a7643117Smillert if (argc == 2 && strcmp(argv[1], "all") == 0) {
1131df930be7Sderaadt printer = prbuf;
1132df930be7Sderaadt while (cgetnext(&bp, printcapdb) > 0) {
1133df930be7Sderaadt cp1 = prbuf;
1134df930be7Sderaadt cp2 = bp;
11357416c11cSmillert while ((c = *cp2++) && c != '|' && c != ':' &&
1136c9e7d913Spjanzen (cp1 - prbuf) < sizeof(prbuf) - 1)
1137df930be7Sderaadt *cp1++ = c;
1138df930be7Sderaadt *cp1 = '\0';
1139df930be7Sderaadt startpr(2);
1140df930be7Sderaadt }
1141df930be7Sderaadt return;
1142df930be7Sderaadt }
1143df930be7Sderaadt while (--argc) {
1144df930be7Sderaadt printer = *++argv;
1145df930be7Sderaadt if ((status = cgetent(&bp, printcapdb, printer)) == -2) {
1146df930be7Sderaadt printf("cannot open printer description file\n");
1147df930be7Sderaadt continue;
1148df930be7Sderaadt } else if (status == -1) {
1149df930be7Sderaadt printf("unknown printer %s\n", printer);
1150df930be7Sderaadt continue;
1151df930be7Sderaadt } else if (status == -3)
1152df930be7Sderaadt fatal("potential reference loop detected in printcap file");
1153df930be7Sderaadt
1154df930be7Sderaadt startpr(2);
1155df930be7Sderaadt }
1156df930be7Sderaadt }
1157