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