summaryrefslogtreecommitdiff
path: root/usr/src/lib/libbc/libc/sys/common/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libbc/libc/sys/common/ioctl.c')
-rw-r--r--usr/src/lib/libbc/libc/sys/common/ioctl.c645
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);
+}