1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1989-2002 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include "stdio.h" 34 #include "termio.h" 35 #include "sys/types.h" 36 #include "errno.h" 37 #include "signal.h" 38 #include "sys/times.h" 39 #include "string.h" 40 #include "limits.h" 41 #include <sys/prnio.h> 42 43 #include "lp.h" 44 45 #include <locale.h> 46 47 /** 48 ** Begin Sun Additions for Parallel ports 49 **/ 50 51 extern char *_sys_errlist[]; 52 #include <string.h> 53 #include <stdarg.h> 54 #include <signal.h> 55 #include <unistd.h> 56 #include <sys/types.h> 57 #include <sys/ioccom.h> 58 #include <sys/ioctl.h> 59 60 #include <sys/bpp_io.h> 61 #include <sys/ecppsys.h> 62 #include <stropts.h> 63 64 /* 65 * the parameter structure for the parallel port 66 */ 67 struct ppc_params_t { 68 int flags; /* same as above */ 69 int state; /* status of the printer interface */ 70 int strobe_w; /* strobe width, in uS */ 71 int data_setup; /* data setup time, in uS */ 72 int ack_timeout; /* ACK timeout, in secs */ 73 int error_timeout; /* PAPER OUT, etc... timeout, in secs */ 74 int busy_timeout; /* BUSY timeout, in seconds */ 75 }; 76 77 78 79 static void printer_info(char *fmt, ...); 80 81 /* These are the routines avaliable to others for use */ 82 int is_a_parallel_bpp(int); 83 int bpp_state(int); 84 int parallel_comm(int, int()); 85 int get_ecpp_status(int fd); 86 int is_a_prnio(int); 87 int prnio_state(int); 88 89 #define PRINTER_ERROR_PAPER_OUT 1 90 #define PRINTER_ERROR_OFFLINE 2 91 #define PRINTER_ERROR_BUSY 3 92 #define PRINTER_ERROR_ERROR 4 93 #define PRINTER_ERROR_CABLE_POWER 5 94 #define PRINTER_ERROR_UNKNOWN 6 95 #define PRINTER_ERROR_TIMEOUT 7 96 #define PRINTER_IO_ERROR 129 97 98 99 /****************************************************************************/ 100 101 /** 102 * for BPP PARALLEL interfaces 103 **/ 104 105 int is_a_parallel_bpp(int fd) 106 { 107 if (ioctl(fd, BPPIOC_TESTIO) == 0 || errno == EIO) 108 return(1); 109 return(0); 110 } 111 112 113 #if defined(DEBUG) && defined(NOTDEF) 114 char *BppState(int state) 115 { 116 static char buf[BUFSIZ]; 117 118 memset(buf, 0, sizeof(buf)); 119 sprintf(buf, "State (0x%.4x) - (%s%s%s%s)\n", state, 120 ((state & BPP_SLCT_ERR) ? "offline " : ""), 121 ((state & BPP_BUSY_ERR) ? "busy " : ""), 122 ((state & BPP_PE_ERR) ? "paper " : ""), 123 ((state & BPP_ERR_ERR) ? "error " : "")); 124 125 return(buf); 126 } 127 #endif 128 129 int bpp_state(int fd) 130 { 131 if (ioctl(fd, BPPIOC_TESTIO)) { 132 struct bpp_error_status bpp_stat; 133 int state; 134 135 if (ioctl(fd, BPPIOC_GETERR, &bpp_stat) < 0) 136 exit(PRINTER_IO_ERROR); 137 state = bpp_stat.pin_status; 138 139 #if defined(DEBUG) && defined(NOTDEF) 140 logit("%s", BppState(state)); 141 #endif 142 143 if (state == (BPP_PE_ERR | BPP_ERR_ERR | BPP_SLCT_ERR)) { 144 /* paper is out */ 145 return(PRINTER_ERROR_PAPER_OUT); 146 } else if (state & BPP_BUSY_ERR) { 147 /* printer is busy */ 148 return(PRINTER_ERROR_BUSY); 149 } else if (state & BPP_SLCT_ERR) { 150 /* printer is offline */ 151 return(PRINTER_ERROR_OFFLINE); 152 } else if (state & BPP_ERR_ERR) { 153 /* printer is errored */ 154 return(PRINTER_ERROR_ERROR); 155 } else if (state == BPP_PE_ERR) { 156 /* printer is off/unplugged */ 157 return(PRINTER_ERROR_CABLE_POWER); 158 } else if (state) { 159 return(PRINTER_ERROR_UNKNOWN); 160 } else 161 return(0); 162 } 163 return(0); 164 } 165 166 /* 167 * For ecpp parallel port 168 */ 169 170 int 171 get_ecpp_status(int fd) 172 { 173 int state; 174 struct ecpp_transfer_parms transfer_parms; 175 176 177 if (ioctl(fd, ECPPIOC_GETPARMS, &transfer_parms) == -1) { 178 return(-1); 179 } 180 181 state = transfer_parms.mode; 182 /* 183 * We don't know what all printers will return in 184 * nibble mode, therefore if we support nibble mode we will 185 * force the printer to be in CENTRONICS mode. 186 */ 187 if (state != ECPP_CENTRONICS) { 188 transfer_parms.mode = ECPP_CENTRONICS; 189 if (ioctl(fd, ECPPIOC_SETPARMS, &transfer_parms) == -1) { 190 return(-1); 191 } else { 192 state = ECPP_CENTRONICS; 193 } 194 } 195 196 197 return(state); 198 } 199 200 /** 201 * For prnio(7I) - generic printer interface 202 **/ 203 int is_a_prnio(int fd) 204 { 205 uint_t cap; 206 207 /* check if device supports prnio */ 208 if (ioctl(fd, PRNIOC_GET_IFCAP, &cap) == -1) { 209 return (0); 210 } 211 /* we will use 1284 status if available */ 212 if ((cap & PRN_1284_STATUS) == 0) { 213 /* some devices may only support 1284 status in unidir. mode */ 214 if (cap & PRN_BIDI) { 215 cap &= ~PRN_BIDI; 216 (void) ioctl(fd, PRNIOC_SET_IFCAP, &cap); 217 } 218 } 219 return (1); 220 } 221 222 int prnio_state(int fd) 223 { 224 uint_t status; 225 uchar_t pins; 226 227 if ((ioctl(fd, PRNIOC_GET_STATUS, &status) == 0) && 228 (status & PRN_READY)) { 229 return(0); 230 } 231 232 if (ioctl(fd, PRNIOC_GET_1284_STATUS, &pins) != 0) { 233 return(PRINTER_ERROR_UNKNOWN); 234 } 235 236 if ((pins & ~PRN_1284_BUSY) == PRN_1284_PE) { 237 /* paper is out */ 238 return(PRINTER_ERROR_PAPER_OUT); 239 } else if (pins == (PRN_1284_PE | PRN_1284_SELECT | 240 PRN_1284_NOFAULT | PRN_1284_BUSY)) { 241 /* printer is off/unplugged */ 242 return(PRINTER_ERROR_CABLE_POWER); 243 } else if ((pins & PRN_1284_SELECT) == 0) { 244 /* printer is offline */ 245 return(PRINTER_ERROR_OFFLINE); 246 } else if ((pins & PRN_1284_NOFAULT) == 0) { 247 /* printer is errored */ 248 return(PRINTER_ERROR_ERROR); 249 } else if (pins & PRN_1284_PE) { 250 /* paper is out */ 251 return(PRINTER_ERROR_PAPER_OUT); 252 } else if (pins ^ (PRN_1284_SELECT | PRN_1284_NOFAULT)) { 253 return(PRINTER_ERROR_UNKNOWN); 254 } 255 256 return(0); 257 } 258 259 /** 260 * Common routines 261 **/ 262 263 /*ARGSUSED0*/ 264 static void 265 ByeByeParallel(int sig) 266 { 267 /* try to shove out the EOT */ 268 (void) write(1, "\004", 1); 269 exit(0); 270 } 271 272 273 /*ARGSUSED0*/ 274 static void 275 printer_info(char *fmt, ...) 276 { 277 char mesg[BUFSIZ]; 278 va_list ap; 279 280 va_start(ap, fmt); 281 vsprintf(mesg, fmt, ap); 282 va_end(ap); 283 /* 284 fprintf(stderr, 285 "%%%%[ PrinterError: %s; source: parallel ]%%%%\n", 286 mesg); 287 */ 288 fprintf(stderr, "%s\n", mesg); 289 fflush(stderr); 290 fsync(2); 291 292 } 293 294 static void 295 printer_error(int error) 296 { 297 switch (error) { 298 case -1: 299 printer_info("ioctl(): %s", _sys_errlist[errno]); 300 break; 301 case PRINTER_ERROR_PAPER_OUT: 302 printer_info("out of paper"); 303 break; 304 case PRINTER_ERROR_OFFLINE: 305 printer_info("offline"); 306 break; 307 case PRINTER_ERROR_BUSY: 308 printer_info("busy"); 309 break; 310 case PRINTER_ERROR_ERROR: 311 printer_info("printer error"); 312 break; 313 case PRINTER_ERROR_CABLE_POWER: 314 printer_info("printer powered off or disconnected"); 315 break; 316 case PRINTER_ERROR_UNKNOWN: 317 printer_info("unknown error"); 318 break; 319 case PRINTER_ERROR_TIMEOUT: 320 printer_info("communications timeout"); 321 break; 322 default: 323 printer_info("get_status() failed"); 324 } 325 } 326 327 328 static void 329 wait_state(int fd, int get_state()) 330 { 331 int state; 332 int was_faulted = 0; 333 334 while (state = get_state(fd)) { 335 was_faulted=1; 336 printer_error(state); 337 sleep(15); 338 } 339 340 if (was_faulted) { 341 fprintf(stderr, "printer ok\n"); 342 fflush(stderr); 343 fsync(2); 344 } 345 } 346 347 /** 348 ** end of Sun Additions for parallel port 349 **/ 350 #define IDENTICAL(A,B) (A.st_dev==B.st_dev && A.st_ino==B.st_ino) 351 #define ISBLK(A) ((A.st_mode & S_IFMT) == S_IFBLK) 352 #define ISCHR(A) ((A.st_mode & S_IFMT) == S_IFCHR) 353 354 #define E_SUCCESS 0 355 #define E_BAD_INPUT 1 356 #define E_BAD_OUTPUT 2 357 #define E_BAD_TERM 3 358 #define E_IDENTICAL 4 359 #define E_WRITE_FAILED 5 360 #define E_TIMEOUT 6 361 #define E_HANGUP 7 362 #define E_INTERRUPT 8 363 364 #define SAFETY_FACTOR 2.0 365 #define R(F) (int)((F) + .5) 366 #define DELAY(N,D) R(SAFETY_FACTOR * ((N) / (double)(D))) 367 368 extern int sys_nerr; 369 370 extern char *sys_errlist[], 371 *getenv(); 372 373 extern int atoi(); 374 375 char buffer[BUFSIZ]; 376 377 void sighup(), 378 sigint(), 379 sigquit(), 380 sigpipe(), 381 sigalrm(), 382 sigterm(); 383 384 #if defined(baudrate) 385 # undef baudrate 386 #endif 387 388 int baudrate(); 389 390 391 int nop(int fd) { return (0); } 392 int bpp_state(int); 393 394 395 /** 396 ** main() 397 **/ 398 399 int main (argc, argv) 400 int argc; 401 char *argv[]; 402 { 403 register int nin, 404 nout, 405 effective_rate, 406 max_delay = 0, 407 n; 408 409 int report_rate; 410 411 short print_rate; 412 413 struct stat in, 414 out; 415 416 struct tms tms; 417 418 long epoch_start, 419 epoch_end; 420 421 char *TERM; 422 423 int (*func)(int fd); 424 425 /* 426 * The Spooler can hit us with SIGTERM for three reasons: 427 * 428 * - the user's job has been canceled 429 * - the printer has been disabled while we were printing 430 * - the Spooler heard that the printer has a fault, 431 * and the fault recovery is wait or beginning 432 * 433 * We should exit cleanly for the first two cases, 434 * but we have to be careful with the last. If it was THIS 435 * PROGRAM that told the Spooler about the fault, we must 436 * exit consistently. 437 * 438 * The method of avoiding any problem is to turn off the 439 * trapping of SIGTERM before telling the Spooler about 440 * the fault. 441 * 442 * Faults that we can detect: 443 * - hangup (drop of carrier) 444 * - interrupt (printer sent a break or quit character) 445 * - SIGPIPE (output port is a FIFO, and was closed early) 446 * - failed or incomplete write() 447 * - excess delay in write() (handled with SIGALRM later) 448 * 449 * Pseudo-faults (errors in use): 450 * - No input/output, or strange input/output 451 * - Input/output identical 452 * - No TERM defined or trouble reading Terminfo database 453 */ 454 signal (SIGTERM, sigterm); 455 signal (SIGHUP, sighup); 456 signal (SIGINT, sigint); 457 signal (SIGQUIT, sigint); 458 signal (SIGPIPE, sigpipe); 459 460 461 if (argc > 1 && STREQU(argv[1], "-r")) { 462 report_rate = 1; 463 argc--; 464 argv++; 465 } else 466 report_rate = 0; 467 468 (void) setlocale(LC_ALL, ""); 469 #if !defined(TEXT_DOMAIN) 470 #define TEXT_DOMAIN "SYS_TEST" 471 #endif 472 (void) textdomain(TEXT_DOMAIN); 473 474 /* 475 * Stat the standard output to be sure it is defined. 476 */ 477 if (fstat(1, &out) < 0) { 478 signal (SIGTERM, SIG_IGN); 479 fprintf ( 480 stderr, 481 gettext("Can't stat output (%s);\nincorrect use of lp.cat!\n"), 482 PERROR 483 ); 484 exit (E_BAD_OUTPUT); 485 } 486 487 /* 488 * Stat the standard input to be sure it is defined. 489 */ 490 if (fstat(0, &in) < 0) { 491 signal (SIGTERM, SIG_IGN); 492 fprintf ( 493 stderr, 494 gettext("Can't stat input (%s);\nincorrect use of lp.cat!\n"), 495 PERROR 496 ); 497 exit (E_BAD_INPUT); 498 } 499 500 /* 501 * If the standard output is not a character special file or a 502 * block special file, make sure it is not identical to the 503 * standard input. 504 * 505 * If we are an ecpp parallel port in centronics mode treat 506 * ourselves as a bpp compatible device. 507 */ 508 509 if (is_a_prnio(1)) { 510 func = prnio_state; 511 } else if (is_a_parallel_bpp(1) || 512 (get_ecpp_status(1) == ECPP_CENTRONICS)) { 513 func = bpp_state; 514 } else if (isatty(1)) { 515 /* serial connection (probably) - continue as usual */ 516 func = nop; 517 } else { 518 func = nop; 519 } 520 521 if (!ISCHR(out) && !ISBLK(out) && IDENTICAL(out, in)) { 522 signal (SIGTERM, SIG_IGN); 523 fprintf ( 524 stderr, 525 gettext("Input and output are identical; incorrect use of lp.cat!\n") 526 ); 527 exit (E_IDENTICAL); 528 } 529 530 /* 531 * The effective data transfer rate is the lesser 532 * of the transmission rate and print rate. If an 533 * argument was passed to us, it should be a data 534 * rate and it may be lower still. 535 * Based on the effective data transfer rate, 536 * we can predict the maximum delay we should experience. 537 * But there are other factors that could introduce 538 * delay, so let's be generous; after all, we'd rather 539 * err in favor of waiting too long to detect a fault 540 * than err too often on false alarms. 541 */ 542 543 if ( 544 !(TERM = getenv("TERM")) 545 || !*TERM 546 ) { 547 signal (SIGTERM, SIG_IGN); 548 fprintf ( 549 stderr, 550 gettext("No TERM variable defined! Trouble with the Spooler!\n") 551 ); 552 exit (E_BAD_TERM); 553 } 554 if ( 555 !STREQU(TERM, NAME_UNKNOWN) 556 && tidbit(TERM, "cps", &print_rate) == -1 557 ) { 558 signal (SIGTERM, SIG_IGN); 559 fprintf ( 560 stderr, 561 gettext("Trouble identifying printer type \"%s\"; check the Terminfo database.\n"), 562 TERM 563 ); 564 exit (E_BAD_TERM); 565 } 566 if (STREQU(TERM, NAME_UNKNOWN)) 567 print_rate = -1; 568 569 effective_rate = baudrate() / 10; /* okay for most bauds */ 570 if (print_rate != -1 && print_rate < effective_rate) 571 effective_rate = print_rate; 572 if (argc > 1 && (n = atoi(argv[1])) >= 0 && n < effective_rate) 573 effective_rate = n; /* 0 means infinite delay */ 574 if (effective_rate) 575 max_delay = DELAY(BUFSIZ, effective_rate); 576 577 /* 578 * We'll use the "alarm()" system call to keep us from 579 * waiting too long to write to a printer in trouble. 580 */ 581 if (max_delay) 582 signal (SIGALRM, sigalrm); 583 584 /* 585 * While not end of standard input, copy blocks to 586 * standard output. 587 */ 588 while ((nin = read(0, buffer, BUFSIZ)) > 0) { 589 char *ptr = buffer; 590 591 /* 592 * We should be safe from incomplete writes to a full 593 * pipe, as long as the size of the buffer we write is 594 * a even divisor of the pipe buffer limit. As long as 595 * we read from files or pipes (not communication devices) 596 * this should be true for all but the last buffer. The 597 * last will be smaller, and won't straddle the pipe max 598 * limit (think about it). 599 */ 600 #if PIPE_BUF < BUFSIZ || (PIPE_MAX % BUFSIZ) 601 this_wont_compile; 602 #endif 603 if (report_rate) 604 epoch_start = times(&tms); 605 do { 606 wait_state(1, func); 607 608 if (max_delay) 609 alarm (max_delay); 610 nout = write(1, ptr, nin); 611 alarm(0); 612 if (nout < 0) { 613 fprintf ( 614 stderr, 615 gettext("Write failed (%s);\nperhaps the printer has gone off-line.\n"), 616 PERROR 617 ); 618 fflush(stderr); 619 if (errno != EINTR) 620 /* I/O error on device, get lpcshed to retry */ 621 exit(PRINTER_IO_ERROR); 622 else /* wait for printer to come back online */ 623 sleep(15); 624 } else { 625 nin -= nout; 626 ptr += nout; 627 } 628 } while (nin > 0); 629 630 if (max_delay) 631 alarm (0); 632 else if (report_rate) { 633 epoch_end = times(&tms); 634 if (epoch_end - epoch_start > 0) 635 fprintf ( 636 stderr, 637 "%d CPS\n", 638 R((100 * BUFSIZ) / (double)(epoch_end - epoch_start)) 639 ); 640 } 641 642 } 643 644 exit (E_SUCCESS); 645 /*NOTREACHED*/ 646 } 647 648 /** 649 ** sighup() - CATCH A HANGUP (LOSS OF CARRIER) 650 **/ 651 652 void sighup () 653 { 654 signal (SIGTERM, SIG_IGN); 655 signal (SIGHUP, SIG_IGN); 656 fprintf (stderr, gettext(HANGUP_FAULT_LPCAT)); 657 exit (E_HANGUP); 658 } 659 660 /** 661 ** sigint() - CATCH AN INTERRUPT 662 **/ 663 664 void sigint () 665 { 666 signal (SIGTERM, SIG_IGN); 667 signal (SIGINT, SIG_IGN); 668 fprintf (stderr, gettext(INTERRUPT_FAULT)); 669 exit (E_INTERRUPT); 670 } 671 672 /** 673 ** sigpipe() - CATCH EARLY CLOSE OF PIPE 674 **/ 675 676 void sigpipe () 677 { 678 signal (SIGTERM, SIG_IGN); 679 signal (SIGPIPE, SIG_IGN); 680 fprintf (stderr, gettext(PIPE_FAULT)); 681 exit (E_INTERRUPT); 682 } 683 684 /** 685 ** sigalrm() - CATCH AN ALARM 686 **/ 687 688 void sigalrm () 689 { 690 signal (SIGTERM, SIG_IGN); 691 fprintf ( 692 stderr, 693 gettext("Excessive write delay; perhaps the printer has gone off-line.\n") 694 ); 695 exit (E_TIMEOUT); 696 } 697 698 /** 699 ** sigterm() - CATCH A TERMINATION SIGNAL 700 **/ 701 702 void sigterm () 703 { 704 signal (SIGTERM, SIG_IGN); 705 /* 706 * try to flush the output queue in the case of ecpp port. 707 * ignore the return code as this may not be the ecpp. 708 */ 709 ioctl(1, I_FLUSH, FLUSHW); 710 exit (E_SUCCESS); 711 } 712 713 /** 714 ** baudrate() - RETURN BAUD RATE OF OUTPUT LINE 715 **/ 716 717 static int baud_convert[] = 718 { 719 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200, 720 1800, 2400, 4800, 9600, 19200, 38400, 57600, 721 76800, 115200, 153600, 230400, 307200, 460800 722 }; 723 724 int baudrate () 725 { 726 struct termio tm; 727 struct termios tms; 728 int speed; 729 730 if (ioctl(1, TCGETS, &tms) < 0) { 731 if (ioctl(1, TCGETA, &tm) < 0) 732 return (1200); 733 else 734 speed = tm.c_cflag&CBAUD; 735 } else 736 speed = cfgetospeed(&tms); 737 738 return (speed ? baud_convert[speed] : 1200); 739 } 740