| File: | src/usr.sbin/lpr/lpc/cmds.c |
| Warning: | line 701, 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 | } |