1 #ifndef lint 2 static char sccsid[] = "@(#)cmds.c 4.8 (Berkeley) 07/27/83"; 3 #endif 4 5 /* 6 * lpc -- line printer control program 7 */ 8 9 #include "lp.h" 10 11 /* 12 * kill an existing daemon and disable printing. 13 */ 14 abort(argc, argv) 15 char *argv[]; 16 { 17 register int c, status; 18 register char *cp1, *cp2; 19 char prbuf[100]; 20 21 if (argc == 1) { 22 printf("Usage: abort {all | printer ...}\n"); 23 return; 24 } 25 if (argc == 2 && !strcmp(argv[1], "all")) { 26 printer = prbuf; 27 while (getprent(line) > 0) { 28 cp1 = prbuf; 29 cp2 = line; 30 while ((c = *cp2++) && c != '|' && c != ':') 31 *cp1++ = c; 32 *cp1 = '\0'; 33 abortpr(); 34 } 35 return; 36 } 37 while (--argc) { 38 printer = *++argv; 39 if ((status = pgetent(line, printer)) < 0) { 40 printf("cannot open printer description file\n"); 41 continue; 42 } else if (status == 0) { 43 printf("unknown printer %s\n", printer); 44 continue; 45 } 46 abortpr(); 47 } 48 } 49 50 abortpr() 51 { 52 register FILE *fp; 53 struct stat stbuf; 54 int pid, fd; 55 56 bp = pbuf; 57 if ((SD = pgetstr("sd", &bp)) == NULL) 58 SD = DEFSPOOL; 59 if ((LO = pgetstr("lo", &bp)) == NULL) 60 LO = DEFLOCK; 61 (void) sprintf(line, "%s/%s", SD, LO); 62 printf("%s:\n", printer); 63 64 /* 65 * Turn on the owner execute bit of the lock file to disable printing. 66 */ 67 if (stat(line, &stbuf) >= 0) { 68 if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 69 printf("\tcannot disable printing\n"); 70 else 71 printf("\tprinting disabled\n"); 72 } else if (errno == ENOENT) { 73 if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 74 printf("\tcannot create lock file\n"); 75 else { 76 (void) close(fd); 77 printf("\tprinting disabled\n"); 78 printf("\tno daemon to abort\n"); 79 } 80 return; 81 } else { 82 printf("\tcannot stat lock file\n"); 83 return; 84 } 85 /* 86 * Kill the current daemon to stop printing now. 87 */ 88 if ((fp = fopen(line, "r")) == NULL) { 89 printf("\tcannot open lock file\n"); 90 return; 91 } 92 if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { 93 (void) fclose(fp); /* unlocks as well */ 94 printf("\tno daemon to abort\n"); 95 return; 96 } 97 (void) fclose(fp); 98 if (kill(pid = atoi(line), SIGINT) < 0) 99 printf("\tWarning: daemon (pid %d) not killed\n", pid); 100 else 101 printf("\tdaemon (pid %d) killed\n", pid); 102 } 103 104 /* 105 * Remove all spool files and temporaries from the spooling area. 106 */ 107 clean(argc, argv) 108 char *argv[]; 109 { 110 register int c, status; 111 register char *cp1, *cp2; 112 char prbuf[100]; 113 114 if (argc == 1) { 115 printf("Usage: clean {all | printer ...}\n"); 116 return; 117 } 118 if (argc == 2 && !strcmp(argv[1], "all")) { 119 printer = prbuf; 120 while (getprent(line) > 0) { 121 cp1 = prbuf; 122 cp2 = line; 123 while ((c = *cp2++) && c != '|' && c != ':') 124 *cp1++ = c; 125 *cp1 = '\0'; 126 cleanpr(); 127 } 128 return; 129 } 130 while (--argc) { 131 printer = *++argv; 132 if ((status = pgetent(line, printer)) < 0) { 133 printf("cannot open printer description file\n"); 134 continue; 135 } else if (status == 0) { 136 printf("unknown printer %s\n", printer); 137 continue; 138 } 139 cleanpr(); 140 } 141 } 142 143 cleanpr() 144 { 145 register int c; 146 register DIR *dirp; 147 register struct direct *dp; 148 char *cp, *cp1; 149 150 bp = pbuf; 151 if ((SD = pgetstr("sd", &bp)) == NULL) 152 SD = DEFSPOOL; 153 for (cp = line, cp1 = SD; *cp++ = *cp1++; ); 154 cp[-1] = '/'; 155 printf("%s:\n", printer); 156 157 if ((dirp = opendir(SD)) == NULL) { 158 printf("\tcannot examine spool directory\n"); 159 return; 160 } 161 while ((dp = readdir(dirp)) != NULL) { 162 c = dp->d_name[0]; 163 if ((c == 'c' || c == 't' || c == 'd') && dp->d_name[1]=='f') { 164 strcpy(cp, dp->d_name); 165 if (unlink(line) < 0) 166 printf("\tcannot remove %s\n", line); 167 else 168 printf("\tremoved %s\n", line); 169 } 170 } 171 closedir(dirp); 172 } 173 174 /* 175 * Enable queuing to the printer (allow lpr's). 176 */ 177 enable(argc, argv) 178 char *argv[]; 179 { 180 register int c, status; 181 register char *cp1, *cp2; 182 char prbuf[100]; 183 184 if (argc == 1) { 185 printf("Usage: enable {all | printer ...}\n"); 186 return; 187 } 188 if (argc == 2 && !strcmp(argv[1], "all")) { 189 printer = prbuf; 190 while (getprent(line) > 0) { 191 cp1 = prbuf; 192 cp2 = line; 193 while ((c = *cp2++) && c != '|' && c != ':') 194 *cp1++ = c; 195 *cp1 = '\0'; 196 enablepr(); 197 } 198 return; 199 } 200 while (--argc) { 201 printer = *++argv; 202 if ((status = pgetent(line, printer)) < 0) { 203 printf("cannot open printer description file\n"); 204 continue; 205 } else if (status == 0) { 206 printf("unknown printer %s\n", printer); 207 continue; 208 } 209 enablepr(); 210 } 211 } 212 213 enablepr() 214 { 215 struct stat stbuf; 216 217 bp = pbuf; 218 if ((SD = pgetstr("sd", &bp)) == NULL) 219 SD = DEFSPOOL; 220 if ((LO = pgetstr("lo", &bp)) == NULL) 221 LO = DEFLOCK; 222 (void) sprintf(line, "%s/%s", SD, LO); 223 printf("%s:\n", printer); 224 225 /* 226 * Turn off the group execute bit of the lock file to enable queuing. 227 */ 228 if (stat(line, &stbuf) >= 0) { 229 if (chmod(line, stbuf.st_mode & 0767) < 0) 230 printf("\tcannot enable queuing\n"); 231 else 232 printf("\tqueuing enabled\n"); 233 } 234 } 235 236 /* 237 * Disable queuing. 238 */ 239 disable(argc, argv) 240 char *argv[]; 241 { 242 register int c, status; 243 register char *cp1, *cp2; 244 char prbuf[100]; 245 246 if (argc == 1) { 247 printf("Usage: disable {all | printer ...}\n"); 248 return; 249 } 250 if (argc == 2 && !strcmp(argv[1], "all")) { 251 printer = prbuf; 252 while (getprent(line) > 0) { 253 cp1 = prbuf; 254 cp2 = line; 255 while ((c = *cp2++) && c != '|' && c != ':') 256 *cp1++ = c; 257 *cp1 = '\0'; 258 disablepr(); 259 } 260 return; 261 } 262 while (--argc) { 263 printer = *++argv; 264 if ((status = pgetent(line, printer)) < 0) { 265 printf("cannot open printer description file\n"); 266 continue; 267 } else if (status == 0) { 268 printf("unknown printer %s\n", printer); 269 continue; 270 } 271 disablepr(); 272 } 273 } 274 275 disablepr() 276 { 277 register int fd; 278 struct stat stbuf; 279 280 bp = pbuf; 281 if ((SD = pgetstr("sd", &bp)) == NULL) 282 SD = DEFSPOOL; 283 if ((LO = pgetstr("lo", &bp)) == NULL) 284 LO = DEFLOCK; 285 (void) sprintf(line, "%s/%s", SD, LO); 286 printf("%s:\n", printer); 287 /* 288 * Turn on the group execute bit of the lock file to disable queuing. 289 */ 290 if (stat(line, &stbuf) >= 0) { 291 if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0) 292 printf("\tcannot disable queuing\n"); 293 else 294 printf("\tqueuing disabled\n"); 295 } else if (errno == ENOENT) { 296 if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0) 297 printf("\tcannot create lock file\n"); 298 else { 299 (void) close(fd); 300 printf("\tqueuing disabled\n"); 301 } 302 return; 303 } else 304 printf("\tcannot stat lock file\n"); 305 } 306 307 /* 308 * Exit lpc 309 */ 310 quit(argc, argv) 311 char *argv[]; 312 { 313 exit(0); 314 } 315 316 /* 317 * Startup the daemon. 318 */ 319 restart(argc, argv) 320 char *argv[]; 321 { 322 register int c, status; 323 register char *cp1, *cp2; 324 char prbuf[100]; 325 326 if (argc == 1) { 327 printf("Usage: restart {all | printer ...}\n"); 328 return; 329 } 330 gethostname(host, sizeof(host)); 331 if (argc == 2 && !strcmp(argv[1], "all")) { 332 printer = prbuf; 333 while (getprent(line) > 0) { 334 cp1 = prbuf; 335 cp2 = line; 336 while ((c = *cp2++) && c != '|' && c != ':') 337 *cp1++ = c; 338 *cp1 = '\0'; 339 startpr(0); 340 } 341 return; 342 } 343 while (--argc) { 344 printer = *++argv; 345 if ((status = pgetent(line, printer)) < 0) { 346 printf("cannot open printer description file\n"); 347 continue; 348 } else if (status == 0) { 349 printf("unknown printer %s\n", printer); 350 continue; 351 } 352 startpr(0); 353 } 354 } 355 356 /* 357 * Enable printing on the specified printer and startup the daemon. 358 */ 359 start(argc, argv) 360 char *argv[]; 361 { 362 register int c, status; 363 register char *cp1, *cp2; 364 char prbuf[100]; 365 366 if (argc == 1) { 367 printf("Usage: start {all | printer ...}\n"); 368 return; 369 } 370 gethostname(host, sizeof(host)); 371 if (argc == 2 && !strcmp(argv[1], "all")) { 372 printer = prbuf; 373 while (getprent(line) > 0) { 374 cp1 = prbuf; 375 cp2 = line; 376 while ((c = *cp2++) && c != '|' && c != ':') 377 *cp1++ = c; 378 *cp1 = '\0'; 379 startpr(1); 380 } 381 return; 382 } 383 while (--argc) { 384 printer = *++argv; 385 if ((status = pgetent(line, printer)) < 0) { 386 printf("cannot open printer description file\n"); 387 continue; 388 } else if (status == 0) { 389 printf("unknown printer %s\n", printer); 390 continue; 391 } 392 startpr(1); 393 } 394 } 395 396 startpr(enable) 397 { 398 struct stat stbuf; 399 400 bp = pbuf; 401 if ((SD = pgetstr("sd", &bp)) == NULL) 402 SD = DEFSPOOL; 403 if ((LO = pgetstr("lo", &bp)) == NULL) 404 LO = DEFLOCK; 405 (void) sprintf(line, "%s/%s", SD, LO); 406 printf("%s:\n", printer); 407 408 /* 409 * Turn off the owner execute bit of the lock file to enable printing. 410 */ 411 if (enable && stat(line, &stbuf) >= 0) { 412 if (chmod(line, stbuf.st_mode & 0677) < 0) 413 printf("\tcannot enable printing\n"); 414 else 415 printf("\tprinting enabled\n"); 416 } 417 if (!startdaemon(printer)) 418 printf("\tcouldn't start daemon\n"); 419 else 420 printf("\tdaemon started\n"); 421 } 422 423 /* 424 * Print the status of each queue listed or all the queues. 425 */ 426 status(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 printer = prbuf; 435 while (getprent(line) > 0) { 436 cp1 = prbuf; 437 cp2 = line; 438 while ((c = *cp2++) && c != '|' && c != ':') 439 *cp1++ = c; 440 *cp1 = '\0'; 441 prstat(); 442 } 443 return; 444 } 445 while (--argc) { 446 printer = *++argv; 447 if ((status = pgetent(line, printer)) < 0) { 448 printf("cannot open printer description file\n"); 449 continue; 450 } else if (status == 0) { 451 printf("unknown printer %s\n", printer); 452 continue; 453 } 454 prstat(); 455 } 456 } 457 458 /* 459 * Print the status of the printer queue. 460 */ 461 prstat() 462 { 463 struct stat stbuf; 464 register int fd, i; 465 register struct direct *dp; 466 DIR *dirp; 467 468 bp = pbuf; 469 if ((SD = pgetstr("sd", &bp)) == NULL) 470 SD = 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 (void) sprintf(line, "%s/%s", SD, LO); 477 if (stat(line, &stbuf) >= 0) { 478 printf("\tqueuing is %s\n", 479 (stbuf.st_mode & 010) ? "disabled" : "enabled"); 480 printf("\tprinting is %s\n", 481 (stbuf.st_mode & 0100) ? "disabled" : "enabled"); 482 } else { 483 printf("\tqueuing is enabled\n"); 484 printf("\tprinting is enabled\n"); 485 } 486 if ((dirp = opendir(SD)) == NULL) { 487 printf("\tcannot examine spool directory\n"); 488 return; 489 } 490 i = 0; 491 while ((dp = readdir(dirp)) != NULL) { 492 if (*dp->d_name == 'c' && dp->d_name[1] == 'f') 493 i++; 494 } 495 closedir(dirp); 496 if (i == 0) 497 printf("\tno entries\n"); 498 else if (i == 1) 499 printf("\t1 entry in spool area\n"); 500 else 501 printf("\t%d entries in spool area\n", i); 502 fd = open(line, O_RDONLY); 503 if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { 504 (void) close(fd); /* unlocks as well */ 505 printf("\tno daemon present\n"); 506 return; 507 } 508 (void) close(fd); 509 putchar('\t'); 510 (void) sprintf(line, "%s/%s", SD, ST); 511 fd = open(line, O_RDONLY); 512 if (fd >= 0) { 513 (void) flock(fd, LOCK_SH); 514 while ((i = read(fd, line, sizeof(line))) > 0) 515 (void) fwrite(line, 1, i, stdout); 516 (void) close(fd); /* unlocks as well */ 517 } 518 } 519 520 /* 521 * Stop the specified daemon after completing the current job and disable 522 * printing. 523 */ 524 stop(argc, argv) 525 char *argv[]; 526 { 527 register int c, status; 528 register char *cp1, *cp2; 529 char prbuf[100]; 530 531 if (argc == 1) { 532 printf("Usage: stop {all | printer ...}\n"); 533 return; 534 } 535 if (argc == 2 && !strcmp(argv[1], "all")) { 536 printer = prbuf; 537 while (getprent(line) > 0) { 538 cp1 = prbuf; 539 cp2 = line; 540 while ((c = *cp2++) && c != '|' && c != ':') 541 *cp1++ = c; 542 *cp1 = '\0'; 543 stoppr(); 544 } 545 return; 546 } 547 while (--argc) { 548 printer = *++argv; 549 if ((status = pgetent(line, printer)) < 0) { 550 printf("cannot open printer description file\n"); 551 continue; 552 } else if (status == 0) { 553 printf("unknown printer %s\n", printer); 554 continue; 555 } 556 stoppr(); 557 } 558 } 559 560 stoppr() 561 { 562 register int fd; 563 struct stat stbuf; 564 565 bp = pbuf; 566 if ((SD = pgetstr("sd", &bp)) == NULL) 567 SD = DEFSPOOL; 568 if ((LO = pgetstr("lo", &bp)) == NULL) 569 LO = DEFLOCK; 570 (void) sprintf(line, "%s/%s", SD, LO); 571 printf("%s:\n", printer); 572 573 /* 574 * Turn on the owner execute bit of the lock file to disable printing. 575 */ 576 if (stat(line, &stbuf) >= 0) { 577 if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) 578 printf("\tcannot disable printing\n"); 579 else 580 printf("\tprinting disabled\n"); 581 } else if (errno == ENOENT) { 582 if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) 583 printf("\tcannot create lock file\n"); 584 else { 585 (void) close(fd); 586 printf("\tprinting disabled\n"); 587 } 588 } else 589 printf("\tcannot stat lock file\n"); 590 } 591 592 /* 593 * Put the specified jobs at the top of printer queue. 594 */ 595 topq(argc, argv) 596 char *argv[]; 597 { 598 register int status, nitems, n; 599 struct stat stbuf; 600 register char *cfname; 601 struct queue **queue; 602 int changed = 0; 603 604 if (argc == 1) { 605 printf("Usage: topq printer [jobnum ...] [user ...]\n"); 606 return; 607 } 608 609 --argc; 610 printer = *++argv; 611 status = pgetent(line, printer); 612 if (status < 0) { 613 printf("cannot open printer description file\n"); 614 return; 615 } else if (status == 0) { 616 printf("%s: unknown printer\n", printer); 617 return; 618 } 619 bp = pbuf; 620 if ((SD = pgetstr("sd", &bp)) == NULL) 621 SD = DEFSPOOL; 622 if ((LO = pgetstr("lo", &bp)) == NULL) 623 LO = DEFLOCK; 624 printf("%s:\n", printer); 625 626 if (chdir(SD) < 0) { 627 printf("\tcannot chdir to %s\n", SD); 628 return; 629 } 630 nitems = getq(&queue); 631 while (--argc) { 632 if ((n = inqueue(*++argv, queue, nitems)) < 0) { 633 printf("\tjob %s is not in the queue\n", *argv); 634 continue; 635 } 636 /* 637 * Reposition the job by changing the modification time of 638 * the control file. 639 */ 640 if (touch(queue[n]->q_name)) { 641 free(queue[n]); 642 queue[n] = NULL; 643 changed++; 644 } 645 } 646 /* 647 * Put the remaining jobs at the end of the queue. 648 */ 649 for (n = 0; n < nitems; n++) { 650 if (queue[n] == NULL) 651 continue; 652 cfname = queue[n]->q_name; 653 if (changed) 654 touch(cfname); 655 free(cfname); 656 } 657 free(queue); 658 printf("\tqueue order %s\n", changed ? "changed" : "unchanged"); 659 /* 660 * Turn on the public execute bit of the lock file to 661 * get lpd to rebuild the queue after the current job. 662 */ 663 if (changed && stat(LO, &stbuf) >= 0) 664 (void) chmod(LO, (stbuf.st_mode & 0777) | 01); 665 } 666 667 /* 668 * Change the modification time of the file. 669 * Returns boolean if successful. 670 */ 671 touch(cfname) 672 char *cfname; 673 { 674 register int fd; 675 676 fd = open(cfname, O_RDWR); 677 if (fd < 0) { 678 printf("\tcannot open %s\n", cfname); 679 return(0); 680 } 681 (void) read(fd, line, 1); 682 (void) lseek(fd, 0L, 0); /* set pointer back to top of file */ 683 (void) write(fd, line, 1); 684 (void) close(fd); 685 sleep(1); /* so times will be different */ 686 return(1); 687 } 688 689 /* 690 * Checks if specified job name is in the printer's queue. 691 * Returns: negative (-1) if argument name is not in the queue. 692 * 0 to n: array index of pointer to argument name. 693 */ 694 inqueue(job, queue, nitems) 695 char *job; 696 struct queue *queue[]; 697 int nitems; 698 { 699 register struct queue *q; 700 register int n, jobnum; 701 register char *cp; 702 FILE *fp; 703 704 jobnum = -1; 705 if (isdigit(*job)) { 706 jobnum = 0; 707 do 708 jobnum = jobnum * 10 + (*job++ - '0'); 709 while (isdigit(*job)); 710 } 711 712 while (--nitems >= 0) { 713 if ((q = queue[nitems]) == NULL) 714 continue; 715 /* this needs to be fixed since the same number can be used 716 by different machines (i.e. jobnum & machine) */ 717 if (jobnum >= 0) { 718 n = 0; 719 for (cp = q->q_name+3; isdigit(*cp); ) 720 n = n * 10 + (*cp++ - '0'); 721 if (jobnum == n) 722 return(nitems); 723 continue; 724 } 725 /* 726 * Read cf file for owner's name 727 */ 728 if ((fp = fopen(q->q_name, "r")) == NULL) 729 continue; 730 while (getline(fp) > 0) { 731 if (line[0] == 'P' && !strcmp(job, line+1)) { 732 (void) fclose(fp); 733 return(nitems); 734 } 735 } 736 (void) fclose(fp); 737 } 738 return(-1); 739 } 740