diff options
Diffstat (limited to 'usr/src/lib/libbc/libc/sys/common/ioctl.c')
-rw-r--r-- | usr/src/lib/libbc/libc/sys/common/ioctl.c | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/usr/src/lib/libbc/libc/sys/common/ioctl.c b/usr/src/lib/libbc/libc/sys/common/ioctl.c new file mode 100644 index 0000000000..bfe677a3c1 --- /dev/null +++ b/usr/src/lib/libbc/libc/sys/common/ioctl.c @@ -0,0 +1,645 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 1995, by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Do not include sys/conf.h- it isn't in the compatibility include dirs. + */ +#ifdef THIS_IS_AVAIL +#include <sys/conf.h> +#endif +#include <stdio.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/ioccom.h> +#include <sys/stropts.h> +#include <sys/des.h> +#include <sys/fcntl.h> +#include <sys/filio.h> +#include <sys/termios.h> +#include <sys/termio.h> +#include <sys/ttold.h> +#include <sys/ttycom.h> +#include <sys/msio.h> +#include <sys/errno.h> +#include <nettli/tihdr.h> +#include <nettli/timod.h> +#include <nettli/tiuser.h> +#include <sun/dkio.h> +#include <scsi/impl/uscsi.h> +#include "cdioctl.h" +#include "s5dkio.h" +#include "s5fdio.h" + +/* + * parameter for windows ioctls + */ +struct winclip { + int wc_blockbytes; /* size of wc_block */ + int wc_clipid; /* Current clip id of clipping */ + short wc_screenrect[4]; /* Screen relatived (used when paint) */ + char *wc_block; /* Block where RectList is copied. */ +}; + +/* + * Ioctl control packet + */ +struct s5termios { + tcflag_t c_iflag; /* input modes */ + tcflag_t c_oflag; /* output modes */ + tcflag_t c_cflag; /* control modes */ + tcflag_t c_lflag; /* line discipline modes */ + cc_t c_cc[19]; /* control chars */ +}; + +#define N_ENOMSG 35 +#define N_I_FIND ('S'<<8)|013 +#define N_I_PUSH ('S'<<8)|02 +#define WINGETEXPOSEDRL _IOWR(g,31,struct winclip) +#define WINGETDAMAGEDRL _IOWR(g,32,struct winclip) + +struct n_sgttyb { + char sg_ispeed; /* input speed */ + char sg_ospeed; /* output speed */ + char sg_erase; /* erase character */ + char sg_kill; /* kill character */ + int sg_flags; /* mode flags */ +}; + +static int handle_dkio_partitions(int, int, int); +static int tcget(int, int, int); +static int tcset(int, int, int); +static int _bc_ioctl(int, int, int); + +int +ioctl(int des, int request, int arg) +{ + int ret; + + if ((ret = _bc_ioctl(des, request, arg)) == -1) + maperror(); + return (ret); +} + +int +bc_ioctl(int des, int request, int arg) +{ + int ret; + + if ((ret = _bc_ioctl(des, request, arg)) == -1) + maperror(); + return (ret); +} + +static int +_bc_ioctl(int des, int request, int arg) +{ + int ret; + int nreq = (request >> 8) & 0xFF; + struct n_sgttyb nsg; + struct s5_dk_cinfo newArgs; + struct dk_info *infoArgs; + struct dk_conf *confArgs; + extern int errno; + + /* not all mappings for 'm' have been performed */ + switch (nreq) { + case ((int) 't'): + if (_ioctl(des, N_I_FIND, "ttcompat") == 0) + if (_ioctl(des, N_I_PUSH, "ttcompat") == -1) + perror("ioctl/I_PUSH"); + switch(request) { + case TIOCSETD: + /* added for sunview */ + return(0); + case TIOCREMOTE: request = ('t'<<8)|30; + break; + case TIOCNOTTY: + bc_setsid(); + return(0); + case TIOCGPGRP: request = ('t'<<8)|20; + break; + case TIOCSPGRP: + { + pid_t pgid; + sigset_t set, oset; + + request = ('t'<<8)|21; + ret = _ioctl(des, request, arg); + + /* + * SunOS4.x allows this to succeed + * even if the process group does + * not exist yet. We emulate the 4.x + * bug by creating the process group + * and reissuing the ioctl(). + * See bugid 1175044. + */ + if (ret != 0 && errno == EPERM && + (pgid = *((pid_t *)arg)) != 0 && + pgid == getpid() && + setpgid(0, pgid) == 0) { + sigemptyset(&set); + sigaddset(&set, SIGTSTP); + sigaddset(&set, SIGTTIN); + sigaddset(&set, SIGTTOU); + sigprocmask(SIG_BLOCK, + &set, &oset); + ret = _ioctl(des, + request, arg); + sigprocmask(SIG_SETMASK, + &oset, NULL); + } + return(ret); + } + case TIOCSTI: request = ('t'<<8)|23; + break; + case TIOCSIGNAL: request = ('t'<<8)|31; + break; + case TIOCCONS: request = ('t'<<8)|36; + break; + case TIOCSWINSZ: request = ('T'<<8)|103; + break; + case TIOCGWINSZ: request = ('T'<<8)|104; + break; + case TIOCSETP: + case TIOCSETN: + { + struct sgttyb *sg = (struct sgttyb *)arg; + nsg.sg_ispeed = sg->sg_ispeed; + nsg.sg_ospeed = sg->sg_ospeed; + nsg.sg_erase = sg->sg_erase; + nsg.sg_kill = sg->sg_kill; + nsg.sg_flags = (int)sg->sg_flags; + arg = (int)&nsg; + request = request & 0x0FFFF; + break; + } + + case TIOCGETP: + { + struct sgttyb *sg = (struct sgttyb *)arg; + + ret = _ioctl(des, request&0xFFFF, &nsg); + if (ret != -1) { + sg->sg_ispeed = nsg.sg_ispeed; + sg->sg_ospeed = nsg.sg_ospeed; + sg->sg_erase = nsg.sg_erase; + sg->sg_kill = nsg.sg_kill; + sg->sg_flags = (short)nsg.sg_flags & 0x0FFFF; + } + return(ret); + } + case TIOCPKT: + case TIOCUCNTL: + case TIOCTCNTL: + case TIOCSSOFTCAR: + case TIOCGSOFTCAR: + case TIOCISPACE: + case TIOCISIZE: + case TIOCSSIZE: + case TIOCGSIZE: + break; + default: request = request & 0x0FFFF; + break; + } + break; + case ((int) 'T'): + switch(request) { + case TCGETS: + request = ('T'<<8)|13; + return(tcget(des, request, arg)); + break; + case TCSETS: + request = ('T'<<8)|14; + return(tcset(des, request, arg)); + break; + case TCSETSW: + request = ('T'<<8)|15; + return(tcset(des, request, arg)); + break; + case TCSETSF: + request = ('T'<<8)|16; + return(tcset(des, request, arg)); + break; + case TCGETA: + case TCSETA: + case TCSETAW: + case TCSETAF: + default: + request = request & 0x0FFFF; + break; + } + break; + case ((int) 'S'): + switch (request) { + case I_PLINK: request = ('S'<<8)|026; + break; + case I_PUNLINK: request = ('S'<<8)|027; + break; + case I_STR: { + struct strioctl *iarg = + (struct strioctl *)arg; + int cmd = iarg->ic_cmd; + + switch (cmd) { + case TI_GETINFO: { + /* + * The T_info_ack structure + * has one additional word + * added to it in 5.x. + * To prevent the module from + * overwritting user memory we + * use an internal buffer for + * the transfer and copy out + * the results to the caller. + */ + struct { + struct T_info_ack info; + long pad[16]; + } args; + char *dp = iarg->ic_dp; + + memcpy(&args.info, iarg->ic_dp, + sizeof(struct T_info_ack)); + iarg->ic_dp = + (char *) &args.info; + iarg->ic_cmd = (TIMOD | 140); + ret = _ioctl(des, + request & 0xffff, arg); + iarg->ic_cmd = cmd; + iarg->ic_dp = dp; + iarg->ic_len = + sizeof(struct T_info_ack); + memcpy(iarg->ic_dp, &args.info, + iarg->ic_len); + return (ret); + break; + } + case TI_OPTMGMT: + iarg->ic_cmd = (TIMOD | 141); + break; + case TI_BIND: + iarg->ic_cmd = (TIMOD | 142); + break; + case TI_UNBIND: + iarg->ic_cmd = (TIMOD | 143); + break; + } + ret = _ioctl(des, + request & 0xffff, arg); + iarg->ic_cmd = cmd; + return ret; + } + default: request = request & 0x0FFFF; + break; + } + break; + case ((int) 'm'): + switch (request) { + case MSIOGETPARMS: request = ('m'<<8)|1; + break; + case MSIOSETPARMS: request = ('m'<<8)|2; + break; + default: request = request & 0x0FFFF; + break; + } + break; + case ((int) 'd'): + switch (request) { + case DKIOCGGEOM: + request = S5DKIOCGGEOM; + break; + case DKIOCSGEOM: + request = S5DKIOCSGEOM; + break; + case DKIOCSAPART: + request = S5DKIOCSAPART; + break; + case DKIOCGAPART: + request = S5DKIOCGAPART; + break; + case DKIOCSTYPE: + request = S5HDKIOCSTYPE; + break; + case DKIOCGTYPE: + request = S5HDKIOCGTYPE; + break; + case DKIOCSBAD: + request = S5HDKIOCSBAD; + break; + case DKIOCGBAD: + request = S5HDKIOCGBAD; + break; + case DKIOCSCMD: + request = S5HDKIOCSCMD; + break; + case DKIOCGDIAG: + request = S5HDKIOCGDIAG; + break; + case FDKIOGCHAR: + request = S5FDIOGCHAR; + break; + case FDKIOSCHAR: + request = S5FDIOSCHAR; + break; + case FDKEJECT: + request = S5FDEJECT; + break; + case FDKGETCHANGE: + request = S5FDGETCHANGE; + break; + case FDKGETDRIVECHAR: + request = S5FDGETDRIVECHAR; + break; + case FDKSETDRIVECHAR: + request = S5FDSETDRIVECHAR; + break; + case FDKGETSEARCH: + request = S5FDGETSEARCH; + break; + case FDKSETSEARCH: + request = S5FDSETSEARCH; + break; + case FDKIOCSCMD: + request = S5FDIOCMD; + break; + case F_RAW: + request = S5FDRAW; + break; + case DKIOCINFO: + ret = _ioctl(des, S5DKIOCINFO, &newArgs); + if (ret != -1) { + infoArgs = (struct dk_info *)arg; + infoArgs->dki_ctlr = + newArgs.dki_addr; + infoArgs->dki_unit = + newArgs.dki_unit; + infoArgs->dki_ctype = + newArgs.dki_ctype; + infoArgs->dki_flags = + newArgs.dki_flags; + } + return ret; + break; + case DKIOCGCONF: + ret = _ioctl(des, S5DKIOCINFO, &newArgs); + if (ret != -1) { + confArgs = (struct dk_conf *)arg; + strncpy(confArgs->dkc_cname, + newArgs.dki_cname, + DK_DEVLEN); + strncpy(confArgs->dkc_dname, + newArgs.dki_dname, + DK_DEVLEN); + confArgs->dkc_ctype = + (u_short)newArgs.dki_ctype; + confArgs->dkc_flags = + (u_short)newArgs.dki_flags; + confArgs->dkc_cnum = + newArgs.dki_cnum; + confArgs->dkc_addr = + newArgs.dki_addr; + confArgs->dkc_space = + (u_int)newArgs.dki_space; + confArgs->dkc_prio = + newArgs.dki_prio; + confArgs->dkc_vec = + newArgs.dki_vec; + confArgs->dkc_unit = + newArgs.dki_unit; + confArgs->dkc_slave = + newArgs.dki_slave; + } + return ret; + break; + case DKIOCWCHK: + /* + * This is unsupported in SVR4. It + * turns on verify-after-write for + * the floppy. I don't think the + * system call should fail, however. + */ + return 0; + break; + case DKIOCGPART: + case DKIOCSPART: + return (handle_dkio_partitions(des, + request, arg)); + case DKIOCGLOG: + /* unsupported */ + errno = EINVAL; + return -1; + break; + case DESIOCBLOCK: + case DESIOCQUICK: + break; /* no change for these two */ + default: + request = request & 0x0FFFF; /* try */ + break; + } + break; + case ((int) 'c'): + switch (request) { + case CDROMPAUSE: + request = S5CDROMPAUSE; + break; + case CDROMRESUME: + request = S5CDROMRESUME; + break; + case CDROMPLAYMSF: + request = S5CDROMPLAYMSF; + break; + case CDROMPLAYTRKIND: + request = S5CDROMPLAYTRKIND; + break; + case CDROMREADTOCHDR: + request = S5CDROMREADTOCHDR; + break; + case CDROMREADTOCENTRY: + request = S5CDROMREADTOCENTRY; + break; + case CDROMSTOP: + request = S5CDROMSTOP; + break; + case CDROMSTART: + request = S5CDROMSTART; + break; + case CDROMEJECT: + request = S5CDROMEJECT; + break; + case CDROMVOLCTRL: + request = S5CDROMVOLCTRL; + break; + case CDROMSUBCHNL: + request = S5CDROMSUBCHNL; + break; + case CDROMREADMODE1: + request = S5CDROMREADMODE1; + break; + case CDROMREADMODE2: + request = S5CDROMREADMODE2; + break; + } + break; + case ((int) 'u'): + switch (request) { + case USCSICMD: + { + struct s5_uscsi_cmd s5_cmd; + struct uscsi_cmd *cmd = + (struct uscsi_cmd *) arg; + request = S5USCSICMD; + s5_cmd.uscsi_cdb = cmd->uscsi_cdb; + s5_cmd.uscsi_cdblen = + cmd->uscsi_cdblen; + s5_cmd.uscsi_bufaddr = + cmd->uscsi_bufaddr; + s5_cmd.uscsi_buflen = + cmd->uscsi_buflen; + s5_cmd.uscsi_flags = + cmd->uscsi_flags; + ret = _ioctl(des, request, &s5_cmd); + cmd->uscsi_status = s5_cmd.uscsi_status; + return(ret); + } + } + break; + case ((int) 'k'): + case ((int) 'v'): + case ((int) 'F'): + case ((int) 'G'): + case ((int) 'X'): + case ((int) 'L'): + request = request & 0x0FFFF; + break; + case ((int) 'f'): + if ((request == FIOCLEX) || (request == FIONCLEX)) + return(fcntl(des, F_SETFD, + ((request == FIOCLEX) ? 1 : 0))); + break; + case ((int) 'g'): + /* Treat the following 2 ioctls specially for + * sunview. */ + if (request == WINGETEXPOSEDRL || + request == WINGETDAMAGEDRL) { + ret = _ioctl(des, request, arg); + if (errno == N_ENOMSG) + errno = EFBIG; + return(ret); + } + break; + } + return (_ioctl(des, request, arg)); +} + + +static int +handle_dkio_partitions(int des, int request, int arg) +{ + struct s5_dk_cinfo cinfo; + struct dk_allmap map; + struct dk_map *part; + int ret; + extern int errno; + + part = (struct dk_map *) arg; + + ret = _ioctl(des, S5DKIOCINFO, &cinfo); + + if ((cinfo.dki_partition < 0) || (cinfo.dki_partition >= NDKMAP)) { + errno = EINVAL; + return (-1); + } + + if (ret != -1) { + ret = _ioctl(des, S5DKIOCGAPART, &map); + if (ret != -1) { + if (request == DKIOCGPART) { + part->dkl_cylno = + map.dka_map[cinfo.dki_partition].dkl_cylno; + part->dkl_nblk = + map.dka_map[cinfo.dki_partition].dkl_nblk; + } else { + map.dka_map[cinfo.dki_partition].dkl_cylno = + part->dkl_cylno; + map.dka_map[cinfo.dki_partition].dkl_nblk = + part->dkl_nblk; + ret = _ioctl(des, S5DKIOCSAPART, &map); + } + } + } + return (ret); +} + +static int +tcset(des, request, arg) + register int des; + register int request; + int arg; +{ + struct s5termios s5termios; + struct termios *termios; + + termios = (struct termios *)arg; + + if (termios != NULL) { + s5termios.c_iflag = termios->c_iflag; + s5termios.c_oflag = termios->c_oflag; + s5termios.c_cflag = termios->c_cflag; + s5termios.c_lflag = termios->c_lflag; + memcpy(s5termios.c_cc, termios->c_cc, NCCS); + return (_ioctl(des, request, &s5termios)); + } else + return (_ioctl(des, request, NULL)); + +} + +static int +tcget(des, request, arg) + register int des; + register int request; + int arg; +{ + struct s5termios s5termios; + struct termios *termios; + int ret; + + termios = (struct termios *)arg; + + ret = _ioctl(des, request, &s5termios); + + if (termios != NULL) { + termios->c_iflag = s5termios.c_iflag; + termios->c_oflag = s5termios.c_oflag; + termios->c_cflag = s5termios.c_cflag; + termios->c_lflag = s5termios.c_lflag; + memcpy(termios->c_cc, s5termios.c_cc, NCCS); + } + + return (ret); +} |