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