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