1 /* printjob.c 4.1 83/04/29 */ 2 /* 3 * printjob -- print jobs in the queue. 4 * 5 * NOTE: the lock file is used to pass information to lpq and lprm. 6 * it does not need to be removed because file locks are dynamic. 7 */ 8 9 #include "lp.h" 10 11 #define DORETURN 0 /* absorb fork error */ 12 #define DOABORT 1 /* abort if dofork fails */ 13 14 char title[80]; /* ``pr'' title */ 15 FILE *cfp; /* control file */ 16 int pfd; /* printer file descriptor */ 17 int ofd; /* output filter file descriptor */ 18 int lfd; /* lock file descriptor */ 19 int pid; /* pid of lpd process */ 20 int prchild; /* id of pr process */ 21 int child; /* id of any filters */ 22 int ofilter; /* id of output filter, if any */ 23 int tof = 1; /* top of form; init true if open does ff */ 24 int remote; /* non zero if sending files to remote */ 25 26 extern banner(); /* big character printer */ 27 char logname[32]; /* user's login name */ 28 char jobname[32]; /* job or file name */ 29 char class[32]; /* classification field */ 30 char width[10] = "-w"; /* page width for `pr' */ 31 char length[10] = "-l"; /* page length for `pr' */ 32 33 printjob() 34 { 35 struct stat stb; 36 register struct queue *q, **qp; 37 struct queue **queue; 38 register int i, nitems; 39 long pidoff; 40 extern int onintr(); 41 42 name = "printjob"; 43 init(); /* set up capabilities */ 44 (void) close(2); /* set up log file */ 45 (void) open(LF, FWRONLY|FAPPEND, 0); 46 dup2(2, 1); 47 pid = getpid(); 48 setpgrp(0, pid); 49 sigset(SIGINT, onintr); /* for use with lprm */ 50 51 /* 52 * uses short form file names 53 */ 54 if (chdir(SD) < 0) { 55 log("cannot chdir to %s", SD); 56 exit(1); 57 } 58 if ((lfd = open(LO, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK|FNBLOCK, 0664)) < 0) { 59 if (errno == EWOULDBLOCK) /* active deamon present */ 60 exit(0); 61 log("cannot create %s", LO); 62 exit(1); 63 } 64 /* 65 * write process id for others to know 66 */ 67 sprintf(line, "%u\n", pid); 68 pidoff = i = strlen(line); 69 if (write(lfd, line, i) != i) 70 log("cannot write daemon pid"); 71 /* 72 * acquire line printer or remote connection 73 */ 74 restart: 75 if (*LP) { 76 for (i = 1; ; i = i < 32 ? i << 1 : i) { 77 pfd = open(LP, RW ? FRDWR : FWRONLY, 0); 78 if (pfd >= 0) 79 break; 80 if (errno == ENOENT) { 81 log("cannot open %s", LP); 82 exit(1); 83 } 84 if (i == 1) 85 status("waiting for %s to become ready (offline ?)", printer); 86 sleep(i); 87 } 88 if (isatty(pfd)) 89 setty(); 90 status("%s is ready and printing", printer); 91 } else if (RM != NULL) { 92 for (i = 1; ; i = i < 512 ? i << 1 : i) { 93 pfd = getport(); 94 if (pfd >= 0) { 95 (void) sprintf(line, "\2%s\n", RP); 96 nitems = strlen(line); 97 if (write(pfd, line, nitems) != nitems) 98 break; 99 if (noresponse()) 100 (void) close(pfd); 101 else 102 break; 103 } 104 if (i == 1) 105 status("waiting for %s to come up", RM); 106 sleep(i); 107 } 108 status("sending to %s", RM); 109 remote = 1; 110 } else { 111 log("no line printer device or remote machine name"); 112 exit(1); 113 } 114 /* 115 * Start running as daemon instead of root 116 */ 117 setuid(DU); 118 /* 119 * Start up an output filter, if needed. 120 */ 121 if (OF) { 122 int p[2]; 123 char *cp; 124 125 pipe(p); 126 if ((ofilter = dofork(DOABORT)) == 0) { /* child */ 127 dup2(p[0], 0); /* pipe is std in */ 128 dup2(pfd, 1); /* printer is std out */ 129 for (i = 3; i < NOFILE; i++) 130 (void) close(i); 131 if ((cp = rindex(OF, '/')) == NULL) 132 cp = OF; 133 else 134 cp++; 135 execl(OF, cp, 0); 136 log("can't execl output filter %s", OF); 137 exit(1); 138 } 139 (void) close(p[0]); /* close input side */ 140 ofd = p[1]; /* use pipe for output */ 141 } else { 142 ofd = pfd; 143 ofilter = 0; 144 } 145 146 /* 147 * search the spool directory for work and sort by queue order. 148 */ 149 again: 150 if ((nitems = getq(&queue)) < 0) { 151 log("can't scan spool directory %s", SD); 152 exit(1); 153 } 154 if (nitems == 0) { /* EOF => no work to do */ 155 if (!SF && !tof) 156 (void) write(ofd, FF, strlen(FF)); 157 if (TR != NULL) /* output trailer */ 158 (void) write(ofd, TR, strlen(TR)); 159 exit(0); 160 } 161 162 /* 163 * we found something to do now do it -- 164 * write the name of the current control file into the lock file 165 * so the spool queue program can tell what we're working on 166 */ 167 for (qp = queue; nitems--; free((char *) q)) { 168 q = *qp++; 169 if (stat(q->q_name, &stb) < 0) 170 continue; 171 (void) lseek(lfd, pidoff, 0); 172 (void) sprintf(line, "%s\n", q->q_name); 173 i = strlen(line); 174 if (write(lfd, line, i) != i) 175 log("can't write (%d) control file name", errno); 176 if (!remote) 177 i = printit(q->q_name); 178 else 179 i = sendit(q->q_name); 180 if (i > 0) { /* restart daemon to reprint job */ 181 log("restarting"); 182 if (ofilter > 0) { 183 kill(ofilter, SIGCONT); /* to be sure */ 184 (void) close(ofd); 185 while ((i = wait(0)) > 0 && i != ofilter) 186 ; 187 ofilter = 0; 188 } 189 (void) close(pfd); 190 free((char *) q); 191 while (nitems--) 192 free((char *) *qp++); 193 free((char *) queue); 194 goto restart; 195 } 196 } 197 free((char *) queue); 198 goto again; 199 } 200 201 char fonts[4][50]; /* fonts for troff */ 202 203 static char ifonts[4][18] = { 204 "/usr/lib/vfont/R", 205 "/usr/lib/vfont/I", 206 "/usr/lib/vfont/B", 207 "/usr/lib/vfont/S" 208 }; 209 210 /* 211 * The remaining part is the reading of the control file (cf) 212 * and performing the various actions. 213 * Returns 0 if everthing was OK, 1 if we should try to reprint the job and 214 * -1 if a non-recoverable error occured. 215 */ 216 printit(file) 217 char *file; 218 { 219 register int i; 220 int bombed = 0; 221 222 /* 223 * open control file 224 */ 225 if ((cfp = fopen(file, "r")) == NULL) { 226 log("control file (%s) open failure <errno = %d>", file, errno); 227 return(0); 228 } 229 /* 230 * Reset troff fonts. 231 */ 232 for (i = 0; i < 4; i++) 233 strcpy(fonts[i], ifonts[i]); 234 235 /* 236 * read the control file for work to do 237 * 238 * file format -- first character in the line is a command 239 * rest of the line is the argument. 240 * valid commands are: 241 * 242 * J -- "job name" on banner page 243 * C -- "class name" on banner page 244 * L -- "literal" user's name to print on banner 245 * T -- "title" for pr 246 * H -- "host name" of machine where lpr was done 247 * P -- "person" user's login name 248 * I -- "indent" changes default indents driver 249 * must have stty/gtty avaialble 250 * f -- "file name" name of text file to print 251 * l -- "file name" text file with control chars 252 * p -- "file name" text file to print with pr(1) 253 * t -- "file name" troff(1) file to print 254 * d -- "file name" dvi file to print 255 * g -- "file name" plot(1G) file to print 256 * v -- "file name" plain raster file to print 257 * c -- "file name" cifplot file to print 258 * 1 -- "R font file" for troff 259 * 2 -- "I font file" for troff 260 * 3 -- "B font file" for troff 261 * 4 -- "S font file" for troff 262 * N -- "name" of file (used by lpq) 263 * U -- "unlink" name of file to remove 264 * (after we print it. (Pass 2 only)). 265 * M -- "mail" to user when done printing 266 * 267 * getline reads a line and expands tabs to blanks 268 */ 269 270 /* pass 1 */ 271 272 while (getline(cfp)) 273 switch (line[0]) { 274 case 'H': 275 strcpy(host, line+1); 276 if (class[0] == '\0') 277 strcpy(class, line+1); 278 continue; 279 280 case 'P': 281 strcpy(logname, line+1); 282 continue; 283 284 case 'J': 285 if (line[1] != '\0') 286 strcpy(jobname, line+1); 287 else 288 strcpy(jobname, " "); 289 continue; 290 291 case 'C': 292 if (line[1] != '\0') 293 strcpy(class, line+1); 294 else if (class[0] == '\0') 295 gethostname(class, sizeof (class)); 296 continue; 297 298 case 'T': /* header title for pr */ 299 strcpy(title, line+1); 300 continue; 301 302 case 'L': /* identification line */ 303 if (!SH) 304 banner(line+1, jobname); 305 continue; 306 307 case '1': /* troff fonts */ 308 case '2': 309 case '3': 310 case '4': 311 if (line[1] != '\0') 312 strcpy(fonts[line[0]-'1'], line+1); 313 continue; 314 315 case 'W': /* page width */ 316 strcpy(width+2, line+1); 317 continue; 318 319 default: /* some file to print */ 320 if ((i = print(line[0], line+1)) > 0) { 321 (void) fclose(cfp); 322 return(1); 323 } else if (i < 0) 324 bombed = 1; 325 title[0] = '\0'; 326 continue; 327 328 case 'I': 329 case 'N': 330 case 'U': 331 case 'M': 332 continue; 333 } 334 335 /* pass 2 */ 336 337 fseek(cfp, 0L, 0); 338 while (getline(cfp)) 339 switch (line[0]) { 340 case 'M': 341 sendmail(bombed); 342 continue; 343 344 case 'U': 345 (void) unlink(line+1); 346 } 347 /* 348 * clean-up incase another control file exists 349 */ 350 (void) fclose(cfp); 351 (void) unlink(file); 352 return(0); 353 } 354 355 /* 356 * Print a file. 357 * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, TF, CF, VF}. 358 * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 359 * 0 if all is well. 360 * Note: all filters take stdin as the file, stdout as the printer, 361 * stderr as the log file, and must not ignore SIGINT. 362 */ 363 print(format, file) 364 int format; 365 char *file; 366 { 367 register int n, fi, fo; 368 register char *prog; 369 char *av[15], buf[BUFSIZ]; 370 int pid, p[2], stopped = 0; 371 union wait status; 372 373 if ((fi = open(file, FRDONLY, 0)) < 0) { 374 log("%s: open failure <errno = %d>", file, errno); 375 return(-1); 376 } 377 if (!SF && !tof) { /* start on a fresh page */ 378 (void) write(ofd, FF, strlen(FF)); 379 tof = 1; 380 } 381 if (IF == NULL && (format == 'f' || format == 'l')) { 382 tof = 0; 383 while ((n = read(fi, buf, BUFSIZ)) > 0) 384 if (write(ofd, buf, n) != n) { 385 (void) close(fi); 386 return(1); 387 } 388 (void) close(fi); 389 return(0); 390 } 391 switch (format) { 392 case 'p': /* print file using 'pr' */ 393 if (IF == NULL) { /* use output filter */ 394 prog = PR; 395 av[0] = "pr"; 396 av[1] = width; 397 av[2] = length; 398 av[3] = "-h"; 399 av[4] = *title ? title : " "; 400 av[5] = 0; 401 fo = ofd; 402 goto start; 403 } 404 pipe(p); 405 if ((prchild = dofork(DORETURN)) == 0) { /* child */ 406 dup2(fi, 0); /* file is stdin */ 407 dup2(p[1], 1); /* pipe is stdout */ 408 for (n = 3; n < NOFILE; n++) 409 (void) close(n); 410 execl(PR, "pr", width, length, "-h", *title ? title : " ", 0); 411 log("cannot execl %s", PR); 412 exit(2); 413 } 414 (void) close(p[1]); /* close output side */ 415 (void) close(fi); 416 if (prchild < 0) { 417 prchild = 0; 418 (void) close(p[0]); 419 return(-1); 420 } 421 fi = p[0]; /* use pipe for input */ 422 case 'f': /* print plain text file */ 423 prog = IF; 424 av[1] = width; 425 av[2] = length; 426 n = 3; 427 break; 428 case 'l': /* like 'f' but pass control characters */ 429 prog = IF; 430 av[1] = "-l"; 431 av[2] = width; 432 av[3] = length; 433 n = 4; 434 break; 435 case 't': /* print troff output */ 436 case 'd': /* print troff output */ 437 (void) unlink(".railmag"); 438 if ((fo = creat(".railmag", 0666)) < 0) { 439 log("cannot create .railmag"); 440 (void) unlink(".railmag"); 441 } else { 442 for (n = 0; n < 4; n++) { 443 if (fonts[n][0] != '/') 444 (void) write(fo, "/usr/lib/vfont/", 15); 445 (void) write(fo, fonts[n], strlen(fonts[n])); 446 (void) write(fo, "\n", 1); 447 } 448 (void) close(fo); 449 } 450 prog = (format == 't') ? TF : DF; 451 n = 1; 452 break; 453 case 'c': /* print cifplot output */ 454 prog = CF; 455 n = 1; 456 break; 457 case 'g': /* print plot(1G) output */ 458 prog = GF; 459 n = 1; 460 break; 461 case 'v': /* print raster output */ 462 prog = VF; 463 n = 1; 464 break; 465 default: 466 (void) close(fi); 467 log("illegal format character '%c'", format); 468 return(-1); 469 } 470 if ((av[0] = rindex(prog, '/')) != NULL) 471 av[0]++; 472 else 473 av[0] = prog; 474 av[n++] = "-n"; 475 av[n++] = logname; 476 av[n++] = "-h"; 477 av[n++] = host; 478 av[n++] = AF; 479 av[n] = 0; 480 fo = pfd; 481 if (ofilter > 0) { /* stop output filter */ 482 write(ofd, "\031\1", 2); 483 while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter) 484 ; 485 if (status.w_stopval != WSTOPPED) { 486 (void) close(fi); 487 log("output filter died (%d)", status.w_retcode); 488 return(1); 489 } 490 stopped++; 491 } 492 start: 493 if ((child = dofork(DORETURN)) == 0) { /* child */ 494 dup2(fi, 0); 495 dup2(fo, 1); 496 for (n = 3; n < NOFILE; n++) 497 (void) close(n); 498 execv(prog, av); 499 log("cannot execl %s", prog); 500 exit(2); 501 } 502 (void) close(fi); 503 if (child < 0) 504 status.w_retcode = 100; 505 else 506 while ((pid = wait(&status)) > 0 && pid != child) 507 ; 508 child = 0; 509 prchild = 0; 510 if (stopped) { /* restart output filter */ 511 if (kill(ofilter, SIGCONT) < 0) { 512 log("cannot restart output filter"); 513 exit(1); 514 } 515 } 516 tof = 0; 517 if (!WIFEXITED(status) || status.w_retcode > 1) { 518 log("Daemon Filter '%c' Malfunction (%d)", format, status.w_retcode); 519 return(-1); 520 } else if (status.w_retcode == 1) 521 return(1); 522 tof = 1; 523 return(0); 524 } 525 526 /* 527 * Send the daemon control file (cf) and any data files. 528 * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 529 * 0 if all is well. 530 */ 531 sendit(file) 532 char *file; 533 { 534 register int linelen, err = 0; 535 char last[132]; 536 537 /* 538 * open control file 539 */ 540 if ((cfp = fopen(file, "r")) == NULL) { 541 log("control file (%s) open failure <errno = %d>", file, errno); 542 return(0); 543 } 544 /* 545 * read the control file for work to do 546 * 547 * file format -- first character in the line is a command 548 * rest of the line is the argument. 549 * commands of interest are: 550 * 551 * a-z -- "file name" name of file to print 552 * U -- "unlink" name of file to remove 553 * (after we print it. (Pass 2 only)). 554 */ 555 556 /* 557 * pass 1 558 */ 559 while (getline(cfp)) { 560 again: 561 if (line[0] >= 'a' && line[0] <= 'z') { 562 strcpy(last, line); 563 while (linelen = getline(cfp)) 564 if (strcmp(last, line)) 565 break; 566 if ((err = sendfile('\3', last+1)) > 0) { 567 (void) fclose(cfp); 568 return(1); 569 } else if (err) 570 break; 571 if (linelen) 572 goto again; 573 break; 574 } 575 } 576 if (!err && sendfile('\2', file) > 0) { 577 (void) fclose(cfp); 578 return(1); 579 } 580 /* 581 * pass 2 582 */ 583 fseek(cfp, 0L, 0); 584 while (getline(cfp)) 585 if (line[0] == 'U') 586 (void) unlink(line+1); 587 /* 588 * clean-up incase another control file exists 589 */ 590 (void) fclose(cfp); 591 (void) unlink(file); 592 return(0); 593 } 594 595 /* 596 * Send a data file to the remote machine and spool it. 597 * Return positive if we should try resending. 598 */ 599 sendfile(type, file) 600 char type, *file; 601 { 602 register int f, i, amt; 603 struct stat stb; 604 char buf[BUFSIZ]; 605 int sizerr; 606 607 if ((f = open(file, FRDONLY, 0)) < 0 || fstat(f, &stb) < 0) { 608 log("file (%s) open failure <errno = %d>", file, errno); 609 return(-1); 610 } 611 (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file); 612 amt = strlen(buf); 613 if (write(pfd, buf, amt) != amt) 614 return(1); 615 if (noresponse()) 616 return(1); 617 sizerr = 0; 618 for (i = 0; i < stb.st_size; i += BUFSIZ) { 619 amt = BUFSIZ; 620 if (i + amt > stb.st_size) 621 amt = stb.st_size - i; 622 if (sizerr == 0 && read(f, buf, amt) != amt) 623 sizerr = 1; 624 if (write(pfd, buf, amt) != amt) 625 return(1); 626 } 627 (void) close(f); 628 if (sizerr) { 629 log("%s: changed size", file); 630 (void) write(pfd, "\1", 1); /* tell recvjob to ignore this file */ 631 return(-1); 632 } 633 if (write(pfd, "", 1) != 1) 634 return(1); 635 if (noresponse()) 636 return(1); 637 return(0); 638 } 639 640 /* 641 * Check to make sure there have been no errors and that both programs 642 * are in sync with eachother. 643 * Return non-zero if the connection was lost. 644 */ 645 static 646 noresponse() 647 { 648 char resp; 649 650 if (read(pfd, &resp, 1) != 1 || resp != '\0') { 651 log("lost connection or error in recvjob"); 652 return(1); 653 } 654 return(0); 655 } 656 657 /* 658 * Banner printing stuff 659 */ 660 banner(name1, name2) 661 char *name1, *name2; 662 { 663 time_t tvec; 664 extern char *ctime(); 665 666 time(&tvec); 667 if (!SF && !tof) 668 (void) write(ofd, FF, strlen(FF)); 669 if (SB) { /* short banner only */ 670 if (class[0]) { 671 (void) write(ofd, class, strlen(class)); 672 (void) write(ofd, ":", 1); 673 } 674 (void) write(ofd, name1, strlen(name1)); 675 (void) write(ofd, " Job: ", 7); 676 (void) write(ofd, name2, strlen(name2)); 677 (void) write(ofd, " Date: ", 8); 678 (void) write(ofd, ctime(&tvec), 24); 679 (void) write(ofd, "\n", 1); 680 } else { /* normal banner */ 681 (void) write(ofd, "\n\n\n", 3); 682 scan_out(ofd, name1, '\0'); 683 (void) write(ofd, "\n\n", 2); 684 scan_out(ofd, name2, '\0'); 685 if (class[0]) { 686 (void) write(ofd,"\n\n\n",3); 687 scan_out(ofd, class, '\0'); 688 } 689 (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); 690 (void) write(ofd, name2, strlen(name2)); 691 (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); 692 (void) write(ofd, ctime(&tvec), 24); 693 (void) write(ofd, "\n", 1); 694 } 695 if (!SF) 696 (void) write(ofd, FF, strlen(FF)); 697 tof = 1; 698 } 699 700 char * 701 scnline(key, p, c) 702 register char key, *p; 703 char c; 704 { 705 register scnwidth; 706 707 for (scnwidth = WIDTH; --scnwidth;) { 708 key <<= 1; 709 *p++ = key & 0200 ? c : BACKGND; 710 } 711 return (p); 712 } 713 714 #define TRC(q) (((q)-' ')&0177) 715 716 scan_out(scfd, scsp, dlm) 717 int scfd; 718 char *scsp, dlm; 719 { 720 register char *strp; 721 register nchrs, j; 722 char outbuf[LINELEN+1], *sp, c, cc; 723 int d, scnhgt; 724 extern char scnkey[][HEIGHT]; /* in lpdchar.c */ 725 726 for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { 727 strp = &outbuf[0]; 728 sp = scsp; 729 for (nchrs = 0; ; ) { 730 d = dropit(c = TRC(cc = *sp++)); 731 if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) 732 for (j = WIDTH; --j;) 733 *strp++ = BACKGND; 734 else 735 strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); 736 if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) 737 break; 738 *strp++ = BACKGND; 739 *strp++ = BACKGND; 740 } 741 while (*--strp == BACKGND && strp >= outbuf) 742 ; 743 strp++; 744 *strp++ = '\n'; 745 (void) write(scfd, outbuf, strp-outbuf); 746 } 747 } 748 749 dropit(c) 750 char c; 751 { 752 switch(c) { 753 754 case TRC('_'): 755 case TRC(';'): 756 case TRC(','): 757 case TRC('g'): 758 case TRC('j'): 759 case TRC('p'): 760 case TRC('q'): 761 case TRC('y'): 762 return (DROP); 763 764 default: 765 return (0); 766 } 767 } 768 769 /* 770 * sendmail --- 771 * tell people about job completion 772 */ 773 sendmail(bombed) 774 int bombed; 775 { 776 static int p[2]; 777 register int i; 778 int stat; 779 register char *cp; 780 char buf[100]; 781 782 pipe(p); 783 if ((stat = dofork(DORETURN)) == 0) { /* child */ 784 dup2(p[0], 0); 785 for (i = 3; i < NOFILE; i++) 786 (void) close(i); 787 if ((cp = rindex(MAIL, '/')) != NULL) 788 cp++; 789 else 790 cp = MAIL; 791 sprintf(buf, "%s@%s", line+1, host); 792 execl(MAIL, cp, buf, 0); 793 exit(0); 794 } else if (stat > 0) { /* parent */ 795 dup2(p[1], 1); 796 printf("To: %s\n", line+1); 797 printf("Subject: printer job\n\n"); 798 printf("Your printer job "); 799 if (*jobname) 800 printf("(%s) ", jobname); 801 if (bombed) 802 printf("bombed\n"); 803 else 804 printf("is done\n"); 805 fflush(stdout); 806 (void) close(1); 807 } 808 (void) close(p[0]); 809 (void) close(p[1]); 810 wait(&stat); 811 } 812 813 /* 814 * dofork - fork with retries on failure 815 */ 816 dofork(action) 817 int action; 818 { 819 register int i, pid; 820 821 for (i = 0; i < 20; i++) { 822 if ((pid = fork()) < 0) 823 sleep((unsigned)(i*i)); 824 else 825 return(pid); 826 } 827 log("can't fork"); 828 829 switch (action) { 830 case DORETURN: 831 return (-1); 832 default: 833 log("bad action (%d) to dofork", action); 834 /*FALL THRU*/ 835 case DOABORT: 836 exit(1); 837 } 838 /*NOTREACHED*/ 839 } 840 841 /* 842 * Cleanup child processes when a SIGINT is caught. 843 */ 844 onintr() 845 { 846 kill(0, SIGINT); 847 if (ofilter > 0) 848 kill(ofilter, SIGCONT); 849 while (wait(0) > 0) 850 ; 851 exit(0); 852 } 853 854 init() 855 { 856 int status; 857 858 if ((status = pgetent(line, printer)) < 0) { 859 log("can't open printer description file"); 860 exit(1); 861 } else if (status == 0) { 862 log("unknown printer"); 863 exit(1); 864 } 865 if ((LP = pgetstr("lp", &bp)) == NULL) 866 LP = DEFDEVLP; 867 if ((RP = pgetstr("rp", &bp)) == NULL) 868 RP = printer; 869 if ((LO = pgetstr("lo", &bp)) == NULL) 870 LO = DEFLOCK; 871 if ((ST = pgetstr("st", &bp)) == NULL) 872 ST = DEFSTAT; 873 if ((LF = pgetstr("lf", &bp)) == NULL) 874 LF = DEFLOGF; 875 if ((SD = pgetstr("sd", &bp)) == NULL) 876 SD = DEFSPOOL; 877 if ((DU = pgetnum("du")) < 0) 878 DU = DEFUID; 879 if ((FF = pgetstr("ff", &bp)) == NULL) 880 FF = DEFFF; 881 if ((PW = pgetnum("pw")) < 0) 882 PW = DEFWIDTH; 883 sprintf(&width[2], "%d", PW); 884 if ((PL = pgetnum("pl")) < 0) 885 PL = DEFLENGTH; 886 sprintf(&length[2], "%d", PL); 887 RM = pgetstr("rm", &bp); 888 AF = pgetstr("af", &bp); 889 OF = pgetstr("of", &bp); 890 IF = pgetstr("if", &bp); 891 TF = pgetstr("tf", &bp); 892 DF = pgetstr("df", &bp); 893 GF = pgetstr("gf", &bp); 894 VF = pgetstr("vf", &bp); 895 CF = pgetstr("cf", &bp); 896 TR = pgetstr("tr", &bp); 897 SF = pgetflag("sf"); 898 SH = pgetflag("sh"); 899 SB = pgetflag("sb"); 900 RW = pgetflag("rw"); 901 BR = pgetnum("br"); 902 if ((FC = pgetnum("fc")) < 0) 903 FC = 0; 904 if ((FS = pgetnum("fs")) < 0) 905 FS = 0; 906 if ((XC = pgetnum("xc")) < 0) 907 XC = 0; 908 if ((XS = pgetnum("xs")) < 0) 909 XS = 0; 910 } 911 912 struct bauds { 913 int baud; 914 int speed; 915 } bauds[] = { 916 50, B50, 917 75, B75, 918 110, B110, 919 134, B134, 920 150, B150, 921 200, B200, 922 300, B300, 923 600, B600, 924 1200, B1200, 925 1800, B1800, 926 2400, B2400, 927 4800, B4800, 928 9600, B9600, 929 19200, EXTA, 930 38400, EXTB, 931 0, 0 932 }; 933 934 /* 935 * setup tty lines. 936 */ 937 setty() 938 { 939 struct sgttyb ttybuf; 940 register struct bauds *bp; 941 942 if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { 943 log("cannot set exclusive-use"); 944 exit(1); 945 } 946 if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { 947 log("cannot get tty parameters"); 948 exit(1); 949 } 950 if (BR > 0) { 951 for (bp = bauds; bp->baud; bp++) 952 if (BR == bp->baud) 953 break; 954 if (!bp->baud) { 955 log("illegal baud rate %d", BR); 956 exit(1); 957 } 958 ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; 959 } 960 if (FC) 961 ttybuf.sg_flags &= ~FC; 962 if (FS) 963 ttybuf.sg_flags |= FS; 964 if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { 965 log("cannot set tty parameters"); 966 exit(1); 967 } 968 if (XC) { 969 if (ioctl(pfd, TIOCLBIC, &XC) < 0) { 970 log("cannot set local tty parameters"); 971 exit(1); 972 } 973 } 974 if (XS) { 975 if (ioctl(pfd, TIOCLBIS, &XS) < 0) { 976 log("cannot set local tty parameters"); 977 exit(1); 978 } 979 } 980 } 981