1 #ifndef lint 2 static char sccsid[] = "@(#)cmds.c 4.9 (Berkeley) 12/16/83"; 3 #endif 4 5 /* 6 * lpc -- line printer control program -- commands: 7 */ 8 9 #include "lp.h" 10 #include <sys/time.h> 11 12 /* 13 * kill an existing daemon and disable printing. 14 */ 15 abort(argc, argv) 16 char *argv[]; 17 { 18 register int c, status; 19 register char *cp1, *cp2; 20 char prbuf[100]; 21 22 if (argc == 1) { 23 printf("Usage: abort {all | printer ...}\n"); 24 return; 25 } 26 if (argc == 2 && !strcmp(argv[1], "all")) { 27 printer = prbuf; 28 while (getprent(line) > 0) { 29 cp1 = prbuf; 30 cp2 = line; 31 while ((c = *cp2++) && c != '|' && c != ':') 32 *cp1++ = c; 33 *cp1 = '\0'; 34 abortpr(); 35 } 36 return; 37 } 38 while (--argc) { 39 printer = *++argv; 40 if ((status = pgetent(line, printer)) < 0) { 41 printf("cannot open printer description file\n"); 42 continue; 43 } else if (status == 0) { 44 printf("unknown printer %s\n", printer); 45 continue; 46 } 47 abortpr(); 48 } 49 } 50 51 abortpr() 52 { 53 register FILE *fp; 54 struct stat stbuf; 55 int pid, fd; 56 57 bp = pbuf; 58 if ((SD = pgetstr("sd", &bp)) == NULL) 59 SD = DEFSPOOL; 60 if ((LO = pgetstr("lo", &bp)) == NULL) 61 LO = DEFLOCK; 62 (void) sprintf(line, "%s/%s", SD, LO); 63 printf("%s:\n", printer); 64 65 /* 66 * Turn on the owner execute bit of the lock file to disable printing. 67 */ 68 if (stat(line, &stbuf) >= 0) { 69 if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 70 printf("\tcannot disable printing\n"); 71 else 72 printf("\tprinting disabled\n"); 73 } else if (errno == ENOENT) { 74 if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 75 printf("\tcannot create lock file\n"); 76 else { 77 (void) close(fd); 78 printf("\tprinting disabled\n"); 79 printf("\tno daemon to abort\n"); 80 } 81 return; 82 } else { 83 printf("\tcannot stat lock file\n"); 84 return; 85 } 86 /* 87 * Kill the current daemon to stop printing now. 88 */ 89 if ((fp = fopen(line, "r")) == NULL) { 90 printf("\tcannot open lock file\n"); 91 return; 92 } 93 if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 94 (void) fclose(fp); /* unlocks as well */ 95 printf("\tno daemon to abort\n"); 96 return; 97 } 98 (void) fclose(fp); 99 if (kill(pid = atoi(line), SIGINT) < 0) 100 printf("\tWarning: daemon (pid %d) not killed\n", pid); 101 else 102 printf("\tdaemon (pid %d) killed\n", pid); 103 } 104 105 /* 106 * Remove all spool files and temporaries from the spooling area. 107 */ 108 clean(argc, argv) 109 char *argv[]; 110 { 111 register int c, status; 112 register char *cp1, *cp2; 113 char prbuf[100]; 114 115 if (argc == 1) { 116 printf("Usage: clean {all | printer ...}\n"); 117 return; 118 } 119 if (argc == 2 && !strcmp(argv[1], "all")) { 120 printer = prbuf; 121 while (getprent(line) > 0) { 122 cp1 = prbuf; 123 cp2 = line; 124 while ((c = *cp2++) && c != '|' && c != ':') 125 *cp1++ = c; 126 *cp1 = '\0'; 127 cleanpr(); 128 } 129 return; 130 } 131 while (--argc) { 132 printer = *++argv; 133 if ((status = pgetent(line, printer)) < 0) { 134 printf("cannot open printer description file\n"); 135 continue; 136 } else if (status == 0) { 137 printf("unknown printer %s\n", printer); 138 continue; 139 } 140 cleanpr(); 141 } 142 } 143 144 select(d) 145 struct direct *d; 146 { 147 int c = d->d_name[0]; 148 149 if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') 150 return(1); 151 return(0); 152 } 153 154 /* 155 * Comparison routine for scandir. Sort by job number and machine, then 156 * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. 157 */ 158 sortq(d1, d2) 159 struct direct **d1, **d2; 160 { 161 int c1, c2; 162 163 if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) 164 return(c1); 165 c1 = (*d1)->d_name[0]; 166 c2 = (*d2)->d_name[0]; 167 if (c1 == c2) 168 return((*d1)->d_name[2] - (*d2)->d_name[2]); 169 if (c1 == 'c') 170 return(-1); 171 if (c1 == 'd' || c2 == 'c') 172 return(1); 173 return(-1); 174 } 175 176 /* 177 * Remove incomplete jobs from spooling area. 178 */ 179 cleanpr() 180 { 181 register int i, n; 182 register char *cp, *cp1, *lp; 183 struct direct **queue; 184 int nitems; 185 186 bp = pbuf; 187 if ((SD = pgetstr("sd", &bp)) == NULL) 188 SD = DEFSPOOL; 189 printf("%s:\n", printer); 190 191 for (lp = line, cp = SD; *lp++ = *cp++; ) 192 ; 193 lp[-1] = '/'; 194 195 nitems = scandir(SD, &queue, select, sortq); 196 if (nitems < 0) { 197 printf("\tcannot examine spool directory\n"); 198 return; 199 } 200 if (nitems == 0) 201 return; 202 i = 0; 203 do { 204 cp = queue[i]->d_name; 205 if (*cp == 'c') { 206 n = 0; 207 while (i + 1 < nitems) { 208 cp1 = queue[i + 1]->d_name; 209 if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) 210 break; 211 i++; 212 n++; 213 } 214 if (n == 0) { 215 strcpy(lp, cp); 216 unlinkf(line); 217 } 218 } else { 219 /* 220 * Must be a df with no cf (otherwise, it would have 221 * been skipped above) or a tf file (which can always 222 * be removed). 223 */ 224 strcpy(lp, cp); 225 unlinkf(line); 226 } 227 } while (++i < nitems); 228 } 229 230 unlinkf(name) 231 char *name; 232 { 233 if (unlink(name) < 0) 234 printf("\tcannot remove %s\n", name); 235 else 236 printf("\tremoved %s\n", name); 237 } 238 239 /* 240 * Enable queuing to the printer (allow lpr's). 241 */ 242 enable(argc, argv) 243 char *argv[]; 244 { 245 register int c, status; 246 register char *cp1, *cp2; 247 char prbuf[100]; 248 249 if (argc == 1) { 250 printf("Usage: enable {all | printer ...}\n"); 251 return; 252 } 253 if (argc == 2 && !strcmp(argv[1], "all")) { 254 printer = prbuf; 255 while (getprent(line) > 0) { 256 cp1 = prbuf; 257 cp2 = line; 258 while ((c = *cp2++) && c != '|' && c != ':') 259 *cp1++ = c; 260 *cp1 = '\0'; 261 enablepr(); 262 } 263 return; 264 } 265 while (--argc) { 266 printer = *++argv; 267 if ((status = pgetent(line, printer)) < 0) { 268 printf("cannot open printer description file\n"); 269 continue; 270 } else if (status == 0) { 271 printf("unknown printer %s\n", printer); 272 continue; 273 } 274 enablepr(); 275 } 276 } 277 278 enablepr() 279 { 280 struct stat stbuf; 281 282 bp = pbuf; 283 if ((SD = pgetstr("sd", &bp)) == NULL) 284 SD = DEFSPOOL; 285 if ((LO = pgetstr("lo", &bp)) == NULL) 286 LO = DEFLOCK; 287 (void) sprintf(line, "%s/%s", SD, LO); 288 printf("%s:\n", printer); 289 290 /* 291 * Turn off the group execute bit of the lock file to enable queuing. 292 */ 293 if (stat(line, &stbuf) >= 0) { 294 if (chmod(line, stbuf.st_mode & 0767) < 0) 295 printf("\tcannot enable queuing\n"); 296 else 297 printf("\tqueuing enabled\n"); 298 } 299 } 300 301 /* 302 * Disable queuing. 303 */ 304 disable(argc, argv) 305 char *argv[]; 306 { 307 register int c, status; 308 register char *cp1, *cp2; 309 char prbuf[100]; 310 311 if (argc == 1) { 312 printf("Usage: disable {all | printer ...}\n"); 313 return; 314 } 315 if (argc == 2 && !strcmp(argv[1], "all")) { 316 printer = prbuf; 317 while (getprent(line) > 0) { 318 cp1 = prbuf; 319 cp2 = line; 320 while ((c = *cp2++) && c != '|' && c != ':') 321 *cp1++ = c; 322 *cp1 = '\0'; 323 disablepr(); 324 } 325 return; 326 } 327 while (--argc) { 328 printer = *++argv; 329 if ((status = pgetent(line, printer)) < 0) { 330 printf("cannot open printer description file\n"); 331 continue; 332 } else if (status == 0) { 333 printf("unknown printer %s\n", printer); 334 continue; 335 } 336 disablepr(); 337 } 338 } 339 340 disablepr() 341 { 342 register int fd; 343 struct stat stbuf; 344 345 bp = pbuf; 346 if ((SD = pgetstr("sd", &bp)) == NULL) 347 SD = DEFSPOOL; 348 if ((LO = pgetstr("lo", &bp)) == NULL) 349 LO = DEFLOCK; 350 (void) sprintf(line, "%s/%s", SD, LO); 351 printf("%s:\n", printer); 352 /* 353 * Turn on the group execute bit of the lock file to disable queuing. 354 */ 355 if (stat(line, &stbuf) >= 0) { 356 if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0) 357 printf("\tcannot disable queuing\n"); 358 else 359 printf("\tqueuing disabled\n"); 360 } else if (errno == ENOENT) { 361 if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0) 362 printf("\tcannot create lock file\n"); 363 else { 364 (void) close(fd); 365 printf("\tqueuing disabled\n"); 366 } 367 return; 368 } else 369 printf("\tcannot stat lock file\n"); 370 } 371 372 /* 373 * Exit lpc 374 */ 375 quit(argc, argv) 376 char *argv[]; 377 { 378 exit(0); 379 } 380 381 /* 382 * Startup the daemon. 383 */ 384 restart(argc, argv) 385 char *argv[]; 386 { 387 register int c, status; 388 register char *cp1, *cp2; 389 char prbuf[100]; 390 391 if (argc == 1) { 392 printf("Usage: restart {all | printer ...}\n"); 393 return; 394 } 395 gethostname(host, sizeof(host)); 396 if (argc == 2 && !strcmp(argv[1], "all")) { 397 printer = prbuf; 398 while (getprent(line) > 0) { 399 cp1 = prbuf; 400 cp2 = line; 401 while ((c = *cp2++) && c != '|' && c != ':') 402 *cp1++ = c; 403 *cp1 = '\0'; 404 startpr(0); 405 } 406 return; 407 } 408 while (--argc) { 409 printer = *++argv; 410 if ((status = pgetent(line, printer)) < 0) { 411 printf("cannot open printer description file\n"); 412 continue; 413 } else if (status == 0) { 414 printf("unknown printer %s\n", printer); 415 continue; 416 } 417 startpr(0); 418 } 419 } 420 421 /* 422 * Enable printing on the specified printer and startup the daemon. 423 */ 424 start(argc, argv) 425 char *argv[]; 426 { 427 register int c, status; 428 register char *cp1, *cp2; 429 char prbuf[100]; 430 431 if (argc == 1) { 432 printf("Usage: start {all | printer ...}\n"); 433 return; 434 } 435 gethostname(host, sizeof(host)); 436 if (argc == 2 && !strcmp(argv[1], "all")) { 437 printer = prbuf; 438 while (getprent(line) > 0) { 439 cp1 = prbuf; 440 cp2 = line; 441 while ((c = *cp2++) && c != '|' && c != ':') 442 *cp1++ = c; 443 *cp1 = '\0'; 444 startpr(1); 445 } 446 return; 447 } 448 while (--argc) { 449 printer = *++argv; 450 if ((status = pgetent(line, printer)) < 0) { 451 printf("cannot open printer description file\n"); 452 continue; 453 } else if (status == 0) { 454 printf("unknown printer %s\n", printer); 455 continue; 456 } 457 startpr(1); 458 } 459 } 460 461 startpr(enable) 462 { 463 struct stat stbuf; 464 465 bp = pbuf; 466 if ((SD = pgetstr("sd", &bp)) == NULL) 467 SD = DEFSPOOL; 468 if ((LO = pgetstr("lo", &bp)) == NULL) 469 LO = DEFLOCK; 470 (void) sprintf(line, "%s/%s", SD, LO); 471 printf("%s:\n", printer); 472 473 /* 474 * Turn off the owner execute bit of the lock file to enable printing. 475 */ 476 if (enable && stat(line, &stbuf) >= 0) { 477 if (chmod(line, stbuf.st_mode & 0677) < 0) 478 printf("\tcannot enable printing\n"); 479 else 480 printf("\tprinting enabled\n"); 481 } 482 if (!startdaemon(printer)) 483 printf("\tcouldn't start daemon\n"); 484 else 485 printf("\tdaemon started\n"); 486 } 487 488 /* 489 * Print the status of each queue listed or all the queues. 490 */ 491 status(argc, argv) 492 char *argv[]; 493 { 494 register int c, status; 495 register char *cp1, *cp2; 496 char prbuf[100]; 497 498 if (argc == 1) { 499 printer = prbuf; 500 while (getprent(line) > 0) { 501 cp1 = prbuf; 502 cp2 = line; 503 while ((c = *cp2++) && c != '|' && c != ':') 504 *cp1++ = c; 505 *cp1 = '\0'; 506 prstat(); 507 } 508 return; 509 } 510 while (--argc) { 511 printer = *++argv; 512 if ((status = pgetent(line, printer)) < 0) { 513 printf("cannot open printer description file\n"); 514 continue; 515 } else if (status == 0) { 516 printf("unknown printer %s\n", printer); 517 continue; 518 } 519 prstat(); 520 } 521 } 522 523 /* 524 * Print the status of the printer queue. 525 */ 526 prstat() 527 { 528 struct stat stbuf; 529 register int fd, i; 530 register struct direct *dp; 531 DIR *dirp; 532 533 bp = pbuf; 534 if ((SD = pgetstr("sd", &bp)) == NULL) 535 SD = DEFSPOOL; 536 if ((LO = pgetstr("lo", &bp)) == NULL) 537 LO = DEFLOCK; 538 if ((ST = pgetstr("st", &bp)) == NULL) 539 ST = DEFSTAT; 540 printf("%s:\n", printer); 541 (void) sprintf(line, "%s/%s", SD, LO); 542 if (stat(line, &stbuf) >= 0) { 543 printf("\tqueuing is %s\n", 544 (stbuf.st_mode & 010) ? "disabled" : "enabled"); 545 printf("\tprinting is %s\n", 546 (stbuf.st_mode & 0100) ? "disabled" : "enabled"); 547 } else { 548 printf("\tqueuing is enabled\n"); 549 printf("\tprinting is enabled\n"); 550 } 551 if ((dirp = opendir(SD)) == NULL) { 552 printf("\tcannot examine spool directory\n"); 553 return; 554 } 555 i = 0; 556 while ((dp = readdir(dirp)) != NULL) { 557 if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 558 i++; 559 } 560 closedir(dirp); 561 if (i == 0) 562 printf("\tno entries\n"); 563 else if (i == 1) 564 printf("\t1 entry in spool area\n"); 565 else 566 printf("\t%d entries in spool area\n", i); 567 fd = open(line, O_RDONLY); 568 if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 569 (void) close(fd); /* unlocks as well */ 570 printf("\tno daemon present\n"); 571 return; 572 } 573 (void) close(fd); 574 putchar('\t'); 575 (void) sprintf(line, "%s/%s", SD, ST); 576 fd = open(line, O_RDONLY); 577 if (fd >= 0) { 578 (void) flock(fd, LOCK_SH); 579 while ((i = read(fd, line, sizeof(line))) > 0) 580 (void) fwrite(line, 1, i, stdout); 581 (void) close(fd); /* unlocks as well */ 582 } 583 } 584 585 /* 586 * Stop the specified daemon after completing the current job and disable 587 * printing. 588 */ 589 stop(argc, argv) 590 char *argv[]; 591 { 592 register int c, status; 593 register char *cp1, *cp2; 594 char prbuf[100]; 595 596 if (argc == 1) { 597 printf("Usage: stop {all | printer ...}\n"); 598 return; 599 } 600 if (argc == 2 && !strcmp(argv[1], "all")) { 601 printer = prbuf; 602 while (getprent(line) > 0) { 603 cp1 = prbuf; 604 cp2 = line; 605 while ((c = *cp2++) && c != '|' && c != ':') 606 *cp1++ = c; 607 *cp1 = '\0'; 608 stoppr(); 609 } 610 return; 611 } 612 while (--argc) { 613 printer = *++argv; 614 if ((status = pgetent(line, printer)) < 0) { 615 printf("cannot open printer description file\n"); 616 continue; 617 } else if (status == 0) { 618 printf("unknown printer %s\n", printer); 619 continue; 620 } 621 stoppr(); 622 } 623 } 624 625 stoppr() 626 { 627 register int fd; 628 struct stat stbuf; 629 630 bp = pbuf; 631 if ((SD = pgetstr("sd", &bp)) == NULL) 632 SD = DEFSPOOL; 633 if ((LO = pgetstr("lo", &bp)) == NULL) 634 LO = DEFLOCK; 635 (void) sprintf(line, "%s/%s", SD, LO); 636 printf("%s:\n", printer); 637 638 /* 639 * Turn on the owner execute bit of the lock file to disable printing. 640 */ 641 if (stat(line, &stbuf) >= 0) { 642 if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 643 printf("\tcannot disable printing\n"); 644 else 645 printf("\tprinting disabled\n"); 646 } else if (errno == ENOENT) { 647 if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 648 printf("\tcannot create lock file\n"); 649 else { 650 (void) close(fd); 651 printf("\tprinting disabled\n"); 652 } 653 } else 654 printf("\tcannot stat lock file\n"); 655 } 656 657 struct queue **queue; 658 int nitems; 659 time_t mtime; 660 661 /* 662 * Put the specified jobs at the top of printer queue. 663 */ 664 topq(argc, argv) 665 char *argv[]; 666 { 667 register int n, i; 668 struct stat stbuf; 669 register char *cfname; 670 int status, changed; 671 672 if (argc < 3) { 673 printf("Usage: topq printer [jobnum ...] [user ...]\n"); 674 return; 675 } 676 677 --argc; 678 printer = *++argv; 679 status = pgetent(line, printer); 680 if (status < 0) { 681 printf("cannot open printer description file\n"); 682 return; 683 } else if (status == 0) { 684 printf("%s: unknown printer\n", printer); 685 return; 686 } 687 bp = pbuf; 688 if ((SD = pgetstr("sd", &bp)) == NULL) 689 SD = DEFSPOOL; 690 if ((LO = pgetstr("lo", &bp)) == NULL) 691 LO = DEFLOCK; 692 printf("%s:\n", printer); 693 694 if (chdir(SD) < 0) { 695 printf("\tcannot chdir to %s\n", SD); 696 return; 697 } 698 nitems = getq(&queue); 699 if (nitems == 0) 700 return; 701 changed = 0; 702 mtime = queue[0]->q_time; 703 for (i = argc; --i; ) { 704 if (doarg(argv[i]) == 0) { 705 printf("\tjob %s is not in the queue\n", argv[i]); 706 continue; 707 } else 708 changed++; 709 } 710 for (i = 0; i < nitems; i++) 711 free(queue[i]); 712 free(queue); 713 if (!changed) { 714 printf("\tqueue order unchanged\n"); 715 return; 716 } 717 /* 718 * Turn on the public execute bit of the lock file to 719 * get lpd to rebuild the queue after the current job. 720 */ 721 if (changed && stat(LO, &stbuf) >= 0) 722 (void) chmod(LO, (stbuf.st_mode & 0777) | 01); 723 } 724 725 /* 726 * Reposition the job by changing the modification time of 727 * the control file. 728 */ 729 touch(q) 730 struct queue *q; 731 { 732 struct timeval tvp[2]; 733 734 tvp[0].tv_sec = tvp[1].tv_sec = --mtime; 735 tvp[0].tv_usec = tvp[1].tv_usec = 0; 736 return(utimes(q->q_name, tvp)); 737 } 738 739 /* 740 * Checks if specified job name is in the printer's queue. 741 * Returns: negative (-1) if argument name is not in the queue. 742 */ 743 doarg(job) 744 char *job; 745 { 746 register struct queue **qq; 747 register int jobnum, n; 748 register char *cp, *machine; 749 int cnt = 0; 750 FILE *fp; 751 752 /* 753 * Look for a job item consisting of system name, colon, number 754 * (example: ucbarpa:114) 755 */ 756 if ((cp = index(job, ':')) != NULL) { 757 machine = job; 758 *cp++ = '\0'; 759 job = cp; 760 } else 761 machine = NULL; 762 763 /* 764 * Check for job specified by number (example: 112 or 235ucbarpa). 765 */ 766 if (isdigit(*job)) { 767 jobnum = 0; 768 do 769 jobnum = jobnum * 10 + (*job++ - '0'); 770 while (isdigit(*job)); 771 for (qq = queue + nitems; --qq >= queue; ) { 772 n = 0; 773 for (cp = (*qq)->q_name+3; isdigit(*cp); ) 774 n = n * 10 + (*cp++ - '0'); 775 if (jobnum != n) 776 continue; 777 if (*job && strcmp(job, cp) != 0) 778 continue; 779 if (machine != NULL && strcmp(machine, cp) != 0) 780 continue; 781 if (touch(*qq) == 0) { 782 printf("\tmoved %s\n", (*qq)->q_name); 783 cnt++; 784 } 785 } 786 return(cnt); 787 } 788 /* 789 * Process item consisting of owner's name (example: henry). 790 */ 791 for (qq = queue + nitems; --qq >= queue; ) { 792 if ((fp = fopen((*qq)->q_name, "r")) == NULL) 793 continue; 794 while (getline(fp) > 0) 795 if (line[0] == 'P') 796 break; 797 (void) fclose(fp); 798 if (line[0] != 'P' || strcmp(job, line+1) != 0) 799 continue; 800 if (touch(*qq) == 0) { 801 printf("\tmoved %s\n", (*qq)->q_name); 802 cnt++; 803 } 804 } 805 return(cnt); 806 } 807