xref: /illumos-gate/usr/src/cmd/lp/model/lp.cat.c (revision bbf21555)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5de81e71eSTim Marsland  * Common Development and Distribution License (the "License").
6de81e71eSTim Marsland  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21de81e71eSTim Marsland 
227c478bd9Sstevel@tonic-gate /*
23de81e71eSTim Marsland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
30ace1a5f1Sdp #include <stdio.h>
31ace1a5f1Sdp #include <stdlib.h>
32ace1a5f1Sdp #include <termio.h>
33ace1a5f1Sdp #include <sys/types.h>
34ace1a5f1Sdp #include <errno.h>
35ace1a5f1Sdp #include <signal.h>
36ace1a5f1Sdp #include <sys/times.h>
37ace1a5f1Sdp #include <string.h>
38ace1a5f1Sdp #include <limits.h>
397c478bd9Sstevel@tonic-gate #include <sys/prnio.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include "lp.h"
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #include <locale.h>
447c478bd9Sstevel@tonic-gate 
45de81e71eSTim Marsland /*
46de81e71eSTim Marsland  *	Begin Sun Additions for Parallel ports
47de81e71eSTim Marsland  */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #include <string.h>
507c478bd9Sstevel@tonic-gate #include <stdarg.h>
517c478bd9Sstevel@tonic-gate #include <signal.h>
527c478bd9Sstevel@tonic-gate #include <unistd.h>
537c478bd9Sstevel@tonic-gate #include <sys/types.h>
547c478bd9Sstevel@tonic-gate #include <sys/ioccom.h>
557c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #include <sys/bpp_io.h>
587c478bd9Sstevel@tonic-gate #include <sys/ecppsys.h>
597c478bd9Sstevel@tonic-gate #include <stropts.h>
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate  * the parameter structure for the parallel port
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate struct ppc_params_t {
657c478bd9Sstevel@tonic-gate 	int		flags;		/* same as above */
667c478bd9Sstevel@tonic-gate 	int		state;		/* status of the printer interface */
677c478bd9Sstevel@tonic-gate 	int		strobe_w;	/* strobe width, in uS */
687c478bd9Sstevel@tonic-gate 	int		data_setup;	/* data setup time, in uS */
697c478bd9Sstevel@tonic-gate 	int		ack_timeout;	/* ACK timeout, in secs */
707c478bd9Sstevel@tonic-gate 	int		error_timeout;	/* PAPER OUT, etc... timeout, in secs */
717c478bd9Sstevel@tonic-gate 	int		busy_timeout;	/* BUSY timeout, in seconds */
727c478bd9Sstevel@tonic-gate };
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static void printer_info(char *fmt, ...);
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*	These are the routines avaliable to others for use 	*/
797c478bd9Sstevel@tonic-gate int is_a_parallel_bpp(int);
807c478bd9Sstevel@tonic-gate int bpp_state(int);
817c478bd9Sstevel@tonic-gate int parallel_comm(int, int());
827c478bd9Sstevel@tonic-gate int get_ecpp_status(int fd);
837c478bd9Sstevel@tonic-gate int is_a_prnio(int);
847c478bd9Sstevel@tonic-gate int prnio_state(int);
857c478bd9Sstevel@tonic-gate 
86de81e71eSTim Marsland #define	PRINTER_ERROR_PAPER_OUT		1
87de81e71eSTim Marsland #define	PRINTER_ERROR_OFFLINE		2
88de81e71eSTim Marsland #define	PRINTER_ERROR_BUSY		3
89de81e71eSTim Marsland #define	PRINTER_ERROR_ERROR		4
90de81e71eSTim Marsland #define	PRINTER_ERROR_CABLE_POWER	5
91de81e71eSTim Marsland #define	PRINTER_ERROR_UNKNOWN		6
92de81e71eSTim Marsland #define	PRINTER_ERROR_TIMEOUT		7
937c478bd9Sstevel@tonic-gate #define	PRINTER_IO_ERROR		129
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 
96de81e71eSTim Marsland /*
977c478bd9Sstevel@tonic-gate  *	for BPP PARALLEL interfaces
98de81e71eSTim Marsland  */
997c478bd9Sstevel@tonic-gate 
100de81e71eSTim Marsland int
is_a_parallel_bpp(int fd)101de81e71eSTim Marsland is_a_parallel_bpp(int fd)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	if (ioctl(fd, BPPIOC_TESTIO) == 0 || errno == EIO)
104de81e71eSTim Marsland 		return (1);
105de81e71eSTim Marsland 	return (0);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #if defined(DEBUG) && defined(NOTDEF)
110de81e71eSTim Marsland char *
BppState(int state)111de81e71eSTim Marsland BppState(int state)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate 	static char buf[BUFSIZ];
1147c478bd9Sstevel@tonic-gate 
115de81e71eSTim Marsland 	memset(buf, 0, sizeof (buf));
116de81e71eSTim Marsland 	sprintf(buf, "State (0x%.4x) - (%s%s%s%s)\n", state,
117de81e71eSTim Marsland 	    ((state & BPP_SLCT_ERR) ?  "offline " : ""),
118de81e71eSTim Marsland 	    ((state & BPP_BUSY_ERR) ?  "busy " : ""),
119de81e71eSTim Marsland 	    ((state & BPP_PE_ERR) ?  "paper " : ""),
120de81e71eSTim Marsland 	    ((state & BPP_ERR_ERR) ?  "error " : ""));
1217c478bd9Sstevel@tonic-gate 
122de81e71eSTim Marsland 	return (buf);
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate #endif
1257c478bd9Sstevel@tonic-gate 
126de81e71eSTim Marsland int
bpp_state(int fd)127de81e71eSTim Marsland bpp_state(int fd)
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate 	if (ioctl(fd, BPPIOC_TESTIO)) {
1307c478bd9Sstevel@tonic-gate 		struct bpp_error_status  bpp_stat;
1317c478bd9Sstevel@tonic-gate 		int state;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 		if (ioctl(fd, BPPIOC_GETERR, &bpp_stat) < 0)
1347c478bd9Sstevel@tonic-gate 			exit(PRINTER_IO_ERROR);
1357c478bd9Sstevel@tonic-gate 		state = bpp_stat.pin_status;
1367c478bd9Sstevel@tonic-gate 
137de81e71eSTim Marsland #if defined(DEBUG) && defined(NOTDEF)
1387c478bd9Sstevel@tonic-gate 		logit("%s", BppState(state));
1397c478bd9Sstevel@tonic-gate #endif
140de81e71eSTim Marsland 
1417c478bd9Sstevel@tonic-gate 		if (state == (BPP_PE_ERR | BPP_ERR_ERR | BPP_SLCT_ERR)) {
1427c478bd9Sstevel@tonic-gate 			/* paper is out */
143de81e71eSTim Marsland 			return (PRINTER_ERROR_PAPER_OUT);
1447c478bd9Sstevel@tonic-gate 		} else if (state & BPP_BUSY_ERR) {
1457c478bd9Sstevel@tonic-gate 			/* printer is busy */
146de81e71eSTim Marsland 			return (PRINTER_ERROR_BUSY);
1477c478bd9Sstevel@tonic-gate 		} else if (state & BPP_SLCT_ERR) {
1487c478bd9Sstevel@tonic-gate 			/* printer is offline */
149de81e71eSTim Marsland 			return (PRINTER_ERROR_OFFLINE);
1507c478bd9Sstevel@tonic-gate 		} else if (state & BPP_ERR_ERR) {
1517c478bd9Sstevel@tonic-gate 			/* printer is errored */
152de81e71eSTim Marsland 			return (PRINTER_ERROR_ERROR);
1537c478bd9Sstevel@tonic-gate 		} else if (state == BPP_PE_ERR) {
1547c478bd9Sstevel@tonic-gate 			/* printer is off/unplugged */
155de81e71eSTim Marsland 			return (PRINTER_ERROR_CABLE_POWER);
1567c478bd9Sstevel@tonic-gate 		} else if (state) {
157de81e71eSTim Marsland 			return (PRINTER_ERROR_UNKNOWN);
1587c478bd9Sstevel@tonic-gate 		} else
159de81e71eSTim Marsland 			return (0);
1607c478bd9Sstevel@tonic-gate 	}
161de81e71eSTim Marsland 	return (0);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate  * For ecpp parallel port
1667c478bd9Sstevel@tonic-gate  */
1677c478bd9Sstevel@tonic-gate 
168de81e71eSTim Marsland int
get_ecpp_status(int fd)1697c478bd9Sstevel@tonic-gate get_ecpp_status(int fd)
1707c478bd9Sstevel@tonic-gate {
1717c478bd9Sstevel@tonic-gate 	int state;
1727c478bd9Sstevel@tonic-gate 	struct ecpp_transfer_parms transfer_parms;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	if (ioctl(fd, ECPPIOC_GETPARMS, &transfer_parms) == -1) {
176de81e71eSTim Marsland 		return (-1);
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	state = transfer_parms.mode;
1807c478bd9Sstevel@tonic-gate 	/*
1817c478bd9Sstevel@tonic-gate 	 * We don't know what all printers will return in
1827c478bd9Sstevel@tonic-gate 	 * nibble mode, therefore if we support nibble mode we will
1837c478bd9Sstevel@tonic-gate 	 * force the printer to be in CENTRONICS mode.
1847c478bd9Sstevel@tonic-gate 	 */
1857c478bd9Sstevel@tonic-gate 	if (state != ECPP_CENTRONICS) {
1867c478bd9Sstevel@tonic-gate 		transfer_parms.mode = ECPP_CENTRONICS;
1877c478bd9Sstevel@tonic-gate 		if (ioctl(fd, ECPPIOC_SETPARMS, &transfer_parms) == -1) {
188de81e71eSTim Marsland 			return (-1);
1897c478bd9Sstevel@tonic-gate 		} else {
1907c478bd9Sstevel@tonic-gate 			state = ECPP_CENTRONICS;
1917c478bd9Sstevel@tonic-gate 		}
1927c478bd9Sstevel@tonic-gate 	}
1937c478bd9Sstevel@tonic-gate 
194de81e71eSTim Marsland 
195de81e71eSTim Marsland 	return (state);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
198de81e71eSTim Marsland /*
199*bbf21555SRichard Lowe  * For prnio(4I) - generic printer interface
200de81e71eSTim Marsland  */
201de81e71eSTim Marsland int
is_a_prnio(int fd)202de81e71eSTim Marsland is_a_prnio(int fd)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate 	uint_t	cap;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/* check if device supports prnio */
2077c478bd9Sstevel@tonic-gate 	if (ioctl(fd, PRNIOC_GET_IFCAP, &cap) == -1) {
2087c478bd9Sstevel@tonic-gate 		return (0);
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 	/* we will use 1284 status if available */
2117c478bd9Sstevel@tonic-gate 	if ((cap & PRN_1284_STATUS) == 0) {
2127c478bd9Sstevel@tonic-gate 		/* some devices may only support 1284 status in unidir. mode */
2137c478bd9Sstevel@tonic-gate 		if (cap & PRN_BIDI) {
2147c478bd9Sstevel@tonic-gate 			cap &= ~PRN_BIDI;
2157c478bd9Sstevel@tonic-gate 			(void) ioctl(fd, PRNIOC_SET_IFCAP, &cap);
2167c478bd9Sstevel@tonic-gate 		}
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 	return (1);
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate 
221de81e71eSTim Marsland int
prnio_state(int fd)222de81e71eSTim Marsland prnio_state(int fd)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate 	uint_t	status;
2257c478bd9Sstevel@tonic-gate 	uchar_t	pins;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	if ((ioctl(fd, PRNIOC_GET_STATUS, &status) == 0) &&
2287c478bd9Sstevel@tonic-gate 	    (status & PRN_READY)) {
229de81e71eSTim Marsland 		return (0);
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	if (ioctl(fd, PRNIOC_GET_1284_STATUS, &pins) != 0) {
233de81e71eSTim Marsland 		return (PRINTER_ERROR_UNKNOWN);
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	if ((pins & ~PRN_1284_BUSY) == PRN_1284_PE) {
2377c478bd9Sstevel@tonic-gate 		/* paper is out */
238de81e71eSTim Marsland 		return (PRINTER_ERROR_PAPER_OUT);
2397c478bd9Sstevel@tonic-gate 	} else if (pins == (PRN_1284_PE | PRN_1284_SELECT |
240de81e71eSTim Marsland 	    PRN_1284_NOFAULT | PRN_1284_BUSY)) {
2417c478bd9Sstevel@tonic-gate 		/* printer is off/unplugged */
242de81e71eSTim Marsland 		return (PRINTER_ERROR_CABLE_POWER);
2437c478bd9Sstevel@tonic-gate 	} else if ((pins & PRN_1284_SELECT) == 0) {
2447c478bd9Sstevel@tonic-gate 		/* printer is offline */
245de81e71eSTim Marsland 		return (PRINTER_ERROR_OFFLINE);
2467c478bd9Sstevel@tonic-gate 	} else if ((pins & PRN_1284_NOFAULT) == 0) {
2477c478bd9Sstevel@tonic-gate 		/* printer is errored */
248de81e71eSTim Marsland 		return (PRINTER_ERROR_ERROR);
2497c478bd9Sstevel@tonic-gate 	} else if (pins & PRN_1284_PE) {
2507c478bd9Sstevel@tonic-gate 		/* paper is out */
251de81e71eSTim Marsland 		return (PRINTER_ERROR_PAPER_OUT);
2527c478bd9Sstevel@tonic-gate 	} else if (pins ^ (PRN_1284_SELECT | PRN_1284_NOFAULT)) {
253de81e71eSTim Marsland 		return (PRINTER_ERROR_UNKNOWN);
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 
256de81e71eSTim Marsland 	return (0);
2577c478bd9Sstevel@tonic-gate }
258de81e71eSTim Marsland 
259de81e71eSTim Marsland /*
2607c478bd9Sstevel@tonic-gate  *	Common routines
261de81e71eSTim Marsland  */
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate /*ARGSUSED0*/
2647c478bd9Sstevel@tonic-gate static void
ByeByeParallel(int sig)2657c478bd9Sstevel@tonic-gate ByeByeParallel(int sig)
2667c478bd9Sstevel@tonic-gate {
2677c478bd9Sstevel@tonic-gate 	/* try to shove out the EOT */
2687c478bd9Sstevel@tonic-gate 	(void) write(1, "\004", 1);
2697c478bd9Sstevel@tonic-gate 	exit(0);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate /*ARGSUSED0*/
2747c478bd9Sstevel@tonic-gate static void
printer_info(char * fmt,...)2757c478bd9Sstevel@tonic-gate printer_info(char *fmt, ...)
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate 	char mesg[BUFSIZ];
2787c478bd9Sstevel@tonic-gate 	va_list ap;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
2817c478bd9Sstevel@tonic-gate 	vsprintf(mesg, fmt, ap);
2827c478bd9Sstevel@tonic-gate 	va_end(ap);
2837c478bd9Sstevel@tonic-gate /*
284de81e71eSTim Marsland  *	fprintf(stderr,
285de81e71eSTim Marsland  *		"%%%%[ PrinterError: %s; source: parallel ]%%%%\n",
286de81e71eSTim Marsland  *		mesg);
287de81e71eSTim Marsland  */
2887c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s\n", mesg);
2897c478bd9Sstevel@tonic-gate 	fflush(stderr);
2907c478bd9Sstevel@tonic-gate 	fsync(2);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate static void
printer_error(int error)2957c478bd9Sstevel@tonic-gate printer_error(int error)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate 	switch (error) {
298de81e71eSTim Marsland 	case -1:
299de81e71eSTim Marsland 		printer_info("ioctl(): %s", strerror(errno));
300de81e71eSTim Marsland 		break;
301de81e71eSTim Marsland 	case PRINTER_ERROR_PAPER_OUT:
302de81e71eSTim Marsland 		printer_info("out of paper");
303de81e71eSTim Marsland 		break;
304de81e71eSTim Marsland 	case PRINTER_ERROR_OFFLINE:
305de81e71eSTim Marsland 		printer_info("offline");
306de81e71eSTim Marsland 		break;
307de81e71eSTim Marsland 	case PRINTER_ERROR_BUSY:
308de81e71eSTim Marsland 		printer_info("busy");
309de81e71eSTim Marsland 		break;
310de81e71eSTim Marsland 	case PRINTER_ERROR_ERROR:
311de81e71eSTim Marsland 		printer_info("printer error");
312de81e71eSTim Marsland 		break;
313de81e71eSTim Marsland 	case PRINTER_ERROR_CABLE_POWER:
314de81e71eSTim Marsland 		printer_info("printer powered off or disconnected");
315de81e71eSTim Marsland 		break;
316de81e71eSTim Marsland 	case PRINTER_ERROR_UNKNOWN:
317de81e71eSTim Marsland 		printer_info("unknown error");
318de81e71eSTim Marsland 		break;
319de81e71eSTim Marsland 	case PRINTER_ERROR_TIMEOUT:
320de81e71eSTim Marsland 		printer_info("communications timeout");
321de81e71eSTim Marsland 		break;
322de81e71eSTim Marsland 	default:
323de81e71eSTim Marsland 		printer_info("get_status() failed");
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate static void
wait_state(int fd,int get_state ())3297c478bd9Sstevel@tonic-gate wait_state(int fd, int get_state())
3307c478bd9Sstevel@tonic-gate {
3317c478bd9Sstevel@tonic-gate 	int state;
3327c478bd9Sstevel@tonic-gate 	int was_faulted = 0;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	while (state = get_state(fd)) {
335de81e71eSTim Marsland 		was_faulted = 1;
3367c478bd9Sstevel@tonic-gate 		printer_error(state);
3377c478bd9Sstevel@tonic-gate 		sleep(15);
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	if (was_faulted) {
3417c478bd9Sstevel@tonic-gate 		fprintf(stderr, "printer ok\n");
3427c478bd9Sstevel@tonic-gate 		fflush(stderr);
3437c478bd9Sstevel@tonic-gate 		fsync(2);
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate 
347de81e71eSTim Marsland /*
348de81e71eSTim Marsland  *  end of Sun Additions for parallel port
349de81e71eSTim Marsland  */
350de81e71eSTim Marsland #define	IDENTICAL(A, B)	(A.st_dev == B.st_dev && A.st_ino == B.st_ino)
351de81e71eSTim Marsland #define	ISBLK(A)	((A.st_mode & S_IFMT) == S_IFBLK)
352de81e71eSTim Marsland #define	ISCHR(A)	((A.st_mode & S_IFMT) == S_IFCHR)
353de81e71eSTim Marsland 
354de81e71eSTim Marsland #define	E_SUCCESS	0
355de81e71eSTim Marsland #define	E_BAD_INPUT	1
356de81e71eSTim Marsland #define	E_BAD_OUTPUT	2
357de81e71eSTim Marsland #define	E_BAD_TERM	3
358de81e71eSTim Marsland #define	E_IDENTICAL	4
3597c478bd9Sstevel@tonic-gate #define	E_WRITE_FAILED	5
3607c478bd9Sstevel@tonic-gate #define	E_TIMEOUT	6
361de81e71eSTim Marsland #define	E_HANGUP	7
362de81e71eSTim Marsland #define	E_INTERRUPT	8
3637c478bd9Sstevel@tonic-gate 
364de81e71eSTim Marsland #define	SAFETY_FACTOR	2.0
365de81e71eSTim Marsland #define	R(F)		(int)((F) + .5)
366de81e71eSTim Marsland #define	DELAY(N, D)	R(SAFETY_FACTOR * ((N) / (double)(D)))
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate char			buffer[BUFSIZ];
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate void			sighup(),
3717c478bd9Sstevel@tonic-gate 			sigint(),
3727c478bd9Sstevel@tonic-gate 			sigquit(),
3737c478bd9Sstevel@tonic-gate 			sigpipe(),
3747c478bd9Sstevel@tonic-gate 			sigalrm(),
3757c478bd9Sstevel@tonic-gate 			sigterm();
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate #if	defined(baudrate)
378de81e71eSTim Marsland #undef	baudrate
3797c478bd9Sstevel@tonic-gate #endif
3807c478bd9Sstevel@tonic-gate 
381de81e71eSTim Marsland int baudrate();
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 
384de81e71eSTim Marsland int
nop(int fd)385de81e71eSTim Marsland nop(int fd)
386de81e71eSTim Marsland {
387de81e71eSTim Marsland 	return (0);
388de81e71eSTim Marsland }
389de81e71eSTim Marsland 
3907c478bd9Sstevel@tonic-gate int bpp_state(int);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 
393de81e71eSTim Marsland /*
394de81e71eSTim Marsland  * main()
395de81e71eSTim Marsland  */
3967c478bd9Sstevel@tonic-gate 
397f928ce67Sceastha int
main(int argc,char * argv[])398f928ce67Sceastha main(int argc, char *argv[])
3997c478bd9Sstevel@tonic-gate {
400de81e71eSTim Marsland 	int	nin, nout, effective_rate, max_delay = 0, n;
401de81e71eSTim Marsland 	int	report_rate;
402de81e71eSTim Marsland 	short	print_rate;
403de81e71eSTim Marsland 	struct stat	in, out;
404de81e71eSTim Marsland 	struct tms	tms;
405de81e71eSTim Marsland 	long	epoch_start, epoch_end;
406de81e71eSTim Marsland 	char	*TERM;
407de81e71eSTim Marsland 	int	(*func)(int fd);
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	/*
4107c478bd9Sstevel@tonic-gate 	 * The Spooler can hit us with SIGTERM for three reasons:
4117c478bd9Sstevel@tonic-gate 	 *
4127c478bd9Sstevel@tonic-gate 	 *	- the user's job has been canceled
4137c478bd9Sstevel@tonic-gate 	 *	- the printer has been disabled while we were printing
4147c478bd9Sstevel@tonic-gate 	 *	- the Spooler heard that the printer has a fault,
4157c478bd9Sstevel@tonic-gate 	 *	  and the fault recovery is wait or beginning
4167c478bd9Sstevel@tonic-gate 	 *
4177c478bd9Sstevel@tonic-gate 	 * We should exit cleanly for the first two cases,
4187c478bd9Sstevel@tonic-gate 	 * but we have to be careful with the last. If it was THIS
4197c478bd9Sstevel@tonic-gate 	 * PROGRAM that told the Spooler about the fault, we must
4207c478bd9Sstevel@tonic-gate 	 * exit consistently.
4217c478bd9Sstevel@tonic-gate 	 *
4227c478bd9Sstevel@tonic-gate 	 * The method of avoiding any problem is to turn off the
4237c478bd9Sstevel@tonic-gate 	 * trapping of SIGTERM before telling the Spooler about
4247c478bd9Sstevel@tonic-gate 	 * the fault.
4257c478bd9Sstevel@tonic-gate 	 *
4267c478bd9Sstevel@tonic-gate 	 * Faults that we can detect:
4277c478bd9Sstevel@tonic-gate 	 *	- hangup (drop of carrier)
4287c478bd9Sstevel@tonic-gate 	 *	- interrupt (printer sent a break or quit character)
4297c478bd9Sstevel@tonic-gate 	 *	- SIGPIPE (output port is a FIFO, and was closed early)
4307c478bd9Sstevel@tonic-gate 	 *	- failed or incomplete write()
4317c478bd9Sstevel@tonic-gate 	 *	- excess delay in write() (handled with SIGALRM later)
4327c478bd9Sstevel@tonic-gate 	 *
4337c478bd9Sstevel@tonic-gate 	 * Pseudo-faults (errors in use):
4347c478bd9Sstevel@tonic-gate 	 *	- No input/output, or strange input/output
4357c478bd9Sstevel@tonic-gate 	 *	- Input/output identical
4367c478bd9Sstevel@tonic-gate 	 *	- No TERM defined or trouble reading Terminfo database
4377c478bd9Sstevel@tonic-gate 	 */
438de81e71eSTim Marsland 	signal(SIGTERM, sigterm);
439de81e71eSTim Marsland 	signal(SIGHUP, sighup);
440de81e71eSTim Marsland 	signal(SIGINT, sigint);
441de81e71eSTim Marsland 	signal(SIGQUIT, sigint);
442de81e71eSTim Marsland 	signal(SIGPIPE, sigpipe);
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	if (argc > 1 && STREQU(argv[1], "-r")) {
4467c478bd9Sstevel@tonic-gate 		report_rate = 1;
4477c478bd9Sstevel@tonic-gate 		argc--;
4487c478bd9Sstevel@tonic-gate 		argv++;
4497c478bd9Sstevel@tonic-gate 	} else
4507c478bd9Sstevel@tonic-gate 		report_rate = 0;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
4537c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
454de81e71eSTim Marsland #define	TEXT_DOMAIN "SYS_TEST"
4557c478bd9Sstevel@tonic-gate #endif
4567c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	/*
4597c478bd9Sstevel@tonic-gate 	 * Stat the standard output to be sure it is defined.
4607c478bd9Sstevel@tonic-gate 	 */
4617c478bd9Sstevel@tonic-gate 	if (fstat(1, &out) < 0) {
462de81e71eSTim Marsland 		signal(SIGTERM, SIG_IGN);
463de81e71eSTim Marsland 		fprintf(stderr, gettext("Can't stat output "
464de81e71eSTim Marsland 		    "(%s);\nincorrect use of lp.cat!\n"), PERROR);
465de81e71eSTim Marsland 		exit(E_BAD_OUTPUT);
4667c478bd9Sstevel@tonic-gate 	}
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	/*
4697c478bd9Sstevel@tonic-gate 	 * Stat the standard input to be sure it is defined.
4707c478bd9Sstevel@tonic-gate 	 */
4717c478bd9Sstevel@tonic-gate 	if (fstat(0, &in) < 0) {
472de81e71eSTim Marsland 		signal(SIGTERM, SIG_IGN);
473de81e71eSTim Marsland 		fprintf(stderr, gettext("Can't stat input "
474de81e71eSTim Marsland 		    "(%s);\nincorrect use of lp.cat!\n"), PERROR);
475de81e71eSTim Marsland 		exit(E_BAD_INPUT);
4767c478bd9Sstevel@tonic-gate 	}
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	/*
4797c478bd9Sstevel@tonic-gate 	 * If the standard output is not a character special file or a
4807c478bd9Sstevel@tonic-gate 	 * block special file, make sure it is not identical to the
4817c478bd9Sstevel@tonic-gate 	 * standard input.
4827c478bd9Sstevel@tonic-gate 	 *
4837c478bd9Sstevel@tonic-gate 	 * If we are an ecpp parallel port in centronics mode treat
4847c478bd9Sstevel@tonic-gate 	 * ourselves as a bpp compatible device.
4857c478bd9Sstevel@tonic-gate 	 */
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	if (is_a_prnio(1)) {
4887c478bd9Sstevel@tonic-gate 		func = prnio_state;
4897c478bd9Sstevel@tonic-gate 	} else if (is_a_parallel_bpp(1) ||
490de81e71eSTim Marsland 	    (get_ecpp_status(1) == ECPP_CENTRONICS)) {
4917c478bd9Sstevel@tonic-gate 		func = bpp_state;
492de81e71eSTim Marsland 	} else if (isatty(1)) {
4937c478bd9Sstevel@tonic-gate 		/* serial connection (probably) - continue as usual */
4947c478bd9Sstevel@tonic-gate 		func = nop;
495de81e71eSTim Marsland 	} else {
4967c478bd9Sstevel@tonic-gate 		func = nop;
497de81e71eSTim Marsland 	}
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	if (!ISCHR(out) && !ISBLK(out) && IDENTICAL(out, in)) {
500de81e71eSTim Marsland 		signal(SIGTERM, SIG_IGN);
501de81e71eSTim Marsland 		fprintf(stderr, gettext("Input and output are identical; "
502de81e71eSTim Marsland 		    "incorrect use of lp.cat!\n"));
503de81e71eSTim Marsland 		exit(E_IDENTICAL);
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	/*
5077c478bd9Sstevel@tonic-gate 	 * The effective data transfer rate is the lesser
5087c478bd9Sstevel@tonic-gate 	 * of the transmission rate and print rate. If an
5097c478bd9Sstevel@tonic-gate 	 * argument was passed to us, it should be a data
5107c478bd9Sstevel@tonic-gate 	 * rate and it may be lower still.
5117c478bd9Sstevel@tonic-gate 	 * Based on the effective data transfer rate,
5127c478bd9Sstevel@tonic-gate 	 * we can predict the maximum delay we should experience.
5137c478bd9Sstevel@tonic-gate 	 * But there are other factors that could introduce
5147c478bd9Sstevel@tonic-gate 	 * delay, so let's be generous; after all, we'd rather
5157c478bd9Sstevel@tonic-gate 	 * err in favor of waiting too long to detect a fault
5167c478bd9Sstevel@tonic-gate 	 * than err too often on false alarms.
5177c478bd9Sstevel@tonic-gate 	 */
5187c478bd9Sstevel@tonic-gate 
519de81e71eSTim Marsland 	if (!(TERM = getenv("TERM")) || !*TERM) {
520de81e71eSTim Marsland 		signal(SIGTERM, SIG_IGN);
521de81e71eSTim Marsland 		fprintf(stderr, gettext("No TERM variable defined! "
522de81e71eSTim Marsland 		    "Trouble with the Spooler!\n"));
523de81e71eSTim Marsland 		exit(E_BAD_TERM);
5247c478bd9Sstevel@tonic-gate 	}
525de81e71eSTim Marsland 	if (!STREQU(TERM, NAME_UNKNOWN) &&
526de81e71eSTim Marsland 	    tidbit(TERM, "cps", &print_rate) == -1) {
527de81e71eSTim Marsland 		signal(SIGTERM, SIG_IGN);
528de81e71eSTim Marsland 		fprintf(stderr, gettext("Trouble identifying printer "
529de81e71eSTim Marsland 		    "type \"%s\"; check the Terminfo database.\n"), TERM);
530de81e71eSTim Marsland 		exit(E_BAD_TERM);
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 	if (STREQU(TERM, NAME_UNKNOWN))
5337c478bd9Sstevel@tonic-gate 		print_rate = -1;
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	effective_rate = baudrate() / 10; /* okay for most bauds */
5367c478bd9Sstevel@tonic-gate 	if (print_rate != -1 && print_rate < effective_rate)
5377c478bd9Sstevel@tonic-gate 		effective_rate = print_rate;
5387c478bd9Sstevel@tonic-gate 	if (argc > 1 && (n = atoi(argv[1])) >= 0 && n < effective_rate)
5397c478bd9Sstevel@tonic-gate 		effective_rate = n;	  /* 0 means infinite delay */
5407c478bd9Sstevel@tonic-gate 	if (effective_rate)
5417c478bd9Sstevel@tonic-gate 		max_delay = DELAY(BUFSIZ, effective_rate);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	/*
5447c478bd9Sstevel@tonic-gate 	 * We'll use the "alarm()" system call to keep us from
5457c478bd9Sstevel@tonic-gate 	 * waiting too long to write to a printer in trouble.
5467c478bd9Sstevel@tonic-gate 	 */
5477c478bd9Sstevel@tonic-gate 	if (max_delay)
548de81e71eSTim Marsland 		signal(SIGALRM, sigalrm);
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	/*
5517c478bd9Sstevel@tonic-gate 	 * While not end of standard input, copy blocks to
5527c478bd9Sstevel@tonic-gate 	 * standard output.
5537c478bd9Sstevel@tonic-gate 	 */
5547c478bd9Sstevel@tonic-gate 	while ((nin = read(0, buffer, BUFSIZ)) > 0) {
5557c478bd9Sstevel@tonic-gate 		char *ptr = buffer;
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 		/*
5587c478bd9Sstevel@tonic-gate 		 * We should be safe from incomplete writes to a full
5597c478bd9Sstevel@tonic-gate 		 * pipe, as long as the size of the buffer we write is
5607c478bd9Sstevel@tonic-gate 		 * a even divisor of the pipe buffer limit. As long as
5617c478bd9Sstevel@tonic-gate 		 * we read from files or pipes (not communication devices)
5627c478bd9Sstevel@tonic-gate 		 * this should be true for all but the last buffer. The
5637c478bd9Sstevel@tonic-gate 		 * last will be smaller, and won't straddle the pipe max
5647c478bd9Sstevel@tonic-gate 		 * limit (think about it).
5657c478bd9Sstevel@tonic-gate 		 */
5667c478bd9Sstevel@tonic-gate #if	PIPE_BUF < BUFSIZ || (PIPE_MAX % BUFSIZ)
5677c478bd9Sstevel@tonic-gate 		this_wont_compile;
5687c478bd9Sstevel@tonic-gate #endif
5697c478bd9Sstevel@tonic-gate 		if (report_rate)
5707c478bd9Sstevel@tonic-gate 			epoch_start = times(&tms);
5717c478bd9Sstevel@tonic-gate 		do {
5727c478bd9Sstevel@tonic-gate 			wait_state(1, func);
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 			if (max_delay)
575de81e71eSTim Marsland 				alarm(max_delay);
5767c478bd9Sstevel@tonic-gate 			nout = write(1, ptr, nin);
5777c478bd9Sstevel@tonic-gate 			alarm(0);
5787c478bd9Sstevel@tonic-gate 			if (nout < 0) {
579de81e71eSTim Marsland 				fprintf(stderr, gettext("Write failed "
580de81e71eSTim Marsland 				    "(%s);\nperhaps the printer has gone "
581de81e71eSTim Marsland 				    "off-line.\n"), PERROR);
5827c478bd9Sstevel@tonic-gate 				fflush(stderr);
5837c478bd9Sstevel@tonic-gate 				if (errno != EINTR)
5847c478bd9Sstevel@tonic-gate 				/* I/O error on device, get lpcshed to retry */
5857c478bd9Sstevel@tonic-gate 					exit(PRINTER_IO_ERROR);
5867c478bd9Sstevel@tonic-gate 				else /* wait for printer to come back online */
5877c478bd9Sstevel@tonic-gate 					sleep(15);
5887c478bd9Sstevel@tonic-gate 			} else {
5897c478bd9Sstevel@tonic-gate 				nin -= nout;
5907c478bd9Sstevel@tonic-gate 				ptr += nout;
5917c478bd9Sstevel@tonic-gate 			}
5927c478bd9Sstevel@tonic-gate 		} while (nin > 0);
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 		if (max_delay)
595de81e71eSTim Marsland 			alarm(0);
5967c478bd9Sstevel@tonic-gate 		else if (report_rate) {
5977c478bd9Sstevel@tonic-gate 			epoch_end = times(&tms);
5987c478bd9Sstevel@tonic-gate 			if (epoch_end - epoch_start > 0)
599de81e71eSTim Marsland 				fprintf(stderr, "%d CPS\n",
600de81e71eSTim Marsland 				    R((100 * BUFSIZ) /
601de81e71eSTim Marsland 				    (double)(epoch_end - epoch_start)));
6027c478bd9Sstevel@tonic-gate 		}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
606f928ce67Sceastha 	return (E_SUCCESS);
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate 
609de81e71eSTim Marsland /*
610de81e71eSTim Marsland  * sighup() - CATCH A HANGUP (LOSS OF CARRIER)
611de81e71eSTim Marsland  */
612de81e71eSTim Marsland void
sighup()613de81e71eSTim Marsland sighup()
6147c478bd9Sstevel@tonic-gate {
615de81e71eSTim Marsland 	signal(SIGTERM, SIG_IGN);
616de81e71eSTim Marsland 	signal(SIGHUP, SIG_IGN);
617de81e71eSTim Marsland 	fprintf(stderr, gettext(HANGUP_FAULT_LPCAT));
618de81e71eSTim Marsland 	exit(E_HANGUP);
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate 
621de81e71eSTim Marsland /*
622de81e71eSTim Marsland  * sigint() - CATCH AN INTERRUPT
623de81e71eSTim Marsland  */
624de81e71eSTim Marsland void
sigint()625de81e71eSTim Marsland sigint()
6267c478bd9Sstevel@tonic-gate {
627de81e71eSTim Marsland 	signal(SIGTERM, SIG_IGN);
628de81e71eSTim Marsland 	signal(SIGINT, SIG_IGN);
629de81e71eSTim Marsland 	fprintf(stderr, gettext(INTERRUPT_FAULT));
630de81e71eSTim Marsland 	exit(E_INTERRUPT);
6317c478bd9Sstevel@tonic-gate }
6327c478bd9Sstevel@tonic-gate 
633de81e71eSTim Marsland /*
634de81e71eSTim Marsland  * sigpipe() - CATCH EARLY CLOSE OF PIPE
635de81e71eSTim Marsland  */
636de81e71eSTim Marsland void
sigpipe()637de81e71eSTim Marsland sigpipe()
6387c478bd9Sstevel@tonic-gate {
639de81e71eSTim Marsland 	signal(SIGTERM, SIG_IGN);
640de81e71eSTim Marsland 	signal(SIGPIPE, SIG_IGN);
641de81e71eSTim Marsland 	fprintf(stderr, gettext(PIPE_FAULT));
642de81e71eSTim Marsland 	exit(E_INTERRUPT);
6437c478bd9Sstevel@tonic-gate }
6447c478bd9Sstevel@tonic-gate 
645de81e71eSTim Marsland /*
646de81e71eSTim Marsland  * sigalrm() - CATCH AN ALARM
647de81e71eSTim Marsland  */
648de81e71eSTim Marsland void
sigalrm()649de81e71eSTim Marsland sigalrm()
6507c478bd9Sstevel@tonic-gate {
651de81e71eSTim Marsland 	signal(SIGTERM, SIG_IGN);
652de81e71eSTim Marsland 	fprintf(stderr, gettext("Excessive write delay; "
653de81e71eSTim Marsland 	    "perhaps the printer has gone off-line.\n"));
654de81e71eSTim Marsland 	exit(E_TIMEOUT);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate 
657de81e71eSTim Marsland /*
658de81e71eSTim Marsland  * sigterm() - CATCH A TERMINATION SIGNAL
659de81e71eSTim Marsland  */
660de81e71eSTim Marsland void
sigterm()661de81e71eSTim Marsland sigterm()
6627c478bd9Sstevel@tonic-gate {
663de81e71eSTim Marsland 	signal(SIGTERM, SIG_IGN);
6647c478bd9Sstevel@tonic-gate 	/*
6657c478bd9Sstevel@tonic-gate 	 * try to flush the output queue in the case of ecpp port.
6667c478bd9Sstevel@tonic-gate 	 * ignore the return code as this may not be the ecpp.
6677c478bd9Sstevel@tonic-gate 	 */
6687c478bd9Sstevel@tonic-gate 	ioctl(1, I_FLUSH, FLUSHW);
669de81e71eSTim Marsland 	exit(E_SUCCESS);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate 
672de81e71eSTim Marsland /*
673de81e71eSTim Marsland  * baudrate() - RETURN BAUD RATE OF OUTPUT LINE
674de81e71eSTim Marsland  */
6757c478bd9Sstevel@tonic-gate 
676d9c3e05cSJoshua M. Clulow static int baud_convert[] = {
677d9c3e05cSJoshua M. Clulow 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
6787c478bd9Sstevel@tonic-gate 	1800, 2400, 4800, 9600, 19200, 38400, 57600,
679d9c3e05cSJoshua M. Clulow 	76800, 115200, 153600, 230400, 307200, 460800, 921600,
680d9c3e05cSJoshua M. Clulow 	1000000, 1152000, 1500000, 2000000, 2500000, 3000000,
681d9c3e05cSJoshua M. Clulow 	3500000, 4000000
6827c478bd9Sstevel@tonic-gate };
6837c478bd9Sstevel@tonic-gate 
684de81e71eSTim Marsland int
baudrate()685de81e71eSTim Marsland baudrate()
6867c478bd9Sstevel@tonic-gate {
6877c478bd9Sstevel@tonic-gate 	struct termio		tm;
6887c478bd9Sstevel@tonic-gate 	struct termios		tms;
6897c478bd9Sstevel@tonic-gate 	int			speed;
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	if (ioctl(1, TCGETS, &tms) < 0) {
692d9c3e05cSJoshua M. Clulow 		if (ioctl(1, TCGETA, &tm) < 0) {
6937c478bd9Sstevel@tonic-gate 			return (1200);
694d9c3e05cSJoshua M. Clulow 		} else {
6957c478bd9Sstevel@tonic-gate 			speed = tm.c_cflag&CBAUD;
696d9c3e05cSJoshua M. Clulow 		}
697d9c3e05cSJoshua M. Clulow 	} else {
6987c478bd9Sstevel@tonic-gate 		speed = cfgetospeed(&tms);
699d9c3e05cSJoshua M. Clulow 	}
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	return (speed ? baud_convert[speed] : 1200);
7027c478bd9Sstevel@tonic-gate }
703