451 lines
12 KiB
C
451 lines
12 KiB
C
/*
|
|
* 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 <sys/param.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/file.h>
|
|
#include <sys/filedesc.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/termios.h>
|
|
#include <sys/tty.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/ioctl.h>
|
|
#include <net/if.h>
|
|
|
|
#include <compat/ibcs2/ibcs2_types.h>
|
|
#include <compat/ibcs2/ibcs2_termios.h>
|
|
|
|
#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;
|
|
}
|
|
|