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