/* * Copyright (c) 1994 Scott Bartram * All rights reserved. * * based on compat/sunos/sun_ioctl.c * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG_IBCS2 #define DPRINTF(s) printf s #else #define DPRINTF(s) #endif /* * iBCS2 ioctl calls. */ static struct speedtab sptab[] = { { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 }, { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 }, { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 }, { 2400, 11 }, { 4800, 12 }, { 9600, 13 }, { 19200, 14 }, { 38400, 15 }, { -1, -1 } }; static u_long s2btab[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, }; static void stios2btios(st, bt) struct ibcs2_termios *st; struct termios *bt; { register u_long l, r; l = st->c_iflag; r = ((l & IBCS2_IGNBRK) ? IGNBRK : 0); r |= ((l & IBCS2_BRKINT) ? BRKINT : 0); r |= ((l & IBCS2_IGNPAR) ? IGNPAR : 0); r |= ((l & IBCS2_PARMRK) ? PARMRK : 0); r |= ((l & IBCS2_INPCK) ? INPCK : 0); r |= ((l & IBCS2_ISTRIP) ? ISTRIP : 0); r |= ((l & IBCS2_INLCR) ? INLCR : 0); r |= ((l & IBCS2_IGNCR) ? IGNCR : 0); r |= ((l & IBCS2_ICRNL) ? ICRNL : 0); r |= ((l & IBCS2_IXON) ? IXON : 0); r |= ((l & IBCS2_IXANY) ? IXANY : 0); r |= ((l & IBCS2_IXOFF) ? IXOFF : 0); r |= ((l & IBCS2_IMAXBEL) ? IMAXBEL : 0); bt->c_iflag = r; l = st->c_oflag; r = ((l & IBCS2_OPOST) ? OPOST : 0); r |= ((l & IBCS2_ONLCR) ? ONLCR : 0); r |= ((l & IBCS2_TAB3) ? OXTABS : 0); bt->c_oflag = r; l = st->c_cflag; r = ((l & IBCS2_CS6) ? CS6 : 0); r |= ((l & IBCS2_CS7) ? CS7 : 0); r |= ((l & IBCS2_CS8) ? CS8 : 0); r |= ((l & IBCS2_CSTOPB) ? CSTOPB : 0); r |= ((l & IBCS2_CREAD) ? CREAD : 0); r |= ((l & IBCS2_PARENB) ? PARENB : 0); r |= ((l & IBCS2_PARODD) ? PARODD : 0); r |= ((l & IBCS2_HUPCL) ? HUPCL : 0); r |= ((l & IBCS2_CLOCAL) ? CLOCAL : 0); bt->c_cflag = r; bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f]; l = st->c_lflag; r = ((l & IBCS2_ISIG) ? ISIG : 0); r |= ((l & IBCS2_ICANON) ? ICANON : 0); r |= ((l & IBCS2_ECHO) ? ECHO : 0); r |= ((l & IBCS2_ECHOE) ? ECHOE : 0); r |= ((l & IBCS2_ECHOK) ? ECHOK : 0); r |= ((l & IBCS2_ECHONL) ? ECHONL : 0); r |= ((l & IBCS2_NOFLSH) ? NOFLSH : 0); r |= ((l & IBCS2_TOSTOP) ? TOSTOP : 0); bt->c_lflag = r; bt->c_cc[VINTR] = st->c_cc[IBCS2_VINTR] ? st->c_cc[IBCS2_VINTR] : _POSIX_VDISABLE; bt->c_cc[VQUIT] = st->c_cc[IBCS2_VQUIT] ? st->c_cc[IBCS2_VQUIT] : _POSIX_VDISABLE; bt->c_cc[VERASE] = st->c_cc[IBCS2_VERASE] ? st->c_cc[IBCS2_VERASE] : _POSIX_VDISABLE; bt->c_cc[VKILL] = st->c_cc[IBCS2_VKILL] ? st->c_cc[IBCS2_VKILL] : _POSIX_VDISABLE; bt->c_cc[VEOF] = st->c_cc[IBCS2_VEOF] ? st->c_cc[IBCS2_VEOF] : _POSIX_VDISABLE; bt->c_cc[VEOL] = st->c_cc[IBCS2_VEOL] ? st->c_cc[IBCS2_VEOL] : _POSIX_VDISABLE; bt->c_cc[VEOL2] = st->c_cc[IBCS2_VEOL2] ? st->c_cc[IBCS2_VEOL2] : _POSIX_VDISABLE; #if 0 bt->c_cc[VSWTCH] = st->c_cc[IBCS2_VSWTCH] ? st->c_cc[IBCS2_VSWTCH] : _POSIX_VDISABLE; #endif bt->c_cc[VSTART] = st->c_cc[IBCS2_VSTART] ? st->c_cc[IBCS2_VSTART] : _POSIX_VDISABLE; bt->c_cc[VSTOP] = st->c_cc[IBCS2_VSTART] ? st->c_cc[IBCS2_VSTART] : _POSIX_VDISABLE; bt->c_cc[VSUSP] = st->c_cc[IBCS2_VSUSP] ? st->c_cc[IBCS2_VSUSP] : _POSIX_VDISABLE; bt->c_cc[VDSUSP] = _POSIX_VDISABLE; bt->c_cc[VREPRINT] = _POSIX_VDISABLE; bt->c_cc[VDISCARD] = _POSIX_VDISABLE; bt->c_cc[VWERASE] = _POSIX_VDISABLE; bt->c_cc[VLNEXT] = _POSIX_VDISABLE; bt->c_cc[VSTATUS] = _POSIX_VDISABLE; } static void btios2stios(bt, st) struct termios *bt; struct ibcs2_termios *st; { register u_long l, r; l = bt->c_iflag; r = ((l & IGNBRK) ? IBCS2_IGNBRK : 0); r |= ((l & BRKINT) ? IBCS2_BRKINT : 0); r |= ((l & IGNPAR) ? IBCS2_IGNPAR : 0); r |= ((l & PARMRK) ? IBCS2_PARMRK : 0); r |= ((l & INPCK) ? IBCS2_INPCK : 0); r |= ((l & ISTRIP) ? IBCS2_ISTRIP : 0); r |= ((l & INLCR) ? IBCS2_INLCR : 0); r |= ((l & IGNCR) ? IBCS2_IGNCR : 0); r |= ((l & ICRNL) ? IBCS2_ICRNL : 0); r |= ((l & IXON) ? IBCS2_IXON : 0); r |= ((l & IXANY) ? IBCS2_IXANY : 0); r |= ((l & IXOFF) ? IBCS2_IXOFF : 0); r |= ((l & IMAXBEL) ? IBCS2_IMAXBEL : 0); st->c_iflag = r; l = bt->c_oflag; r = ((l & OPOST) ? IBCS2_OPOST : 0); r |= ((l & ONLCR) ? IBCS2_ONLCR : 0); r |= ((l & OXTABS) ? IBCS2_TAB3 : 0); st->c_oflag = r; l = bt->c_cflag; r = ((l & CS6) ? IBCS2_CS6 : 0); r |= ((l & CS7) ? IBCS2_CS7 : 0); r |= ((l & CS8) ? IBCS2_CS8 : 0); r |= ((l & CSTOPB) ? IBCS2_CSTOPB : 0); r |= ((l & CREAD) ? IBCS2_CREAD : 0); r |= ((l & PARENB) ? IBCS2_PARENB : 0); r |= ((l & PARODD) ? IBCS2_PARODD : 0); r |= ((l & HUPCL) ? IBCS2_HUPCL : 0); r |= ((l & CLOCAL) ? IBCS2_CLOCAL : 0); st->c_cflag = r; l = bt->c_lflag; r = ((l & ISIG) ? IBCS2_ISIG : 0); r |= ((l & ICANON) ? IBCS2_ICANON : 0); r |= ((l & ECHO) ? IBCS2_ECHO : 0); r |= ((l & ECHOE) ? IBCS2_ECHOE : 0); r |= ((l & ECHOK) ? IBCS2_ECHOK : 0); r |= ((l & ECHONL) ? IBCS2_ECHONL : 0); r |= ((l & NOFLSH) ? IBCS2_NOFLSH : 0); r |= ((l & TOSTOP) ? IBCS2_TOSTOP : 0); st->c_lflag = r; l = ttspeedtab(bt->c_ospeed, sptab); if (l >= 0) st->c_cflag |= l; st->c_cc[IBCS2_VINTR] = bt->c_cc[VINTR] != _POSIX_VDISABLE ? bt->c_cc[VINTR] : 0; st->c_cc[IBCS2_VQUIT] = bt->c_cc[VQUIT] != _POSIX_VDISABLE ? bt->c_cc[VQUIT] : 0; st->c_cc[IBCS2_VERASE] = bt->c_cc[VERASE] != _POSIX_VDISABLE ? bt->c_cc[VERASE] : 0; st->c_cc[IBCS2_VKILL] = bt->c_cc[VKILL] != _POSIX_VDISABLE ? bt->c_cc[VKILL] : 0; st->c_cc[IBCS2_VEOF] = bt->c_cc[VEOF] != _POSIX_VDISABLE ? bt->c_cc[VEOF] : 0; st->c_cc[IBCS2_VEOL] = bt->c_cc[VEOL] != _POSIX_VDISABLE ? bt->c_cc[VEOL] : 0; st->c_cc[IBCS2_VEOL2] = bt->c_cc[VEOL2] != _POSIX_VDISABLE ? bt->c_cc[VEOL2] : 0; st->c_cc[IBCS2_VSWTCH] = 0; st->c_cc[IBCS2_VSUSP]= bt->c_cc[VSUSP] != _POSIX_VDISABLE ? bt->c_cc[VSUSP] : 0; st->c_cc[IBCS2_VSTART] = bt->c_cc[VSTART] != _POSIX_VDISABLE ? bt->c_cc[VSTART] : 0; st->c_cc[IBCS2_VSTOP] = bt->c_cc[VSTOP] != _POSIX_VDISABLE ? bt->c_cc[VSTOP] : 0; st->c_line = 0; } static void stios2stio(ts, t) struct ibcs2_termios *ts; struct ibcs2_termio *t; { t->c_iflag = ts->c_iflag; t->c_oflag = ts->c_oflag; t->c_cflag = ts->c_cflag; t->c_lflag = ts->c_lflag; t->c_line = ts->c_line; bcopy(ts->c_cc, t->c_cc, IBCS2_NCC); } static void stio2stios(t, ts) struct ibcs2_termio *t; struct ibcs2_termios *ts; { ts->c_iflag = t->c_iflag; ts->c_oflag = t->c_oflag; ts->c_cflag = t->c_cflag; ts->c_lflag = t->c_lflag; ts->c_line = t->c_line; bcopy(t->c_cc, ts->c_cc, IBCS2_NCC); } struct ibcs2_ioctl_args { int fd; int cmd; caddr_t data; }; int ibcs2_ioctl(p, uap, retval) register struct proc *p; register struct ibcs2_ioctl_args *uap; int *retval; { register struct filedesc *fdp = p->p_fd; register struct file *fp; register int (*ctl)(); int error; if ((unsigned)uap->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[uap->fd]) == NULL) { DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid, uap->fd)); return EBADF; } if ((fp->f_flag & (FREAD|FWRITE)) == 0) { DPRINTF(("ibcs2_ioctl(%d): bad fp flag ", p->p_pid)); return EBADF; } ctl = fp->f_ops->fo_ioctl; switch (uap->cmd) { case IBCS2_TCGETA: case IBCS2_XCGETA: case IBCS2_OXCGETA: { struct termios bts; struct ibcs2_termios sts; struct ibcs2_termio st; if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0) return error; btios2stios (&bts, &sts); if (uap->cmd == IBCS2_TCGETA) { stios2stio (&sts, &st); error = copyout((caddr_t)&st, uap->data, sizeof (st)); if (error) DPRINTF(("ibcs2_ioctl(%d): copyout failed ", p->p_pid)); return error; } else return copyout((caddr_t)&sts, uap->data, sizeof (sts)); /*NOTREACHED*/ } case IBCS2_TCSETA: case IBCS2_TCSETAW: case IBCS2_TCSETAF: { struct termios bts; struct ibcs2_termios sts; struct ibcs2_termio st; if ((error = copyin(uap->data, (caddr_t)&st, sizeof (st))) != 0) { DPRINTF(("ibcs2_ioctl(%d): TCSET copyin failed ", p->p_pid)); return error; } /* get full BSD termios so we don't lose information */ if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0) { DPRINTF(("ibcs2_ioctl(%d): TCSET ctl failed fd %d ", p->p_pid, uap->fd)); return error; } /* * convert to iBCS2 termios, copy in information from * termio, and convert back, then set new values. */ btios2stios(&bts, &sts); stio2stios(&st, &sts); stios2btios(&sts, &bts); return (*ctl)(fp, uap->cmd - IBCS2_TCSETA + TIOCSETA, (caddr_t)&bts, p); } case IBCS2_XCSETA: case IBCS2_XCSETAW: case IBCS2_XCSETAF: { struct termios bts; struct ibcs2_termios sts; if ((error = copyin(uap->data, (caddr_t)&sts, sizeof (sts))) != 0) { return error; } stios2btios (&sts, &bts); return (*ctl)(fp, uap->cmd - IBCS2_XCSETA + TIOCSETA, (caddr_t)&bts, p); } case IBCS2_OXCSETA: case IBCS2_OXCSETAW: case IBCS2_OXCSETAF: { struct termios bts; struct ibcs2_termios sts; if ((error = copyin(uap->data, (caddr_t)&sts, sizeof (sts))) != 0) { return error; } stios2btios (&sts, &bts); return (*ctl)(fp, uap->cmd - IBCS2_OXCSETA + TIOCSETA, (caddr_t)&bts, p); } case IBCS2_TCSBRK: DPRINTF(("ibcs2_ioctl(%d): TCSBRK ", p->p_pid)); return ENOSYS; case IBCS2_TCXONC: DPRINTF(("ibcs2_ioctl(%d): TCXONC ", p->p_pid)); return ENOSYS; case IBCS2_TCFLSH: DPRINTF(("ibcs2_ioctl(%d): TCFLSH ", p->p_pid)); return ENOSYS; case IBCS2_TIOCGWINSZ: DPRINTF(("ibcs2_ioctl(%d): TIOCGWINSZ ", p->p_pid)); return ENOSYS; case IBCS2_TIOCSWINSZ: DPRINTF(("ibcs2_ioctl(%d): TIOCSWINSZ ", p->p_pid)); return ENOSYS; case IBCS2_TIOCGPGRP: return copyout((caddr_t)&p->p_pgrp->pg_id, uap->data, sizeof(p->p_pgrp->pg_id)); case IBCS2_TIOCSPGRP: /* XXX - is uap->data a pointer to pgid? */ { struct setpgid_args { int pid; int pgid; } sa; sa.pid = 0; sa.pgid = (int)uap->data; if (error = setpgid(p, &sa, retval)) return error; return 0; } case IBCS2_TCGETSC: /* SCO console - get scancode flags */ return ENOSYS; case IBCS2_TCSETSC: /* SCO console - set scancode flags */ return ENOSYS; default: DPRINTF(("ibcs2_ioctl(%d): unknown cmd 0x%x ", p->p_pid, uap->cmd)); return ENOSYS; } return ENOSYS; }