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