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