xref: /titanic_52/usr/src/lib/libbc/libc/gen/common/posix_tty.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
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 1995 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * wrappers for posix tty manipulation functions
31  */
32 
33 #include <errno.h>
34 #include <termios.h>
35 #include <termio.h>
36 #include <sys/types.h>
37 
38 /*
39  * return the output speed from the struct
40  */
41 speed_t
42 cfgetospeed(struct termios *termios_p)
43 {
44 	return (termios_p->c_cflag & CBAUDEXT ?
45 			(termios_p->c_cflag & CBAUD) + CBAUD + 1 :
46 			termios_p->c_cflag & CBAUD);
47 }
48 
49 /*
50  * set the speed in the struct
51  */
52 int
53 cfsetospeed(struct termios *termios_p, speed_t speed)
54 {
55 	if (speed > (2*CBAUD + 1)) {
56 		errno = EINVAL;
57 		return (-1);
58 	}
59 	if (speed > CBAUD) {
60 		termios_p->c_cflag |= CBAUDEXT;
61 		speed -= (CBAUD + 1);
62 	} else
63 		termios_p->c_cflag &= ~CBAUDEXT;
64 
65 	termios_p->c_cflag =
66 	    (termios_p->c_cflag & ~CBAUD) | (speed & CBAUD);
67 	return (0);
68 }
69 
70 /*
71  * return the input speed from the struct
72  */
73 speed_t
74 cfgetispeed(struct termios *termios_p)
75 {
76 	return (termios_p->c_cflag & CIBAUDEXT ?
77 	    ((termios_p->c_cflag & CIBAUD) >> IBSHIFT)
78 		+ (CIBAUD >> IBSHIFT) + 1 :
79 	    (termios_p->c_cflag & CIBAUD) >> IBSHIFT);
80 }
81 
82 /*
83  * set the input speed in the struct
84  */
85 int
86 cfsetispeed(struct termios *termios_p, speed_t speed)
87 {
88 	if (speed > (2*CBAUD + 1)) {
89 		errno = EINVAL;
90 		return (-1);
91 	}
92 	if ((speed << IBSHIFT) > CIBAUD) {
93 		termios_p->c_cflag |= CIBAUDEXT;
94 		speed -= ((CIBAUD >> IBSHIFT) + 1);
95 	} else
96 		termios_p->c_cflag &= ~CIBAUDEXT;
97 	termios_p->c_cflag =
98 	    (termios_p->c_cflag & ~CIBAUD) | ((speed << IBSHIFT) & CIBAUD);
99 	return (0);
100 }
101 
102 /*
103  * grab the modes
104  */
105 int
106 tcgetattr(int fd, struct termios *termios_p)
107 {
108 	return (ioctl(fd, TCGETS, termios_p));
109 }
110 
111 /*
112  * set the modes
113  */
114 int
115 tcsetattr(int fd, int option, struct termios *termios_p)
116 {
117 	struct termios	work_area;
118 
119 	/* If input speed is zero, set it to the output speed. */
120 	if ((((termios_p->c_cflag >> IBSHIFT) & CIBAUD) == 0) &&
121 		((termios_p->c_cflag & CIBAUDEXT) == 0)) {
122 		work_area = *termios_p;
123 		work_area.c_cflag |= (work_area.c_cflag & CBAUD) << IBSHIFT;
124 		if (termios_p->c_cflag & CBAUDEXT)
125 			work_area.c_cflag |= CIBAUDEXT;
126 		termios_p = &work_area;
127 	}
128 	switch (option) {
129 	case TCSADRAIN:
130 		return (ioctl(fd, TCSETSW, termios_p));
131 	case TCSAFLUSH:
132 		return (ioctl(fd, TCSETSF, termios_p));
133 	case TCSANOW:
134 		return (ioctl(fd, TCSETS, termios_p));
135 	default:
136 		errno = EINVAL;
137 		return (-1);
138 	}
139 	/*NOTREACHED*/
140 }
141 
142 /*
143  * send a break
144  * This is kludged for duration != 0; it should do something like crank the
145  * baud rate down and then send the break if the duration != 0.
146  */
147 int
148 tcsendbreak(int fd, int duration)
149 {
150 	unsigned d = (unsigned)duration;
151 
152 	do
153 		if (ioctl(fd, TCSBRK, 0) == -1)
154 			return (-1);
155 	while (d--);
156 	return (0);
157 }
158 
159 /*
160  * wait for all output to drain from fd
161  */
162 int
163 tcdrain(int fd)
164 {
165 	return (ioctl(fd, TCSBRK, !0));
166 }
167 
168 /*
169  * flow control
170  */
171 int
172 tcflow(int fd, int action)
173 {
174 	switch (action) {
175 	default:
176 		errno = EINVAL;
177 		return (-1);
178 	case TCOOFF:
179 	case TCOON:
180 	case TCIOFF:
181 	case TCION:
182 		return (ioctl(fd, TCXONC, action));
183 	}
184 	/*NOTREACHED*/
185 }
186 
187 /*
188  * flush read/write/both
189  */
190 int
191 tcflush(int fd, int queue)
192 {
193 	switch (queue) {
194 	default:
195 		errno = EINVAL;
196 		return (-1);
197 	case TCIFLUSH:
198 	case TCOFLUSH:
199 	case TCIOFLUSH:
200 		return (ioctl(fd, TCFLSH, queue));
201 	}
202 	/*NOTREACHED*/
203 }
204 
205 /*
206  * get the foreground process group id
207  */
208 pid_t
209 tcgetpgrp(int fd)
210 {
211 	int grp_id;
212 
213 	if (ioctl(fd, TIOCGETPGRP, &grp_id) == -1)
214 		return ((pid_t)-1);
215 	else
216 		return ((pid_t)grp_id);
217 }
218 
219 /*
220  * set the foreground process group id
221  */
222 int
223 tcsetpgrp(int fd, int grp_id)
224 {
225 	return (ioctl(fd, TIOCSETPGRP, &grp_id));
226 }
227