diff options
Diffstat (limited to 'libbsd/sgtty.c')
-rw-r--r-- | libbsd/sgtty.c | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/libbsd/sgtty.c b/libbsd/sgtty.c new file mode 100644 index 0000000..c3cecc1 --- /dev/null +++ b/libbsd/sgtty.c @@ -0,0 +1,272 @@ +/* sgtty.c - emulate BSD sgtty stuff with termios - ross biro, rick sladkey */ + +#define _SGTTY_SOURCE + +#include <bsd/sgtty.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <termios.h> + +struct mask +{ + unsigned short mask; + unsigned short res; +}; + +struct sf +{ + struct mask iflag; + struct mask oflag; + struct mask cflag; + struct mask lflag; +}; + +static struct sf trans[] = +{ + /* order is important here. */ + /* iflag oflag cflag lflag */ + /* this needs to be fixed. */ + {{0,0}, {OPOST,0}, {0,0}, {ISIG,0}}, /* O_RAW */ + {{0,0}, {0,0}, {0,0}, {XCASE,XCASE}}, /* O_LCASE */ + {{ICRNL,ICRNL}, {ONLCR, ONLCR}, {0,0}, {0,0}}, /* O_CRMOD */ + {{0,0}, {0,0}, {0,0}, {ECHO,ECHO}}, /* O_ECHO */ + {{0,0}, {0,0}, {PARENB|PARODD,PARENB|PARODD}, {0,0}},/* O_ODDP */ + {{0,0}, {0,0}, {PARENB|PARODD,PARENB}, {0,0}}, /* O_EVENP */ + {{0,0}, {0,0}, {0,0}, {ICANON,0}}, /* O_CBREAK */ +}; + +#define _BSD_VDISABLE 255 + +static int +bchar (c) +unsigned char c; +{ + return c == _POSIX_VDISABLE ? _BSD_VDISABLE : c; +} + +static int +pchar (c) +unsigned char c; +{ + return c == _BSD_VDISABLE ? _POSIX_VDISABLE : c; +} + +int +gtty (fd,sg) +int fd; +struct sgttyb *sg; +{ + struct termios t; + int err; + int i; + err = ioctl (fd, TCGETS, &t); + if (err < 0) return (err); + sg->sg_ispeed = cfgetispeed (&t); + sg->sg_ospeed = cfgetospeed (&t); + sg->sg_erase = bchar (t.c_cc[VERASE]); + sg->sg_kill = bchar (t.c_cc[VKILL]); + sg->sg_flags = 0; + for (i = 0; i < sizeof (trans) / sizeof (struct sf); i++) + { + if ((t.c_iflag & trans[i].iflag.mask) == trans[i].iflag.res && + (t.c_oflag & trans[i].oflag.mask) == trans[i].oflag.res && + (t.c_cflag & trans[i].cflag.mask) == trans[i].cflag.res && + (t.c_lflag & trans[i].lflag.mask) == trans[i].lflag.res) + { + sg->sg_flags |= 1 << i; + } + } + return (0); +} + +static int +tiocset (fd,sg,method) +int fd; +struct sgttyb *sg; +int method; +{ + struct termios t; + int err; + int i; + err = ioctl (fd, TCGETS, &t); + if (err < 0) return (err); + + cfsetispeed (&t, sg->sg_ispeed); + cfsetospeed (&t, sg->sg_ospeed); + t.c_cc[VERASE] = pchar (sg->sg_erase); + t.c_cc[VKILL] = pchar (sg->sg_kill); + for (i = sizeof (trans) / sizeof (struct sf) - 1; i >= 0; i--) + { + t.c_iflag &= ~trans[i].iflag.mask; + t.c_oflag &= ~trans[i].oflag.mask; + t.c_cflag &= ~trans[i].cflag.mask; + t.c_lflag &= ~trans[i].lflag.mask; + if (sg->sg_flags & (1 << i)) + { + t.c_iflag |= trans[i].iflag.res; + t.c_oflag |= trans[i].oflag.res; + t.c_cflag |= trans[i].cflag.res; + t.c_lflag |= trans[i].lflag.res; + } + else + { + t.c_iflag |= (~trans[i].iflag.res) & trans[i].iflag.mask; + t.c_oflag |= (~trans[i].oflag.res) & trans[i].oflag.mask; + t.c_cflag |= (~trans[i].cflag.res) & trans[i].cflag.mask; + t.c_lflag |= (~trans[i].lflag.res) & trans[i].lflag.mask; + } + } + return (ioctl (fd, method, &t)); +} + +int +stty (fd,sg) +int fd; +struct sgttyb *sg; +{ + return tiocset (fd, sg, TCSETSF); +} + +static int +tiocsetn (fd,sg) +int fd; +struct sgttyb *sg; +{ + return tiocset (fd, sg, TCSETS); +} + +static int +tiocgetc (fd,tc) +int fd; +struct tchars *tc; +{ + struct termios t; + int err; + err = ioctl (fd, TCGETS, &t); + if (err < 0) return (err); + tc->t_intrc = bchar (t.c_cc[VINTR]); + tc->t_quitc = bchar (t.c_cc[VQUIT]); + tc->t_eofc = bchar (t.c_cc[VEOF]); + tc->t_startc = bchar (t.c_cc[VSTART]); + tc->t_stopc = bchar (t.c_cc[VSTOP]); + tc->t_brkc = bchar (t.c_cc[VEOL]); + return (0); +} + +static int +tiocsetc (fd,tc) +int fd; +struct tchars *tc; +{ + struct termios t; + int err; + err = ioctl (fd, TCGETS, &t); + if (err < 0) return (err); + t.c_cc[VINTR] = pchar (tc->t_intrc); + t.c_cc[VQUIT] = pchar (tc->t_quitc); + t.c_cc[VEOF] = pchar (tc->t_eofc); + t.c_cc[VEOL] = pchar (tc->t_brkc); + t.c_cc[VSTART] = pchar (tc->t_startc); + t.c_cc[VSTOP] = pchar (tc->t_stopc); + return (ioctl (fd, TCSETS, &t)); +} + +static int +tiocgltc (fd,tc) +int fd; +struct ltchars *tc; +{ + struct termios t; + int err; + err = ioctl (fd, TCGETS, &t); + if (err < 0) return (err); + tc->t_werasc = bchar (t.c_cc[VWERASE]); + tc->t_suspc = bchar (t.c_cc[VSUSP]); + tc->t_dsuspc = bchar (t.c_cc[VSUSP]); + tc->t_rprntc = bchar (t.c_cc[VREPRINT]); + tc->t_flushc = bchar (t.c_cc[VDISCARD]); + tc->t_lnextc = bchar (t.c_cc[VLNEXT]); + return (0); +} + +static int +tiocsltc (fd,tc) +int fd; +struct ltchars *tc; +{ + struct termios t; + int err; + err = ioctl (fd, TCGETS, &t); + if (err < 0) return (err); + t.c_cc[VWERASE] = pchar (tc->t_werasc); + t.c_cc[VSUSP] = pchar (tc->t_suspc); + if(t.c_cc[VSUSP] == _POSIX_VDISABLE) + t.c_cc[VSUSP] = pchar (tc->t_dsuspc); + t.c_cc[VREPRINT] = pchar (tc->t_rprntc); + t.c_cc[VDISCARD] = pchar (tc->t_flushc); + t.c_cc[VLNEXT] = pchar (tc->t_lnextc); + return (ioctl (fd, TCSETS, &t)); +} + +static int +tioclget (fd,lflagsp) +int fd; +int *lflagsp; +{ + struct termios t; + int lflags = 0; + + *lflagsp = lflags; + return 0; +} + +static int +tioclset (fd,lflagsp) +int fd; +int *lflagsp; +{ + return 0; +} + +static int +tiocflush (fd,arg) +int fd; +int *arg; +{ + return 0; +} + +int +bsd_ioctl (fd,option,arg) +int fd; +int option; +void *arg; +{ + switch (option) { + case TIOCGETP: + return gtty(fd, (struct sgttyb *) arg); + case TIOCSETP: + return stty(fd, (struct sgttyb *) arg); + case TIOCGETC: + return tiocgetc(fd, (struct tchars *) arg); + case TIOCSETC: + return tiocsetc(fd, (struct tchars *) arg); + case TIOCGLTC: + return tiocgltc(fd, (struct ltchars *) arg); + case TIOCSLTC: + return tiocsltc(fd, (struct ltchars *) arg); + case TIOCLGET: + return tioclget(fd, (int *) arg); + case TIOCLSET: + return tioclset(fd, (int *) arg); + case TIOCFLUSH: + return tiocflush(fd, (int *) arg); + case TIOCSETN: + return tiocsetn(fd, (struct sgttyb *) arg); + default: + return ioctl(fd, option, arg); + } +} + |