10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate * Copyright 1995 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
27*722Smuffin #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * wrappers for posix tty manipulation functions
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include <errno.h>
340Sstevel@tonic-gate #include <termios.h>
350Sstevel@tonic-gate #include <termio.h>
360Sstevel@tonic-gate #include <sys/types.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate * return the output speed from the struct
400Sstevel@tonic-gate */
410Sstevel@tonic-gate speed_t
cfgetospeed(struct termios * termios_p)42*722Smuffin cfgetospeed(struct termios *termios_p)
430Sstevel@tonic-gate {
440Sstevel@tonic-gate return (termios_p->c_cflag & CBAUDEXT ?
450Sstevel@tonic-gate (termios_p->c_cflag & CBAUD) + CBAUD + 1 :
460Sstevel@tonic-gate termios_p->c_cflag & CBAUD);
470Sstevel@tonic-gate }
480Sstevel@tonic-gate
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate * set the speed in the struct
510Sstevel@tonic-gate */
52*722Smuffin int
cfsetospeed(struct termios * termios_p,speed_t speed)53*722Smuffin cfsetospeed(struct termios *termios_p, speed_t speed)
540Sstevel@tonic-gate {
550Sstevel@tonic-gate if (speed > (2*CBAUD + 1)) {
560Sstevel@tonic-gate errno = EINVAL;
570Sstevel@tonic-gate return (-1);
580Sstevel@tonic-gate }
590Sstevel@tonic-gate if (speed > CBAUD) {
600Sstevel@tonic-gate termios_p->c_cflag |= CBAUDEXT;
610Sstevel@tonic-gate speed -= (CBAUD + 1);
620Sstevel@tonic-gate } else
630Sstevel@tonic-gate termios_p->c_cflag &= ~CBAUDEXT;
640Sstevel@tonic-gate
650Sstevel@tonic-gate termios_p->c_cflag =
660Sstevel@tonic-gate (termios_p->c_cflag & ~CBAUD) | (speed & CBAUD);
670Sstevel@tonic-gate return (0);
680Sstevel@tonic-gate }
690Sstevel@tonic-gate
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate * return the input speed from the struct
720Sstevel@tonic-gate */
730Sstevel@tonic-gate speed_t
cfgetispeed(struct termios * termios_p)74*722Smuffin cfgetispeed(struct termios *termios_p)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate return (termios_p->c_cflag & CIBAUDEXT ?
770Sstevel@tonic-gate ((termios_p->c_cflag & CIBAUD) >> IBSHIFT)
780Sstevel@tonic-gate + (CIBAUD >> IBSHIFT) + 1 :
790Sstevel@tonic-gate (termios_p->c_cflag & CIBAUD) >> IBSHIFT);
800Sstevel@tonic-gate }
810Sstevel@tonic-gate
820Sstevel@tonic-gate /*
830Sstevel@tonic-gate * set the input speed in the struct
840Sstevel@tonic-gate */
85*722Smuffin int
cfsetispeed(struct termios * termios_p,speed_t speed)86*722Smuffin cfsetispeed(struct termios *termios_p, speed_t speed)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate if (speed > (2*CBAUD + 1)) {
890Sstevel@tonic-gate errno = EINVAL;
900Sstevel@tonic-gate return (-1);
910Sstevel@tonic-gate }
920Sstevel@tonic-gate if ((speed << IBSHIFT) > CIBAUD) {
930Sstevel@tonic-gate termios_p->c_cflag |= CIBAUDEXT;
940Sstevel@tonic-gate speed -= ((CIBAUD >> IBSHIFT) + 1);
950Sstevel@tonic-gate } else
960Sstevel@tonic-gate termios_p->c_cflag &= ~CIBAUDEXT;
970Sstevel@tonic-gate termios_p->c_cflag =
980Sstevel@tonic-gate (termios_p->c_cflag & ~CIBAUD) | ((speed << IBSHIFT) & CIBAUD);
990Sstevel@tonic-gate return (0);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate /*
1030Sstevel@tonic-gate * grab the modes
1040Sstevel@tonic-gate */
105*722Smuffin int
tcgetattr(int fd,struct termios * termios_p)106*722Smuffin tcgetattr(int fd, struct termios *termios_p)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate return (ioctl(fd, TCGETS, termios_p));
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate * set the modes
1130Sstevel@tonic-gate */
114*722Smuffin int
tcsetattr(int fd,int option,struct termios * termios_p)115*722Smuffin tcsetattr(int fd, int option, struct termios *termios_p)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate struct termios work_area;
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate /* If input speed is zero, set it to the output speed. */
1200Sstevel@tonic-gate if ((((termios_p->c_cflag >> IBSHIFT) & CIBAUD) == 0) &&
1210Sstevel@tonic-gate ((termios_p->c_cflag & CIBAUDEXT) == 0)) {
1220Sstevel@tonic-gate work_area = *termios_p;
1230Sstevel@tonic-gate work_area.c_cflag |= (work_area.c_cflag & CBAUD) << IBSHIFT;
1240Sstevel@tonic-gate if (termios_p->c_cflag & CBAUDEXT)
1250Sstevel@tonic-gate work_area.c_cflag |= CIBAUDEXT;
1260Sstevel@tonic-gate termios_p = &work_area;
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate switch (option) {
1290Sstevel@tonic-gate case TCSADRAIN:
1300Sstevel@tonic-gate return (ioctl(fd, TCSETSW, termios_p));
1310Sstevel@tonic-gate case TCSAFLUSH:
1320Sstevel@tonic-gate return (ioctl(fd, TCSETSF, termios_p));
1330Sstevel@tonic-gate case TCSANOW:
1340Sstevel@tonic-gate return (ioctl(fd, TCSETS, termios_p));
1350Sstevel@tonic-gate default:
1360Sstevel@tonic-gate errno = EINVAL;
1370Sstevel@tonic-gate return (-1);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate /*NOTREACHED*/
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * send a break
1440Sstevel@tonic-gate * This is kludged for duration != 0; it should do something like crank the
1450Sstevel@tonic-gate * baud rate down and then send the break if the duration != 0.
1460Sstevel@tonic-gate */
147*722Smuffin int
tcsendbreak(int fd,int duration)148*722Smuffin tcsendbreak(int fd, int duration)
1490Sstevel@tonic-gate {
150*722Smuffin unsigned d = (unsigned)duration;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate do
1530Sstevel@tonic-gate if (ioctl(fd, TCSBRK, 0) == -1)
1540Sstevel@tonic-gate return (-1);
1550Sstevel@tonic-gate while (d--);
1560Sstevel@tonic-gate return (0);
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * wait for all output to drain from fd
1610Sstevel@tonic-gate */
162*722Smuffin int
tcdrain(int fd)163*722Smuffin tcdrain(int fd)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate return (ioctl(fd, TCSBRK, !0));
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate * flow control
1700Sstevel@tonic-gate */
171*722Smuffin int
tcflow(int fd,int action)172*722Smuffin tcflow(int fd, int action)
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate switch (action) {
1750Sstevel@tonic-gate default:
1760Sstevel@tonic-gate errno = EINVAL;
1770Sstevel@tonic-gate return (-1);
1780Sstevel@tonic-gate case TCOOFF:
1790Sstevel@tonic-gate case TCOON:
1800Sstevel@tonic-gate case TCIOFF:
1810Sstevel@tonic-gate case TCION:
1820Sstevel@tonic-gate return (ioctl(fd, TCXONC, action));
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate /*NOTREACHED*/
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate /*
1880Sstevel@tonic-gate * flush read/write/both
1890Sstevel@tonic-gate */
190*722Smuffin int
tcflush(int fd,int queue)191*722Smuffin tcflush(int fd, int queue)
1920Sstevel@tonic-gate {
1930Sstevel@tonic-gate switch (queue) {
1940Sstevel@tonic-gate default:
1950Sstevel@tonic-gate errno = EINVAL;
1960Sstevel@tonic-gate return (-1);
1970Sstevel@tonic-gate case TCIFLUSH:
1980Sstevel@tonic-gate case TCOFLUSH:
1990Sstevel@tonic-gate case TCIOFLUSH:
2000Sstevel@tonic-gate return (ioctl(fd, TCFLSH, queue));
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate /*NOTREACHED*/
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate /*
2060Sstevel@tonic-gate * get the foreground process group id
2070Sstevel@tonic-gate */
2080Sstevel@tonic-gate pid_t
tcgetpgrp(int fd)209*722Smuffin tcgetpgrp(int fd)
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate int grp_id;
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate if (ioctl(fd, TIOCGETPGRP, &grp_id) == -1)
2140Sstevel@tonic-gate return ((pid_t)-1);
2150Sstevel@tonic-gate else
2160Sstevel@tonic-gate return ((pid_t)grp_id);
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate /*
2200Sstevel@tonic-gate * set the foreground process group id
2210Sstevel@tonic-gate */
222*722Smuffin int
tcsetpgrp(int fd,int grp_id)223*722Smuffin tcsetpgrp(int fd, int grp_id)
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate return (ioctl(fd, TIOCSETPGRP, &grp_id));
2260Sstevel@tonic-gate }
227