75static void abortpr __P((struct printer *, int)); 76static int doarg __P((char *)); 77static int doselect __P((struct dirent *)); 78static void putmsg __P((struct printer *, int, char **)); 79static int sortq __P((const void *, const void *)); 80static void startpr __P((struct printer *, int)); 81static int touch __P((struct queue *)); 82static void unlinkf __P((char *)); 83static void upstat __P((struct printer *, char *)); 84 85/* 86 * generic framework for commands which operate on all or a specified 87 * set of printers 88 */ 89void 90generic(doit, argc, argv) 91 void (*doit) __P((struct printer *)); 92 int argc; 93 char *argv[]; 94{ 95 int status, more; 96 struct printer myprinter, *pp = &myprinter; 97 98 if (argc == 1) { 99 printf("Usage: %s {all | printer ...}\n", argv[0]); 100 return; 101 } 102 if (argc == 2 && strcmp(argv[1], "all") == 0) { 103 more = firstprinter(pp, &status); 104 if (status) 105 goto looperr; 106 while (more) { 107 (*doit)(pp); 108 do { 109 more = nextprinter(pp, &status); 110looperr: 111 switch (status) { 112 case PCAPERR_TCOPEN: 113 printf("warning: %s: unresolved " 114 "tc= reference(s) ", 115 pp->printer); 116 case PCAPERR_SUCCESS: 117 break; 118 default: 119 fatal(pp, pcaperr(status)); 120 } 121 } while (more && status); 122 } 123 return; 124 } 125 while (--argc) { 126 ++argv; 127 init_printer(pp); 128 status = getprintcap(*argv, pp); 129 switch(status) { 130 default: 131 fatal(pp, pcaperr(status)); 132 case PCAPERR_NOTFOUND: 133 printf("unknown printer %s\n", *argv); 134 continue; 135 case PCAPERR_TCOPEN: 136 printf("warning: %s: unresolved tc= reference(s)\n", 137 *argv); 138 break; 139 case PCAPERR_SUCCESS: 140 break; 141 } 142 (*doit)(pp); 143 } 144} 145 146/* 147 * kill an existing daemon and disable printing. 148 */ 149void 150doabort(pp) 151 struct printer *pp; 152{ 153 abortpr(pp, 1); 154} 155 156static void 157abortpr(pp, dis) 158 struct printer *pp; 159 int dis; 160{ 161 register FILE *fp; 162 struct stat stbuf; 163 int pid, fd; 164 char lf[MAXPATHLEN]; 165 166 lock_file_name(pp, lf, sizeof lf); 167 printf("%s:\n", pp->printer); 168 169 /* 170 * Turn on the owner execute bit of the lock file to disable printing. 171 */ 172 if (dis) { 173 seteuid(euid); 174 if (stat(lf, &stbuf) >= 0) { 175 if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 176 printf("\tcannot disable printing: %s\n", 177 strerror(errno)); 178 else { 179 upstat(pp, "printing disabled\n"); 180 printf("\tprinting disabled\n"); 181 } 182 } else if (errno == ENOENT) { 183 if ((fd = open(lf, O_WRONLY|O_CREAT, 184 LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 185 printf("\tcannot create lock file: %s\n", 186 strerror(errno)); 187 else { 188 (void) close(fd); 189 upstat(pp, "printing disabled\n"); 190 printf("\tprinting disabled\n"); 191 printf("\tno daemon to abort\n"); 192 } 193 goto out; 194 } else { 195 printf("\tcannot stat lock file\n"); 196 goto out; 197 } 198 } 199 /* 200 * Kill the current daemon to stop printing now. 201 */ 202 if ((fp = fopen(lf, "r")) == NULL) { 203 printf("\tcannot open lock file\n"); 204 goto out; 205 } 206 if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 207 (void) fclose(fp); /* unlocks as well */ 208 printf("\tno daemon to abort\n"); 209 goto out; 210 } 211 (void) fclose(fp); 212 if (kill(pid = atoi(line), SIGTERM) < 0) { 213 if (errno == ESRCH) 214 printf("\tno daemon to abort\n"); 215 else 216 printf("\tWarning: daemon (pid %d) not killed\n", pid); 217 } else 218 printf("\tdaemon (pid %d) killed\n", pid); 219out: 220 seteuid(uid); 221} 222 223/* 224 * Write a message into the status file. 225 */ 226static void 227upstat(pp, msg) 228 struct printer *pp; 229 char *msg; 230{ 231 register int fd; 232 char statfile[MAXPATHLEN]; 233 234 status_file_name(pp, statfile, sizeof statfile); 235 umask(0); 236 fd = open(statfile, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 237 if (fd < 0) { 238 printf("\tcannot create status file: %s\n", strerror(errno)); 239 return; 240 } 241 (void) ftruncate(fd, 0); 242 if (msg == (char *)NULL) 243 (void) write(fd, "\n", 1); 244 else 245 (void) write(fd, msg, strlen(msg)); 246 (void) close(fd); 247} 248 249static int 250doselect(d) 251 struct dirent *d; 252{ 253 int c = d->d_name[0]; 254 255 if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') 256 return(1); 257 return(0); 258} 259 260/* 261 * Comparison routine for scandir. Sort by job number and machine, then 262 * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. 263 */ 264static int 265sortq(a, b) 266 const void *a, *b; 267{ 268 struct dirent **d1, **d2; 269 int c1, c2; 270 271 d1 = (struct dirent **)a; 272 d2 = (struct dirent **)b; 273 if ((c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))) 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 all spool files and temporaries from the spooling area. 288 * Or, perhaps: 289 * Remove incomplete jobs from spooling area. 290 */ 291void 292clean(pp) 293 struct printer *pp; 294{ 295 register int i, n; 296 register char *cp, *cp1, *lp; 297 struct dirent **queue; 298 int nitems; 299 300 printf("%s:\n", pp->printer); 301 302 lp = line; 303 cp = pp->spool_dir; 304 while (lp < &line[sizeof(line) - 1]) { 305 if ((*lp++ = *cp++) == 0) 306 break; 307 } 308 lp[-1] = '/'; 309 310 seteuid(euid); 311 nitems = scandir(pp->spool_dir, &queue, doselect, sortq); 312 seteuid(uid); 313 if (nitems < 0) { 314 printf("\tcannot examine spool directory\n"); 315 return; 316 } 317 if (nitems == 0) 318 return; 319 i = 0; 320 do { 321 cp = queue[i]->d_name; 322 if (*cp == 'c') { 323 n = 0; 324 while (i + 1 < nitems) { 325 cp1 = queue[i + 1]->d_name; 326 if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 327 break; 328 i++; 329 n++; 330 } 331 if (n == 0) { 332 strncpy(lp, cp, sizeof(line) - strlen(line) - 1); 333 line[sizeof(line) - 1] = '\0'; 334 unlinkf(line); 335 } 336 } else { 337 /* 338 * Must be a df with no cf (otherwise, it would have 339 * been skipped above) or a tf file (which can always 340 * be removed). 341 */ 342 strncpy(lp, cp, sizeof(line) - strlen(line) - 1); 343 line[sizeof(line) - 1] = '\0'; 344 unlinkf(line); 345 } 346 } while (++i < nitems); 347} 348 349static void 350unlinkf(name) 351 char *name; 352{ 353 seteuid(euid); 354 if (unlink(name) < 0) 355 printf("\tcannot remove %s\n", name); 356 else 357 printf("\tremoved %s\n", name); 358 seteuid(uid); 359} 360 361/* 362 * Enable queuing to the printer (allow lpr's). 363 */ 364void 365enable(pp) 366 struct printer *pp; 367{ 368 struct stat stbuf; 369 char lf[MAXPATHLEN]; 370 371 lock_file_name(pp, lf, sizeof lf); 372 printf("%s:\n", pp->printer); 373 374 /* 375 * Turn off the group execute bit of the lock file to enable queuing. 376 */ 377 seteuid(euid); 378 if (stat(lf, &stbuf) >= 0) { 379 if (chmod(lf, stbuf.st_mode & ~LFM_QUEUE_DIS) < 0) 380 printf("\tcannot enable queuing\n"); 381 else 382 printf("\tqueuing enabled\n"); 383 } 384 seteuid(uid); 385} 386 387/* 388 * Disable queuing. 389 */ 390void 391disable(pp) 392 struct printer *pp; 393{ 394 register int fd; 395 struct stat stbuf; 396 char lf[MAXPATHLEN]; 397 398 lock_file_name(pp, lf, sizeof lf); 399 printf("%s:\n", pp->printer); 400 /* 401 * Turn on the group execute bit of the lock file to disable queuing. 402 */ 403 seteuid(euid); 404 if (stat(lf, &stbuf) >= 0) { 405 if (chmod(lf, stbuf.st_mode | LFM_QUEUE_DIS) < 0) 406 printf("\tcannot disable queuing: %s\n", 407 strerror(errno)); 408 else 409 printf("\tqueuing disabled\n"); 410 } else if (errno == ENOENT) { 411 if ((fd = open(lf, O_WRONLY|O_CREAT, 412 LOCK_FILE_MODE | LFM_QUEUE_DIS)) < 0) 413 printf("\tcannot create lock file: %s\n", 414 strerror(errno)); 415 else { 416 (void) close(fd); 417 printf("\tqueuing disabled\n"); 418 } 419 } else 420 printf("\tcannot stat lock file\n"); 421 seteuid(uid); 422} 423 424/* 425 * Disable queuing and printing and put a message into the status file 426 * (reason for being down). 427 */ 428void 429down(argc, argv) 430 int argc; 431 char *argv[]; 432{ 433 int status, more; 434 struct printer myprinter, *pp = &myprinter; 435 436 if (argc == 1) { 437 printf("Usage: down {all | printer} [message ...]\n"); 438 return; 439 } 440 if (!strcmp(argv[1], "all")) { 441 more = firstprinter(pp, &status); 442 if (status) 443 goto looperr; 444 while (more) { 445 putmsg(pp, argc - 2, argv + 2); 446 do { 447 more = nextprinter(pp, &status); 448looperr: 449 switch (status) { 450 case PCAPERR_TCOPEN: 451 printf("warning: %s: unresolved " 452 "tc= reference(s) ", 453 pp->printer); 454 case PCAPERR_SUCCESS: 455 break; 456 default: 457 fatal(pp, pcaperr(status)); 458 } 459 } while (more && status); 460 } 461 return; 462 } 463 init_printer(pp); 464 status = getprintcap(argv[1], pp); 465 switch(status) { 466 default: 467 fatal(pp, pcaperr(status)); 468 case PCAPERR_NOTFOUND: 469 printf("unknown printer %s\n", argv[1]); 470 return; 471 case PCAPERR_TCOPEN: 472 printf("warning: %s: unresolved tc= reference(s)", argv[1]); 473 break; 474 case PCAPERR_SUCCESS: 475 break; 476 } 477 putmsg(pp, argc - 2, argv + 2); 478} 479 480static void 481putmsg(pp, argc, argv) 482 struct printer *pp; 483 int argc; 484 char **argv; 485{ 486 register int fd; 487 register char *cp1, *cp2; 488 char buf[1024]; 489 char file[MAXPATHLEN]; 490 struct stat stbuf; 491 492 printf("%s:\n", pp->printer); 493 /* 494 * Turn on the group execute bit of the lock file to disable queuing; 495 * turn on the owner execute bit of the lock file to disable printing. 496 */ 497 lock_file_name(pp, file, sizeof file); 498 seteuid(euid); 499 if (stat(file, &stbuf) >= 0) { 500 if (chmod(file, stbuf.st_mode|LFM_PRINT_DIS|LFM_QUEUE_DIS) < 0) 501 printf("\tcannot disable queuing: %s\n", 502 strerror(errno)); 503 else 504 printf("\tprinter and queuing disabled\n"); 505 } else if (errno == ENOENT) { 506 if ((fd = open(file, O_WRONLY|O_CREAT, 507 LOCK_FILE_MODE|LFM_PRINT_DIS|LFM_QUEUE_DIS)) < 0) 508 printf("\tcannot create lock file: %s\n", 509 strerror(errno)); 510 else { 511 (void) close(fd); 512 printf("\tprinter and queuing disabled\n"); 513 } 514 seteuid(uid); 515 return; 516 } else 517 printf("\tcannot stat lock file\n"); 518 /* 519 * Write the message into the status file. 520 */ 521 status_file_name(pp, file, sizeof file); 522 fd = open(file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 523 if (fd < 0) { 524 printf("\tcannot create status file: %s\n", strerror(errno)); 525 seteuid(uid); 526 return; 527 } 528 seteuid(uid); 529 (void) ftruncate(fd, 0); 530 if (argc <= 0) { 531 (void) write(fd, "\n", 1); 532 (void) close(fd); 533 return; 534 } 535 cp1 = buf; 536 while (--argc >= 0) { 537 cp2 = *argv++; 538 while ((cp1 - buf) < sizeof(buf) && (*cp1++ = *cp2++)) 539 ; 540 cp1[-1] = ' '; 541 } 542 cp1[-1] = '\n'; 543 *cp1 = '\0'; 544 (void) write(fd, buf, strlen(buf)); 545 (void) close(fd); 546} 547 548/* 549 * Exit lpc 550 */ 551void 552quit(argc, argv) 553 int argc; 554 char *argv[]; 555{ 556 exit(0); 557} 558 559/* 560 * Kill and restart the daemon. 561 */ 562void 563restart(pp) 564 struct printer *pp; 565{ 566 abortpr(pp, 0); 567 startpr(pp, 0); 568} 569 570/* 571 * Enable printing on the specified printer and startup the daemon. 572 */ 573void 574startcmd(pp) 575 struct printer *pp; 576{ 577 startpr(pp, 1); 578} 579 580static void 581startpr(pp, enable) 582 struct printer *pp; 583 int enable; 584{ 585 struct stat stbuf; 586 char lf[MAXPATHLEN]; 587 588 lock_file_name(pp, lf, sizeof lf); 589 printf("%s:\n", pp->printer); 590 591 /* 592 * Turn off the owner execute bit of the lock file to enable printing. 593 */ 594 seteuid(euid); 595 if (enable && stat(lf, &stbuf) >= 0) { 596 mode_t bits = (enable == 2 ? 0 597 : (LFM_PRINT_DIS | LFM_QUEUE_DIS)); 598 if (chmod(lf, stbuf.st_mode & (LOCK_FILE_MODE | bits)) < 0) 599 printf("\tcannot enable printing\n"); 600 else 601 printf("\tprinting enabled\n"); 602 } 603 if (!startdaemon(pp)) 604 printf("\tcouldn't start daemon\n"); 605 else 606 printf("\tdaemon started\n"); 607 seteuid(uid); 608} 609 610/* 611 * Print the status of the printer queue. 612 */ 613void 614status(pp) 615 struct printer *pp; 616{ 617 struct stat stbuf; 618 register int fd, i; 619 register struct dirent *dp; 620 DIR *dirp; 621 char file[MAXPATHLEN]; 622 623 printf("%s:\n", pp->printer); 624 lock_file_name(pp, file, sizeof file); 625 if (stat(file, &stbuf) >= 0) { 626 printf("\tqueuing is %s\n", 627 ((stbuf.st_mode & LFM_QUEUE_DIS) ? "disabled" 628 : "enabled")); 629 printf("\tprinting is %s\n", 630 ((stbuf.st_mode & LFM_PRINT_DIS) ? "disabled" 631 : "enabled")); 632 } else { 633 printf("\tqueuing is enabled\n"); 634 printf("\tprinting is enabled\n"); 635 } 636 if ((dirp = opendir(pp->spool_dir)) == NULL) { 637 printf("\tcannot examine spool directory\n"); 638 return; 639 } 640 i = 0; 641 while ((dp = readdir(dirp)) != NULL) { 642 if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 643 i++; 644 } 645 closedir(dirp); 646 if (i == 0) 647 printf("\tno entries in spool area\n"); 648 else if (i == 1) 649 printf("\t1 entry in spool area\n"); 650 else 651 printf("\t%d entries in spool area\n", i); 652 fd = open(file, O_RDONLY); 653 if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 654 (void) close(fd); /* unlocks as well */ 655 printf("\tprinter idle\n"); 656 return; 657 } 658 (void) close(fd); 659 /* print out the contents of the status file, if it exists */ 660 status_file_name(pp, file, sizeof file); 661 fd = open(file, O_RDONLY|O_SHLOCK); 662 if (fd >= 0) { 663 (void) fstat(fd, &stbuf); 664 if (stbuf.st_size > 0) { 665 putchar('\t'); 666 while ((i = read(fd, line, sizeof(line))) > 0) 667 (void) fwrite(line, 1, i, stdout); 668 } 669 (void) close(fd); /* unlocks as well */ 670 } 671} 672 673/* 674 * Stop the specified daemon after completing the current job and disable 675 * printing. 676 */ 677void 678stop(pp) 679 struct printer *pp; 680{ 681 register int fd; 682 struct stat stbuf; 683 char lf[MAXPATHLEN]; 684 685 lock_file_name(pp, lf, sizeof lf); 686 printf("%s:\n", pp->printer); 687 688 /* 689 * Turn on the owner execute bit of the lock file to disable printing. 690 */ 691 seteuid(euid); 692 if (stat(lf, &stbuf) >= 0) { 693 if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 694 printf("\tcannot disable printing: %s\n", 695 strerror(errno)); 696 else { 697 upstat(pp, "printing disabled\n"); 698 printf("\tprinting disabled\n"); 699 } 700 } else if (errno == ENOENT) { 701 if ((fd = open(lf, O_WRONLY|O_CREAT, 702 LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 703 printf("\tcannot create lock file: %s\n", 704 strerror(errno)); 705 else { 706 (void) close(fd); 707 upstat(pp, "printing disabled\n"); 708 printf("\tprinting disabled\n"); 709 } 710 } else 711 printf("\tcannot stat lock file\n"); 712 seteuid(uid); 713} 714 715struct queue **queue; 716int nitems; 717time_t mtime; 718 719/* 720 * Put the specified jobs at the top of printer queue. 721 */ 722void 723topq(argc, argv) 724 int argc; 725 char *argv[]; 726{ 727 register int i; 728 struct stat stbuf; 729 int status, changed; 730 struct printer myprinter, *pp = &myprinter; 731 732 if (argc < 3) { 733 printf("Usage: topq printer [jobnum ...] [user ...]\n"); 734 return; 735 } 736 737 --argc; 738 ++argv; 739 init_printer(pp); 740 status = getprintcap(*argv, pp); 741 switch(status) { 742 default: 743 fatal(pp, pcaperr(status)); 744 case PCAPERR_NOTFOUND: 745 printf("unknown printer %s\n", *argv); 746 return; 747 case PCAPERR_TCOPEN: 748 printf("warning: %s: unresolved tc= reference(s)", *argv); 749 break; 750 case PCAPERR_SUCCESS: 751 break; 752 } 753 printf("%s:\n", pp->printer); 754 755 seteuid(euid); 756 if (chdir(pp->spool_dir) < 0) { 757 printf("\tcannot chdir to %s\n", pp->spool_dir); 758 goto out; 759 } 760 seteuid(uid); 761 nitems = getq(pp, &queue); 762 if (nitems == 0) 763 return; 764 changed = 0; 765 mtime = queue[0]->q_time; 766 for (i = argc; --i; ) { 767 if (doarg(argv[i]) == 0) { 768 printf("\tjob %s is not in the queue\n", argv[i]); 769 continue; 770 } else 771 changed++; 772 } 773 for (i = 0; i < nitems; i++) 774 free(queue[i]); 775 free(queue); 776 if (!changed) { 777 printf("\tqueue order unchanged\n"); 778 return; 779 } 780 /* 781 * Turn on the public execute bit of the lock file to 782 * get lpd to rebuild the queue after the current job. 783 */ 784 seteuid(euid); 785 if (changed && stat(pp->lock_file, &stbuf) >= 0) 786 (void) chmod(pp->lock_file, stbuf.st_mode | LFM_RESET_QUE); 787 788out: 789 seteuid(uid); 790} 791 792/* 793 * Reposition the job by changing the modification time of 794 * the control file. 795 */ 796static int 797touch(q) 798 struct queue *q; 799{ 800 struct timeval tvp[2]; 801 int ret; 802 803 tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 804 tvp[0].tv_usec = tvp[1].tv_usec = 0; 805 seteuid(euid); 806 ret = utimes(q->q_name, tvp); 807 seteuid(uid); 808 return (ret); 809} 810 811/* 812 * Checks if specified job name is in the printer's queue. 813 * Returns: negative (-1) if argument name is not in the queue. 814 */ 815static int 816doarg(job) 817 char *job; 818{ 819 register struct queue **qq; 820 register int jobnum, n; 821 register char *cp, *machine; 822 int cnt = 0; 823 FILE *fp; 824 825 /* 826 * Look for a job item consisting of system name, colon, number 827 * (example: ucbarpa:114) 828 */ 829 if ((cp = strchr(job, ':')) != NULL) { 830 machine = job; 831 *cp++ = '\0'; 832 job = cp; 833 } else 834 machine = NULL; 835 836 /* 837 * Check for job specified by number (example: 112 or 235ucbarpa). 838 */ 839 if (isdigit(*job)) { 840 jobnum = 0; 841 do 842 jobnum = jobnum * 10 + (*job++ - '0'); 843 while (isdigit(*job)); 844 for (qq = queue + nitems; --qq >= queue; ) { 845 n = 0; 846 for (cp = (*qq)->q_name+3; isdigit(*cp); ) 847 n = n * 10 + (*cp++ - '0'); 848 if (jobnum != n) 849 continue; 850 if (*job && strcmp(job, cp) != 0) 851 continue; 852 if (machine != NULL && strcmp(machine, cp) != 0) 853 continue; 854 if (touch(*qq) == 0) { 855 printf("\tmoved %s\n", (*qq)->q_name); 856 cnt++; 857 } 858 } 859 return(cnt); 860 } 861 /* 862 * Process item consisting of owner's name (example: henry). 863 */ 864 for (qq = queue + nitems; --qq >= queue; ) { 865 seteuid(euid); 866 fp = fopen((*qq)->q_name, "r"); 867 seteuid(uid); 868 if (fp == NULL) 869 continue; 870 while (getline(fp) > 0) 871 if (line[0] == 'P') 872 break; 873 (void) fclose(fp); 874 if (line[0] != 'P' || strcmp(job, line+1) != 0) 875 continue; 876 if (touch(*qq) == 0) { 877 printf("\tmoved %s\n", (*qq)->q_name); 878 cnt++; 879 } 880 } 881 return(cnt); 882} 883 884/* 885 * Enable everything and start printer (undo `down'). 886 */ 887void 888up(pp) 889 struct printer *pp; 890{ 891 startpr(pp, 2); 892}
| 73static void abortpr __P((struct printer *, int)); 74static int doarg __P((char *)); 75static int doselect __P((struct dirent *)); 76static void putmsg __P((struct printer *, int, char **)); 77static int sortq __P((const void *, const void *)); 78static void startpr __P((struct printer *, int)); 79static int touch __P((struct queue *)); 80static void unlinkf __P((char *)); 81static void upstat __P((struct printer *, char *)); 82 83/* 84 * generic framework for commands which operate on all or a specified 85 * set of printers 86 */ 87void 88generic(doit, argc, argv) 89 void (*doit) __P((struct printer *)); 90 int argc; 91 char *argv[]; 92{ 93 int status, more; 94 struct printer myprinter, *pp = &myprinter; 95 96 if (argc == 1) { 97 printf("Usage: %s {all | printer ...}\n", argv[0]); 98 return; 99 } 100 if (argc == 2 && strcmp(argv[1], "all") == 0) { 101 more = firstprinter(pp, &status); 102 if (status) 103 goto looperr; 104 while (more) { 105 (*doit)(pp); 106 do { 107 more = nextprinter(pp, &status); 108looperr: 109 switch (status) { 110 case PCAPERR_TCOPEN: 111 printf("warning: %s: unresolved " 112 "tc= reference(s) ", 113 pp->printer); 114 case PCAPERR_SUCCESS: 115 break; 116 default: 117 fatal(pp, pcaperr(status)); 118 } 119 } while (more && status); 120 } 121 return; 122 } 123 while (--argc) { 124 ++argv; 125 init_printer(pp); 126 status = getprintcap(*argv, pp); 127 switch(status) { 128 default: 129 fatal(pp, pcaperr(status)); 130 case PCAPERR_NOTFOUND: 131 printf("unknown printer %s\n", *argv); 132 continue; 133 case PCAPERR_TCOPEN: 134 printf("warning: %s: unresolved tc= reference(s)\n", 135 *argv); 136 break; 137 case PCAPERR_SUCCESS: 138 break; 139 } 140 (*doit)(pp); 141 } 142} 143 144/* 145 * kill an existing daemon and disable printing. 146 */ 147void 148doabort(pp) 149 struct printer *pp; 150{ 151 abortpr(pp, 1); 152} 153 154static void 155abortpr(pp, dis) 156 struct printer *pp; 157 int dis; 158{ 159 register FILE *fp; 160 struct stat stbuf; 161 int pid, fd; 162 char lf[MAXPATHLEN]; 163 164 lock_file_name(pp, lf, sizeof lf); 165 printf("%s:\n", pp->printer); 166 167 /* 168 * Turn on the owner execute bit of the lock file to disable printing. 169 */ 170 if (dis) { 171 seteuid(euid); 172 if (stat(lf, &stbuf) >= 0) { 173 if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 174 printf("\tcannot disable printing: %s\n", 175 strerror(errno)); 176 else { 177 upstat(pp, "printing disabled\n"); 178 printf("\tprinting disabled\n"); 179 } 180 } else if (errno == ENOENT) { 181 if ((fd = open(lf, O_WRONLY|O_CREAT, 182 LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 183 printf("\tcannot create lock file: %s\n", 184 strerror(errno)); 185 else { 186 (void) close(fd); 187 upstat(pp, "printing disabled\n"); 188 printf("\tprinting disabled\n"); 189 printf("\tno daemon to abort\n"); 190 } 191 goto out; 192 } else { 193 printf("\tcannot stat lock file\n"); 194 goto out; 195 } 196 } 197 /* 198 * Kill the current daemon to stop printing now. 199 */ 200 if ((fp = fopen(lf, "r")) == NULL) { 201 printf("\tcannot open lock file\n"); 202 goto out; 203 } 204 if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 205 (void) fclose(fp); /* unlocks as well */ 206 printf("\tno daemon to abort\n"); 207 goto out; 208 } 209 (void) fclose(fp); 210 if (kill(pid = atoi(line), SIGTERM) < 0) { 211 if (errno == ESRCH) 212 printf("\tno daemon to abort\n"); 213 else 214 printf("\tWarning: daemon (pid %d) not killed\n", pid); 215 } else 216 printf("\tdaemon (pid %d) killed\n", pid); 217out: 218 seteuid(uid); 219} 220 221/* 222 * Write a message into the status file. 223 */ 224static void 225upstat(pp, msg) 226 struct printer *pp; 227 char *msg; 228{ 229 register int fd; 230 char statfile[MAXPATHLEN]; 231 232 status_file_name(pp, statfile, sizeof statfile); 233 umask(0); 234 fd = open(statfile, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 235 if (fd < 0) { 236 printf("\tcannot create status file: %s\n", strerror(errno)); 237 return; 238 } 239 (void) ftruncate(fd, 0); 240 if (msg == (char *)NULL) 241 (void) write(fd, "\n", 1); 242 else 243 (void) write(fd, msg, strlen(msg)); 244 (void) close(fd); 245} 246 247static int 248doselect(d) 249 struct dirent *d; 250{ 251 int c = d->d_name[0]; 252 253 if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') 254 return(1); 255 return(0); 256} 257 258/* 259 * Comparison routine for scandir. Sort by job number and machine, then 260 * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. 261 */ 262static int 263sortq(a, b) 264 const void *a, *b; 265{ 266 struct dirent **d1, **d2; 267 int c1, c2; 268 269 d1 = (struct dirent **)a; 270 d2 = (struct dirent **)b; 271 if ((c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3))) 272 return(c1); 273 c1 = (*d1)->d_name[0]; 274 c2 = (*d2)->d_name[0]; 275 if (c1 == c2) 276 return((*d1)->d_name[2] - (*d2)->d_name[2]); 277 if (c1 == 'c') 278 return(-1); 279 if (c1 == 'd' || c2 == 'c') 280 return(1); 281 return(-1); 282} 283 284/* 285 * Remove all spool files and temporaries from the spooling area. 286 * Or, perhaps: 287 * Remove incomplete jobs from spooling area. 288 */ 289void 290clean(pp) 291 struct printer *pp; 292{ 293 register int i, n; 294 register char *cp, *cp1, *lp; 295 struct dirent **queue; 296 int nitems; 297 298 printf("%s:\n", pp->printer); 299 300 lp = line; 301 cp = pp->spool_dir; 302 while (lp < &line[sizeof(line) - 1]) { 303 if ((*lp++ = *cp++) == 0) 304 break; 305 } 306 lp[-1] = '/'; 307 308 seteuid(euid); 309 nitems = scandir(pp->spool_dir, &queue, doselect, sortq); 310 seteuid(uid); 311 if (nitems < 0) { 312 printf("\tcannot examine spool directory\n"); 313 return; 314 } 315 if (nitems == 0) 316 return; 317 i = 0; 318 do { 319 cp = queue[i]->d_name; 320 if (*cp == 'c') { 321 n = 0; 322 while (i + 1 < nitems) { 323 cp1 = queue[i + 1]->d_name; 324 if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 325 break; 326 i++; 327 n++; 328 } 329 if (n == 0) { 330 strncpy(lp, cp, sizeof(line) - strlen(line) - 1); 331 line[sizeof(line) - 1] = '\0'; 332 unlinkf(line); 333 } 334 } else { 335 /* 336 * Must be a df with no cf (otherwise, it would have 337 * been skipped above) or a tf file (which can always 338 * be removed). 339 */ 340 strncpy(lp, cp, sizeof(line) - strlen(line) - 1); 341 line[sizeof(line) - 1] = '\0'; 342 unlinkf(line); 343 } 344 } while (++i < nitems); 345} 346 347static void 348unlinkf(name) 349 char *name; 350{ 351 seteuid(euid); 352 if (unlink(name) < 0) 353 printf("\tcannot remove %s\n", name); 354 else 355 printf("\tremoved %s\n", name); 356 seteuid(uid); 357} 358 359/* 360 * Enable queuing to the printer (allow lpr's). 361 */ 362void 363enable(pp) 364 struct printer *pp; 365{ 366 struct stat stbuf; 367 char lf[MAXPATHLEN]; 368 369 lock_file_name(pp, lf, sizeof lf); 370 printf("%s:\n", pp->printer); 371 372 /* 373 * Turn off the group execute bit of the lock file to enable queuing. 374 */ 375 seteuid(euid); 376 if (stat(lf, &stbuf) >= 0) { 377 if (chmod(lf, stbuf.st_mode & ~LFM_QUEUE_DIS) < 0) 378 printf("\tcannot enable queuing\n"); 379 else 380 printf("\tqueuing enabled\n"); 381 } 382 seteuid(uid); 383} 384 385/* 386 * Disable queuing. 387 */ 388void 389disable(pp) 390 struct printer *pp; 391{ 392 register int fd; 393 struct stat stbuf; 394 char lf[MAXPATHLEN]; 395 396 lock_file_name(pp, lf, sizeof lf); 397 printf("%s:\n", pp->printer); 398 /* 399 * Turn on the group execute bit of the lock file to disable queuing. 400 */ 401 seteuid(euid); 402 if (stat(lf, &stbuf) >= 0) { 403 if (chmod(lf, stbuf.st_mode | LFM_QUEUE_DIS) < 0) 404 printf("\tcannot disable queuing: %s\n", 405 strerror(errno)); 406 else 407 printf("\tqueuing disabled\n"); 408 } else if (errno == ENOENT) { 409 if ((fd = open(lf, O_WRONLY|O_CREAT, 410 LOCK_FILE_MODE | LFM_QUEUE_DIS)) < 0) 411 printf("\tcannot create lock file: %s\n", 412 strerror(errno)); 413 else { 414 (void) close(fd); 415 printf("\tqueuing disabled\n"); 416 } 417 } else 418 printf("\tcannot stat lock file\n"); 419 seteuid(uid); 420} 421 422/* 423 * Disable queuing and printing and put a message into the status file 424 * (reason for being down). 425 */ 426void 427down(argc, argv) 428 int argc; 429 char *argv[]; 430{ 431 int status, more; 432 struct printer myprinter, *pp = &myprinter; 433 434 if (argc == 1) { 435 printf("Usage: down {all | printer} [message ...]\n"); 436 return; 437 } 438 if (!strcmp(argv[1], "all")) { 439 more = firstprinter(pp, &status); 440 if (status) 441 goto looperr; 442 while (more) { 443 putmsg(pp, argc - 2, argv + 2); 444 do { 445 more = nextprinter(pp, &status); 446looperr: 447 switch (status) { 448 case PCAPERR_TCOPEN: 449 printf("warning: %s: unresolved " 450 "tc= reference(s) ", 451 pp->printer); 452 case PCAPERR_SUCCESS: 453 break; 454 default: 455 fatal(pp, pcaperr(status)); 456 } 457 } while (more && status); 458 } 459 return; 460 } 461 init_printer(pp); 462 status = getprintcap(argv[1], pp); 463 switch(status) { 464 default: 465 fatal(pp, pcaperr(status)); 466 case PCAPERR_NOTFOUND: 467 printf("unknown printer %s\n", argv[1]); 468 return; 469 case PCAPERR_TCOPEN: 470 printf("warning: %s: unresolved tc= reference(s)", argv[1]); 471 break; 472 case PCAPERR_SUCCESS: 473 break; 474 } 475 putmsg(pp, argc - 2, argv + 2); 476} 477 478static void 479putmsg(pp, argc, argv) 480 struct printer *pp; 481 int argc; 482 char **argv; 483{ 484 register int fd; 485 register char *cp1, *cp2; 486 char buf[1024]; 487 char file[MAXPATHLEN]; 488 struct stat stbuf; 489 490 printf("%s:\n", pp->printer); 491 /* 492 * Turn on the group execute bit of the lock file to disable queuing; 493 * turn on the owner execute bit of the lock file to disable printing. 494 */ 495 lock_file_name(pp, file, sizeof file); 496 seteuid(euid); 497 if (stat(file, &stbuf) >= 0) { 498 if (chmod(file, stbuf.st_mode|LFM_PRINT_DIS|LFM_QUEUE_DIS) < 0) 499 printf("\tcannot disable queuing: %s\n", 500 strerror(errno)); 501 else 502 printf("\tprinter and queuing disabled\n"); 503 } else if (errno == ENOENT) { 504 if ((fd = open(file, O_WRONLY|O_CREAT, 505 LOCK_FILE_MODE|LFM_PRINT_DIS|LFM_QUEUE_DIS)) < 0) 506 printf("\tcannot create lock file: %s\n", 507 strerror(errno)); 508 else { 509 (void) close(fd); 510 printf("\tprinter and queuing disabled\n"); 511 } 512 seteuid(uid); 513 return; 514 } else 515 printf("\tcannot stat lock file\n"); 516 /* 517 * Write the message into the status file. 518 */ 519 status_file_name(pp, file, sizeof file); 520 fd = open(file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 521 if (fd < 0) { 522 printf("\tcannot create status file: %s\n", strerror(errno)); 523 seteuid(uid); 524 return; 525 } 526 seteuid(uid); 527 (void) ftruncate(fd, 0); 528 if (argc <= 0) { 529 (void) write(fd, "\n", 1); 530 (void) close(fd); 531 return; 532 } 533 cp1 = buf; 534 while (--argc >= 0) { 535 cp2 = *argv++; 536 while ((cp1 - buf) < sizeof(buf) && (*cp1++ = *cp2++)) 537 ; 538 cp1[-1] = ' '; 539 } 540 cp1[-1] = '\n'; 541 *cp1 = '\0'; 542 (void) write(fd, buf, strlen(buf)); 543 (void) close(fd); 544} 545 546/* 547 * Exit lpc 548 */ 549void 550quit(argc, argv) 551 int argc; 552 char *argv[]; 553{ 554 exit(0); 555} 556 557/* 558 * Kill and restart the daemon. 559 */ 560void 561restart(pp) 562 struct printer *pp; 563{ 564 abortpr(pp, 0); 565 startpr(pp, 0); 566} 567 568/* 569 * Enable printing on the specified printer and startup the daemon. 570 */ 571void 572startcmd(pp) 573 struct printer *pp; 574{ 575 startpr(pp, 1); 576} 577 578static void 579startpr(pp, enable) 580 struct printer *pp; 581 int enable; 582{ 583 struct stat stbuf; 584 char lf[MAXPATHLEN]; 585 586 lock_file_name(pp, lf, sizeof lf); 587 printf("%s:\n", pp->printer); 588 589 /* 590 * Turn off the owner execute bit of the lock file to enable printing. 591 */ 592 seteuid(euid); 593 if (enable && stat(lf, &stbuf) >= 0) { 594 mode_t bits = (enable == 2 ? 0 595 : (LFM_PRINT_DIS | LFM_QUEUE_DIS)); 596 if (chmod(lf, stbuf.st_mode & (LOCK_FILE_MODE | bits)) < 0) 597 printf("\tcannot enable printing\n"); 598 else 599 printf("\tprinting enabled\n"); 600 } 601 if (!startdaemon(pp)) 602 printf("\tcouldn't start daemon\n"); 603 else 604 printf("\tdaemon started\n"); 605 seteuid(uid); 606} 607 608/* 609 * Print the status of the printer queue. 610 */ 611void 612status(pp) 613 struct printer *pp; 614{ 615 struct stat stbuf; 616 register int fd, i; 617 register struct dirent *dp; 618 DIR *dirp; 619 char file[MAXPATHLEN]; 620 621 printf("%s:\n", pp->printer); 622 lock_file_name(pp, file, sizeof file); 623 if (stat(file, &stbuf) >= 0) { 624 printf("\tqueuing is %s\n", 625 ((stbuf.st_mode & LFM_QUEUE_DIS) ? "disabled" 626 : "enabled")); 627 printf("\tprinting is %s\n", 628 ((stbuf.st_mode & LFM_PRINT_DIS) ? "disabled" 629 : "enabled")); 630 } else { 631 printf("\tqueuing is enabled\n"); 632 printf("\tprinting is enabled\n"); 633 } 634 if ((dirp = opendir(pp->spool_dir)) == NULL) { 635 printf("\tcannot examine spool directory\n"); 636 return; 637 } 638 i = 0; 639 while ((dp = readdir(dirp)) != NULL) { 640 if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 641 i++; 642 } 643 closedir(dirp); 644 if (i == 0) 645 printf("\tno entries in spool area\n"); 646 else if (i == 1) 647 printf("\t1 entry in spool area\n"); 648 else 649 printf("\t%d entries in spool area\n", i); 650 fd = open(file, O_RDONLY); 651 if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 652 (void) close(fd); /* unlocks as well */ 653 printf("\tprinter idle\n"); 654 return; 655 } 656 (void) close(fd); 657 /* print out the contents of the status file, if it exists */ 658 status_file_name(pp, file, sizeof file); 659 fd = open(file, O_RDONLY|O_SHLOCK); 660 if (fd >= 0) { 661 (void) fstat(fd, &stbuf); 662 if (stbuf.st_size > 0) { 663 putchar('\t'); 664 while ((i = read(fd, line, sizeof(line))) > 0) 665 (void) fwrite(line, 1, i, stdout); 666 } 667 (void) close(fd); /* unlocks as well */ 668 } 669} 670 671/* 672 * Stop the specified daemon after completing the current job and disable 673 * printing. 674 */ 675void 676stop(pp) 677 struct printer *pp; 678{ 679 register int fd; 680 struct stat stbuf; 681 char lf[MAXPATHLEN]; 682 683 lock_file_name(pp, lf, sizeof lf); 684 printf("%s:\n", pp->printer); 685 686 /* 687 * Turn on the owner execute bit of the lock file to disable printing. 688 */ 689 seteuid(euid); 690 if (stat(lf, &stbuf) >= 0) { 691 if (chmod(lf, stbuf.st_mode | LFM_PRINT_DIS) < 0) 692 printf("\tcannot disable printing: %s\n", 693 strerror(errno)); 694 else { 695 upstat(pp, "printing disabled\n"); 696 printf("\tprinting disabled\n"); 697 } 698 } else if (errno == ENOENT) { 699 if ((fd = open(lf, O_WRONLY|O_CREAT, 700 LOCK_FILE_MODE | LFM_PRINT_DIS)) < 0) 701 printf("\tcannot create lock file: %s\n", 702 strerror(errno)); 703 else { 704 (void) close(fd); 705 upstat(pp, "printing disabled\n"); 706 printf("\tprinting disabled\n"); 707 } 708 } else 709 printf("\tcannot stat lock file\n"); 710 seteuid(uid); 711} 712 713struct queue **queue; 714int nitems; 715time_t mtime; 716 717/* 718 * Put the specified jobs at the top of printer queue. 719 */ 720void 721topq(argc, argv) 722 int argc; 723 char *argv[]; 724{ 725 register int i; 726 struct stat stbuf; 727 int status, changed; 728 struct printer myprinter, *pp = &myprinter; 729 730 if (argc < 3) { 731 printf("Usage: topq printer [jobnum ...] [user ...]\n"); 732 return; 733 } 734 735 --argc; 736 ++argv; 737 init_printer(pp); 738 status = getprintcap(*argv, pp); 739 switch(status) { 740 default: 741 fatal(pp, pcaperr(status)); 742 case PCAPERR_NOTFOUND: 743 printf("unknown printer %s\n", *argv); 744 return; 745 case PCAPERR_TCOPEN: 746 printf("warning: %s: unresolved tc= reference(s)", *argv); 747 break; 748 case PCAPERR_SUCCESS: 749 break; 750 } 751 printf("%s:\n", pp->printer); 752 753 seteuid(euid); 754 if (chdir(pp->spool_dir) < 0) { 755 printf("\tcannot chdir to %s\n", pp->spool_dir); 756 goto out; 757 } 758 seteuid(uid); 759 nitems = getq(pp, &queue); 760 if (nitems == 0) 761 return; 762 changed = 0; 763 mtime = queue[0]->q_time; 764 for (i = argc; --i; ) { 765 if (doarg(argv[i]) == 0) { 766 printf("\tjob %s is not in the queue\n", argv[i]); 767 continue; 768 } else 769 changed++; 770 } 771 for (i = 0; i < nitems; i++) 772 free(queue[i]); 773 free(queue); 774 if (!changed) { 775 printf("\tqueue order unchanged\n"); 776 return; 777 } 778 /* 779 * Turn on the public execute bit of the lock file to 780 * get lpd to rebuild the queue after the current job. 781 */ 782 seteuid(euid); 783 if (changed && stat(pp->lock_file, &stbuf) >= 0) 784 (void) chmod(pp->lock_file, stbuf.st_mode | LFM_RESET_QUE); 785 786out: 787 seteuid(uid); 788} 789 790/* 791 * Reposition the job by changing the modification time of 792 * the control file. 793 */ 794static int 795touch(q) 796 struct queue *q; 797{ 798 struct timeval tvp[2]; 799 int ret; 800 801 tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 802 tvp[0].tv_usec = tvp[1].tv_usec = 0; 803 seteuid(euid); 804 ret = utimes(q->q_name, tvp); 805 seteuid(uid); 806 return (ret); 807} 808 809/* 810 * Checks if specified job name is in the printer's queue. 811 * Returns: negative (-1) if argument name is not in the queue. 812 */ 813static int 814doarg(job) 815 char *job; 816{ 817 register struct queue **qq; 818 register int jobnum, n; 819 register char *cp, *machine; 820 int cnt = 0; 821 FILE *fp; 822 823 /* 824 * Look for a job item consisting of system name, colon, number 825 * (example: ucbarpa:114) 826 */ 827 if ((cp = strchr(job, ':')) != NULL) { 828 machine = job; 829 *cp++ = '\0'; 830 job = cp; 831 } else 832 machine = NULL; 833 834 /* 835 * Check for job specified by number (example: 112 or 235ucbarpa). 836 */ 837 if (isdigit(*job)) { 838 jobnum = 0; 839 do 840 jobnum = jobnum * 10 + (*job++ - '0'); 841 while (isdigit(*job)); 842 for (qq = queue + nitems; --qq >= queue; ) { 843 n = 0; 844 for (cp = (*qq)->q_name+3; isdigit(*cp); ) 845 n = n * 10 + (*cp++ - '0'); 846 if (jobnum != n) 847 continue; 848 if (*job && strcmp(job, cp) != 0) 849 continue; 850 if (machine != NULL && strcmp(machine, cp) != 0) 851 continue; 852 if (touch(*qq) == 0) { 853 printf("\tmoved %s\n", (*qq)->q_name); 854 cnt++; 855 } 856 } 857 return(cnt); 858 } 859 /* 860 * Process item consisting of owner's name (example: henry). 861 */ 862 for (qq = queue + nitems; --qq >= queue; ) { 863 seteuid(euid); 864 fp = fopen((*qq)->q_name, "r"); 865 seteuid(uid); 866 if (fp == NULL) 867 continue; 868 while (getline(fp) > 0) 869 if (line[0] == 'P') 870 break; 871 (void) fclose(fp); 872 if (line[0] != 'P' || strcmp(job, line+1) != 0) 873 continue; 874 if (touch(*qq) == 0) { 875 printf("\tmoved %s\n", (*qq)->q_name); 876 cnt++; 877 } 878 } 879 return(cnt); 880} 881 882/* 883 * Enable everything and start printer (undo `down'). 884 */ 885void 886up(pp) 887 struct printer *pp; 888{ 889 startpr(pp, 2); 890}
|