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