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
cfgetospeed(struct termios * termios_p)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
cfsetospeed(struct termios * termios_p,speed_t speed)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
cfgetispeed(struct termios * termios_p)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
cfsetispeed(struct termios * termios_p,speed_t speed)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
tcgetattr(int fd,struct termios * termios_p)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
tcsetattr(int fd,int option,struct termios * termios_p)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
tcsendbreak(int fd,int duration)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
tcdrain(int fd)163 tcdrain(int fd)
164 {
165 return (ioctl(fd, TCSBRK, !0));
166 }
167
168 /*
169 * flow control
170 */
171 int
tcflow(int fd,int action)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
tcflush(int fd,int queue)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
tcgetpgrp(int fd)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
tcsetpgrp(int fd,int grp_id)223 tcsetpgrp(int fd, int grp_id)
224 {
225 return (ioctl(fd, TIOCSETPGRP, &grp_id));
226 }
227