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