4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
33 #include <sys/types.h>
36 #include <sys/times.h>
39 #include <sys/prnio.h>
46 * Begin Sun Additions for Parallel ports
53 #include <sys/types.h>
54 #include <sys/ioccom.h>
55 #include <sys/ioctl.h>
57 #include <sys/bpp_io.h>
58 #include <sys/ecppsys.h>
62 * the parameter structure for the parallel port
65 int flags
; /* same as above */
66 int state
; /* status of the printer interface */
67 int strobe_w
; /* strobe width, in uS */
68 int data_setup
; /* data setup time, in uS */
69 int ack_timeout
; /* ACK timeout, in secs */
70 int error_timeout
; /* PAPER OUT, etc... timeout, in secs */
71 int busy_timeout
; /* BUSY timeout, in seconds */
76 static void printer_info(char *fmt
, ...);
78 /* These are the routines avaliable to others for use */
79 int is_a_parallel_bpp(int);
81 int parallel_comm(int, int());
82 int get_ecpp_status(int fd
);
86 #define PRINTER_ERROR_PAPER_OUT 1
87 #define PRINTER_ERROR_OFFLINE 2
88 #define PRINTER_ERROR_BUSY 3
89 #define PRINTER_ERROR_ERROR 4
90 #define PRINTER_ERROR_CABLE_POWER 5
91 #define PRINTER_ERROR_UNKNOWN 6
92 #define PRINTER_ERROR_TIMEOUT 7
93 #define PRINTER_IO_ERROR 129
97 * for BPP PARALLEL interfaces
101 is_a_parallel_bpp(int fd
)
103 if (ioctl(fd
, BPPIOC_TESTIO
) == 0 || errno
== EIO
)
109 #if defined(DEBUG) && defined(NOTDEF)
113 static char buf
[BUFSIZ
];
115 memset(buf
, 0, sizeof (buf
));
116 sprintf(buf
, "State (0x%.4x) - (%s%s%s%s)\n", state
,
117 ((state
& BPP_SLCT_ERR
) ? "offline " : ""),
118 ((state
& BPP_BUSY_ERR
) ? "busy " : ""),
119 ((state
& BPP_PE_ERR
) ? "paper " : ""),
120 ((state
& BPP_ERR_ERR
) ? "error " : ""));
129 if (ioctl(fd
, BPPIOC_TESTIO
)) {
130 struct bpp_error_status bpp_stat
;
133 if (ioctl(fd
, BPPIOC_GETERR
, &bpp_stat
) < 0)
134 exit(PRINTER_IO_ERROR
);
135 state
= bpp_stat
.pin_status
;
137 #if defined(DEBUG) && defined(NOTDEF)
138 logit("%s", BppState(state
));
141 if (state
== (BPP_PE_ERR
| BPP_ERR_ERR
| BPP_SLCT_ERR
)) {
143 return (PRINTER_ERROR_PAPER_OUT
);
144 } else if (state
& BPP_BUSY_ERR
) {
145 /* printer is busy */
146 return (PRINTER_ERROR_BUSY
);
147 } else if (state
& BPP_SLCT_ERR
) {
148 /* printer is offline */
149 return (PRINTER_ERROR_OFFLINE
);
150 } else if (state
& BPP_ERR_ERR
) {
151 /* printer is errored */
152 return (PRINTER_ERROR_ERROR
);
153 } else if (state
== BPP_PE_ERR
) {
154 /* printer is off/unplugged */
155 return (PRINTER_ERROR_CABLE_POWER
);
157 return (PRINTER_ERROR_UNKNOWN
);
165 * For ecpp parallel port
169 get_ecpp_status(int fd
)
172 struct ecpp_transfer_parms transfer_parms
;
175 if (ioctl(fd
, ECPPIOC_GETPARMS
, &transfer_parms
) == -1) {
179 state
= transfer_parms
.mode
;
181 * We don't know what all printers will return in
182 * nibble mode, therefore if we support nibble mode we will
183 * force the printer to be in CENTRONICS mode.
185 if (state
!= ECPP_CENTRONICS
) {
186 transfer_parms
.mode
= ECPP_CENTRONICS
;
187 if (ioctl(fd
, ECPPIOC_SETPARMS
, &transfer_parms
) == -1) {
190 state
= ECPP_CENTRONICS
;
199 * For prnio(7I) - generic printer interface
206 /* check if device supports prnio */
207 if (ioctl(fd
, PRNIOC_GET_IFCAP
, &cap
) == -1) {
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
) {
215 (void) ioctl(fd
, PRNIOC_SET_IFCAP
, &cap
);
227 if ((ioctl(fd
, PRNIOC_GET_STATUS
, &status
) == 0) &&
228 (status
& PRN_READY
)) {
232 if (ioctl(fd
, PRNIOC_GET_1284_STATUS
, &pins
) != 0) {
233 return (PRINTER_ERROR_UNKNOWN
);
236 if ((pins
& ~PRN_1284_BUSY
) == PRN_1284_PE
) {
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
) {
251 return (PRINTER_ERROR_PAPER_OUT
);
252 } else if (pins
^ (PRN_1284_SELECT
| PRN_1284_NOFAULT
)) {
253 return (PRINTER_ERROR_UNKNOWN
);
265 ByeByeParallel(int sig
)
267 /* try to shove out the EOT */
268 (void) write(1, "\004", 1);
275 printer_info(char *fmt
, ...)
281 vsprintf(mesg
, fmt
, ap
);
285 * "%%%%[ PrinterError: %s; source: parallel ]%%%%\n",
288 fprintf(stderr
, "%s\n", mesg
);
295 printer_error(int error
)
299 printer_info("ioctl(): %s", strerror(errno
));
301 case PRINTER_ERROR_PAPER_OUT
:
302 printer_info("out of paper");
304 case PRINTER_ERROR_OFFLINE
:
305 printer_info("offline");
307 case PRINTER_ERROR_BUSY
:
308 printer_info("busy");
310 case PRINTER_ERROR_ERROR
:
311 printer_info("printer error");
313 case PRINTER_ERROR_CABLE_POWER
:
314 printer_info("printer powered off or disconnected");
316 case PRINTER_ERROR_UNKNOWN
:
317 printer_info("unknown error");
319 case PRINTER_ERROR_TIMEOUT
:
320 printer_info("communications timeout");
323 printer_info("get_status() failed");
329 wait_state(int fd
, int get_state())
334 while (state
= get_state(fd
)) {
336 printer_error(state
);
341 fprintf(stderr
, "printer ok\n");
348 * end of Sun Additions for parallel port
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)
355 #define E_BAD_INPUT 1
356 #define E_BAD_OUTPUT 2
358 #define E_IDENTICAL 4
359 #define E_WRITE_FAILED 5
362 #define E_INTERRUPT 8
364 #define SAFETY_FACTOR 2.0
365 #define R(F) (int)((F) + .5)
366 #define DELAY(N, D) R(SAFETY_FACTOR * ((N) / (double)(D)))
377 #if defined(baudrate)
398 main(int argc
, char *argv
[])
400 int nin
, nout
, effective_rate
, max_delay
= 0, n
;
405 long epoch_start
, epoch_end
;
410 * The Spooler can hit us with SIGTERM for three reasons:
412 * - the user's job has been canceled
413 * - the printer has been disabled while we were printing
414 * - the Spooler heard that the printer has a fault,
415 * and the fault recovery is wait or beginning
417 * We should exit cleanly for the first two cases,
418 * but we have to be careful with the last. If it was THIS
419 * PROGRAM that told the Spooler about the fault, we must
422 * The method of avoiding any problem is to turn off the
423 * trapping of SIGTERM before telling the Spooler about
426 * Faults that we can detect:
427 * - hangup (drop of carrier)
428 * - interrupt (printer sent a break or quit character)
429 * - SIGPIPE (output port is a FIFO, and was closed early)
430 * - failed or incomplete write()
431 * - excess delay in write() (handled with SIGALRM later)
433 * Pseudo-faults (errors in use):
434 * - No input/output, or strange input/output
435 * - Input/output identical
436 * - No TERM defined or trouble reading Terminfo database
438 signal(SIGTERM
, sigterm
);
439 signal(SIGHUP
, sighup
);
440 signal(SIGINT
, sigint
);
441 signal(SIGQUIT
, sigint
);
442 signal(SIGPIPE
, sigpipe
);
445 if (argc
> 1 && STREQU(argv
[1], "-r")) {
452 (void) setlocale(LC_ALL
, "");
453 #if !defined(TEXT_DOMAIN)
454 #define TEXT_DOMAIN "SYS_TEST"
456 (void) textdomain(TEXT_DOMAIN
);
459 * Stat the standard output to be sure it is defined.
461 if (fstat(1, &out
) < 0) {
462 signal(SIGTERM
, SIG_IGN
);
463 fprintf(stderr
, gettext("Can't stat output "
464 "(%s);\nincorrect use of lp.cat!\n"), PERROR
);
469 * Stat the standard input to be sure it is defined.
471 if (fstat(0, &in
) < 0) {
472 signal(SIGTERM
, SIG_IGN
);
473 fprintf(stderr
, gettext("Can't stat input "
474 "(%s);\nincorrect use of lp.cat!\n"), PERROR
);
479 * If the standard output is not a character special file or a
480 * block special file, make sure it is not identical to the
483 * If we are an ecpp parallel port in centronics mode treat
484 * ourselves as a bpp compatible device.
489 } else if (is_a_parallel_bpp(1) ||
490 (get_ecpp_status(1) == ECPP_CENTRONICS
)) {
492 } else if (isatty(1)) {
493 /* serial connection (probably) - continue as usual */
499 if (!ISCHR(out
) && !ISBLK(out
) && IDENTICAL(out
, in
)) {
500 signal(SIGTERM
, SIG_IGN
);
501 fprintf(stderr
, gettext("Input and output are identical; "
502 "incorrect use of lp.cat!\n"));
507 * The effective data transfer rate is the lesser
508 * of the transmission rate and print rate. If an
509 * argument was passed to us, it should be a data
510 * rate and it may be lower still.
511 * Based on the effective data transfer rate,
512 * we can predict the maximum delay we should experience.
513 * But there are other factors that could introduce
514 * delay, so let's be generous; after all, we'd rather
515 * err in favor of waiting too long to detect a fault
516 * than err too often on false alarms.
519 if (!(TERM
= getenv("TERM")) || !*TERM
) {
520 signal(SIGTERM
, SIG_IGN
);
521 fprintf(stderr
, gettext("No TERM variable defined! "
522 "Trouble with the Spooler!\n"));
525 if (!STREQU(TERM
, NAME_UNKNOWN
) &&
526 tidbit(TERM
, "cps", &print_rate
) == -1) {
527 signal(SIGTERM
, SIG_IGN
);
528 fprintf(stderr
, gettext("Trouble identifying printer "
529 "type \"%s\"; check the Terminfo database.\n"), TERM
);
532 if (STREQU(TERM
, NAME_UNKNOWN
))
535 effective_rate
= baudrate() / 10; /* okay for most bauds */
536 if (print_rate
!= -1 && print_rate
< effective_rate
)
537 effective_rate
= print_rate
;
538 if (argc
> 1 && (n
= atoi(argv
[1])) >= 0 && n
< effective_rate
)
539 effective_rate
= n
; /* 0 means infinite delay */
541 max_delay
= DELAY(BUFSIZ
, effective_rate
);
544 * We'll use the "alarm()" system call to keep us from
545 * waiting too long to write to a printer in trouble.
548 signal(SIGALRM
, sigalrm
);
551 * While not end of standard input, copy blocks to
554 while ((nin
= read(0, buffer
, BUFSIZ
)) > 0) {
558 * We should be safe from incomplete writes to a full
559 * pipe, as long as the size of the buffer we write is
560 * a even divisor of the pipe buffer limit. As long as
561 * we read from files or pipes (not communication devices)
562 * this should be true for all but the last buffer. The
563 * last will be smaller, and won't straddle the pipe max
564 * limit (think about it).
566 #if PIPE_BUF < BUFSIZ || (PIPE_MAX % BUFSIZ)
570 epoch_start
= times(&tms
);
576 nout
= write(1, ptr
, nin
);
579 fprintf(stderr
, gettext("Write failed "
580 "(%s);\nperhaps the printer has gone "
581 "off-line.\n"), PERROR
);
584 /* I/O error on device, get lpcshed to retry */
585 exit(PRINTER_IO_ERROR
);
586 else /* wait for printer to come back online */
596 else if (report_rate
) {
597 epoch_end
= times(&tms
);
598 if (epoch_end
- epoch_start
> 0)
599 fprintf(stderr
, "%d CPS\n",
601 (double)(epoch_end
- epoch_start
)));
610 * sighup() - CATCH A HANGUP (LOSS OF CARRIER)
615 signal(SIGTERM
, SIG_IGN
);
616 signal(SIGHUP
, SIG_IGN
);
617 fprintf(stderr
, gettext(HANGUP_FAULT_LPCAT
));
622 * sigint() - CATCH AN INTERRUPT
627 signal(SIGTERM
, SIG_IGN
);
628 signal(SIGINT
, SIG_IGN
);
629 fprintf(stderr
, gettext(INTERRUPT_FAULT
));
634 * sigpipe() - CATCH EARLY CLOSE OF PIPE
639 signal(SIGTERM
, SIG_IGN
);
640 signal(SIGPIPE
, SIG_IGN
);
641 fprintf(stderr
, gettext(PIPE_FAULT
));
646 * sigalrm() - CATCH AN ALARM
651 signal(SIGTERM
, SIG_IGN
);
652 fprintf(stderr
, gettext("Excessive write delay; "
653 "perhaps the printer has gone off-line.\n"));
658 * sigterm() - CATCH A TERMINATION SIGNAL
663 signal(SIGTERM
, SIG_IGN
);
665 * try to flush the output queue in the case of ecpp port.
666 * ignore the return code as this may not be the ecpp.
668 ioctl(1, I_FLUSH
, FLUSHW
);
673 * baudrate() - RETURN BAUD RATE OF OUTPUT LINE
676 static int baud_convert
[] =
678 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
679 1800, 2400, 4800, 9600, 19200, 38400, 57600,
680 76800, 115200, 153600, 230400, 307200, 460800, 921600
690 if (ioctl(1, TCGETS
, &tms
) < 0) {
691 if (ioctl(1, TCGETA
, &tm
) < 0)
694 speed
= tm
.c_cflag
&CBAUD
;
696 speed
= cfgetospeed(&tms
);
698 return (speed
? baud_convert
[speed
] : 1200);