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