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 <stdlib.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 #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", strerror(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 char buffer[BUFSIZ]; 368 369 void sighup(), 370 sigint(), 371 sigquit(), 372 sigpipe(), 373 sigalrm(), 374 sigterm(); 375 376 #if defined(baudrate) 377 # undef baudrate 378 #endif 379 380 int baudrate(); 381 382 383 int nop(int fd) { return (0); } 384 int bpp_state(int); 385 386 387 /** 388 ** main() 389 **/ 390 391 int 392 main(int argc, char *argv[]) 393 { 394 int nin, 395 nout, 396 effective_rate, 397 max_delay = 0, 398 n; 399 400 int report_rate; 401 402 short print_rate; 403 404 struct stat in, 405 out; 406 407 struct tms tms; 408 409 long epoch_start, 410 epoch_end; 411 412 char *TERM; 413 414 int (*func)(int fd); 415 416 /* 417 * The Spooler can hit us with SIGTERM for three reasons: 418 * 419 * - the user's job has been canceled 420 * - the printer has been disabled while we were printing 421 * - the Spooler heard that the printer has a fault, 422 * and the fault recovery is wait or beginning 423 * 424 * We should exit cleanly for the first two cases, 425 * but we have to be careful with the last. If it was THIS 426 * PROGRAM that told the Spooler about the fault, we must 427 * exit consistently. 428 * 429 * The method of avoiding any problem is to turn off the 430 * trapping of SIGTERM before telling the Spooler about 431 * the fault. 432 * 433 * Faults that we can detect: 434 * - hangup (drop of carrier) 435 * - interrupt (printer sent a break or quit character) 436 * - SIGPIPE (output port is a FIFO, and was closed early) 437 * - failed or incomplete write() 438 * - excess delay in write() (handled with SIGALRM later) 439 * 440 * Pseudo-faults (errors in use): 441 * - No input/output, or strange input/output 442 * - Input/output identical 443 * - No TERM defined or trouble reading Terminfo database 444 */ 445 signal (SIGTERM, sigterm); 446 signal (SIGHUP, sighup); 447 signal (SIGINT, sigint); 448 signal (SIGQUIT, sigint); 449 signal (SIGPIPE, sigpipe); 450 451 452 if (argc > 1 && STREQU(argv[1], "-r")) { 453 report_rate = 1; 454 argc--; 455 argv++; 456 } else 457 report_rate = 0; 458 459 (void) setlocale(LC_ALL, ""); 460 #if !defined(TEXT_DOMAIN) 461 #define TEXT_DOMAIN "SYS_TEST" 462 #endif 463 (void) textdomain(TEXT_DOMAIN); 464 465 /* 466 * Stat the standard output to be sure it is defined. 467 */ 468 if (fstat(1, &out) < 0) { 469 signal (SIGTERM, SIG_IGN); 470 fprintf ( 471 stderr, 472 gettext("Can't stat output (%s);\nincorrect use of lp.cat!\n"), 473 PERROR 474 ); 475 exit (E_BAD_OUTPUT); 476 } 477 478 /* 479 * Stat the standard input to be sure it is defined. 480 */ 481 if (fstat(0, &in) < 0) { 482 signal (SIGTERM, SIG_IGN); 483 fprintf ( 484 stderr, 485 gettext("Can't stat input (%s);\nincorrect use of lp.cat!\n"), 486 PERROR 487 ); 488 exit (E_BAD_INPUT); 489 } 490 491 /* 492 * If the standard output is not a character special file or a 493 * block special file, make sure it is not identical to the 494 * standard input. 495 * 496 * If we are an ecpp parallel port in centronics mode treat 497 * ourselves as a bpp compatible device. 498 */ 499 500 if (is_a_prnio(1)) { 501 func = prnio_state; 502 } else if (is_a_parallel_bpp(1) || 503 (get_ecpp_status(1) == ECPP_CENTRONICS)) { 504 func = bpp_state; 505 } else if (isatty(1)) { 506 /* serial connection (probably) - continue as usual */ 507 func = nop; 508 } else { 509 func = nop; 510 } 511 512 if (!ISCHR(out) && !ISBLK(out) && IDENTICAL(out, in)) { 513 signal (SIGTERM, SIG_IGN); 514 fprintf ( 515 stderr, 516 gettext("Input and output are identical; incorrect use of lp.cat!\n") 517 ); 518 exit (E_IDENTICAL); 519 } 520 521 /* 522 * The effective data transfer rate is the lesser 523 * of the transmission rate and print rate. If an 524 * argument was passed to us, it should be a data 525 * rate and it may be lower still. 526 * Based on the effective data transfer rate, 527 * we can predict the maximum delay we should experience. 528 * But there are other factors that could introduce 529 * delay, so let's be generous; after all, we'd rather 530 * err in favor of waiting too long to detect a fault 531 * than err too often on false alarms. 532 */ 533 534 if ( 535 !(TERM = getenv("TERM")) 536 || !*TERM 537 ) { 538 signal (SIGTERM, SIG_IGN); 539 fprintf ( 540 stderr, 541 gettext("No TERM variable defined! Trouble with the Spooler!\n") 542 ); 543 exit (E_BAD_TERM); 544 } 545 if ( 546 !STREQU(TERM, NAME_UNKNOWN) 547 && tidbit(TERM, "cps", &print_rate) == -1 548 ) { 549 signal (SIGTERM, SIG_IGN); 550 fprintf ( 551 stderr, 552 gettext("Trouble identifying printer type \"%s\"; check the Terminfo database.\n"), 553 TERM 554 ); 555 exit (E_BAD_TERM); 556 } 557 if (STREQU(TERM, NAME_UNKNOWN)) 558 print_rate = -1; 559 560 effective_rate = baudrate() / 10; /* okay for most bauds */ 561 if (print_rate != -1 && print_rate < effective_rate) 562 effective_rate = print_rate; 563 if (argc > 1 && (n = atoi(argv[1])) >= 0 && n < effective_rate) 564 effective_rate = n; /* 0 means infinite delay */ 565 if (effective_rate) 566 max_delay = DELAY(BUFSIZ, effective_rate); 567 568 /* 569 * We'll use the "alarm()" system call to keep us from 570 * waiting too long to write to a printer in trouble. 571 */ 572 if (max_delay) 573 signal (SIGALRM, sigalrm); 574 575 /* 576 * While not end of standard input, copy blocks to 577 * standard output. 578 */ 579 while ((nin = read(0, buffer, BUFSIZ)) > 0) { 580 char *ptr = buffer; 581 582 /* 583 * We should be safe from incomplete writes to a full 584 * pipe, as long as the size of the buffer we write is 585 * a even divisor of the pipe buffer limit. As long as 586 * we read from files or pipes (not communication devices) 587 * this should be true for all but the last buffer. The 588 * last will be smaller, and won't straddle the pipe max 589 * limit (think about it). 590 */ 591 #if PIPE_BUF < BUFSIZ || (PIPE_MAX % BUFSIZ) 592 this_wont_compile; 593 #endif 594 if (report_rate) 595 epoch_start = times(&tms); 596 do { 597 wait_state(1, func); 598 599 if (max_delay) 600 alarm (max_delay); 601 nout = write(1, ptr, nin); 602 alarm(0); 603 if (nout < 0) { 604 fprintf ( 605 stderr, 606 gettext("Write failed (%s);\nperhaps the printer has gone off-line.\n"), 607 PERROR 608 ); 609 fflush(stderr); 610 if (errno != EINTR) 611 /* I/O error on device, get lpcshed to retry */ 612 exit(PRINTER_IO_ERROR); 613 else /* wait for printer to come back online */ 614 sleep(15); 615 } else { 616 nin -= nout; 617 ptr += nout; 618 } 619 } while (nin > 0); 620 621 if (max_delay) 622 alarm (0); 623 else if (report_rate) { 624 epoch_end = times(&tms); 625 if (epoch_end - epoch_start > 0) 626 fprintf ( 627 stderr, 628 "%d CPS\n", 629 R((100 * BUFSIZ) / (double)(epoch_end - epoch_start)) 630 ); 631 } 632 633 } 634 635 return (E_SUCCESS); 636 } 637 638 /** 639 ** sighup() - CATCH A HANGUP (LOSS OF CARRIER) 640 **/ 641 642 void sighup () 643 { 644 signal (SIGTERM, SIG_IGN); 645 signal (SIGHUP, SIG_IGN); 646 fprintf (stderr, gettext(HANGUP_FAULT_LPCAT)); 647 exit (E_HANGUP); 648 } 649 650 /** 651 ** sigint() - CATCH AN INTERRUPT 652 **/ 653 654 void sigint () 655 { 656 signal (SIGTERM, SIG_IGN); 657 signal (SIGINT, SIG_IGN); 658 fprintf (stderr, gettext(INTERRUPT_FAULT)); 659 exit (E_INTERRUPT); 660 } 661 662 /** 663 ** sigpipe() - CATCH EARLY CLOSE OF PIPE 664 **/ 665 666 void sigpipe () 667 { 668 signal (SIGTERM, SIG_IGN); 669 signal (SIGPIPE, SIG_IGN); 670 fprintf (stderr, gettext(PIPE_FAULT)); 671 exit (E_INTERRUPT); 672 } 673 674 /** 675 ** sigalrm() - CATCH AN ALARM 676 **/ 677 678 void sigalrm () 679 { 680 signal (SIGTERM, SIG_IGN); 681 fprintf ( 682 stderr, 683 gettext("Excessive write delay; perhaps the printer has gone off-line.\n") 684 ); 685 exit (E_TIMEOUT); 686 } 687 688 /** 689 ** sigterm() - CATCH A TERMINATION SIGNAL 690 **/ 691 692 void sigterm () 693 { 694 signal (SIGTERM, SIG_IGN); 695 /* 696 * try to flush the output queue in the case of ecpp port. 697 * ignore the return code as this may not be the ecpp. 698 */ 699 ioctl(1, I_FLUSH, FLUSHW); 700 exit (E_SUCCESS); 701 } 702 703 /** 704 ** baudrate() - RETURN BAUD RATE OF OUTPUT LINE 705 **/ 706 707 static int baud_convert[] = 708 { 709 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200, 710 1800, 2400, 4800, 9600, 19200, 38400, 57600, 711 76800, 115200, 153600, 230400, 307200, 460800 712 }; 713 714 int baudrate () 715 { 716 struct termio tm; 717 struct termios tms; 718 int speed; 719 720 if (ioctl(1, TCGETS, &tms) < 0) { 721 if (ioctl(1, TCGETA, &tm) < 0) 722 return (1200); 723 else 724 speed = tm.c_cflag&CBAUD; 725 } else 726 speed = cfgetospeed(&tms); 727 728 return (speed ? baud_convert[speed] : 1200); 729 } 730