home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
LIB
/
unix.zoo
/
ioctl.c
< prev
next >
Wrap
Text File
|
2009-11-06
|
18KB
|
508 lines
/***************************************************************************/
/* */
/* ioctl() : Unix library (OS9/68000) */
/* ======= */
/* */
/* Author: K. Schmitt */
/* Compiler: Microware C Vers. 3.0 */
/* OS: OS9/68000 Vers. 2.2 */
/* */
/* Edition History */
/* =============== */
/* */
/* Ed. 0.00 Date 11/11/88 */
/* First version */
/* */
/***************************************************************************/
/* */
/* Description */
/*
NAME
ioctl - control device
SYNOPSIS
#include <UNIX/ioctl.h>
ioctl (fildes, request, arg)
int fildes, request;
DESCRIPTION
Ioctl performs a variety of functions on character special
files (devices).
Ioctl will fail if one or more of the following are true:
[EBADF] Fildes is not a valid open file descriptor.
[ENOTTY] Fildes is not associated with a character
special device.
[EINVAL] Request or arg is not valid.
[EINTR] A signal was caught during the ioctl system
call.
RETURN VALUE
If an error has occurred, a value of -1 is returned and
errno is set to indicate the error.
*/
#include <stdio.h>
#include <UNIX/errno.h>
#include <UNIX/ioctl.h>
#include <UNIX/termio.h>
#include <sgstat.h>
# ifndef TRUE
#define TRUE 1
#define FALSE 0
#define ERROR -1
# endif
typedef unsigned char FLAG;
extern int errno;
extern struct sgbuf _tty_opt_; /* defined in 'isatty()' */
/* external functions */
extern int fclose(), close(), open(), munlink(), tsleep(), _gs_opt(), _ss_opt();
extern int fflush(), _gs_devn(), _gs_rdy(), isatty();
extern FILE *fopen();
extern char *modlink();
int ioctl (fildes, request, arg)
register int fildes;
int request;
struct termio *arg; /* CAUTION: in some calls 'arg' is of type int */
{
register struct sgbuf *tty_options;
register int i;
register long *l;
if (i=isatty(fildes)) /* is 'fildes' a tty path ? */
{
if (i == ERROR) return (EBADF); /* bad fildes */
}
else
{
return (ENOTTY); /* no tty fildes */
}
tty_options = &_tty_opt_;
switch (request)
{
/****************************/
/* 'arg' is of type 'int' */
/****************************/
case TIOCFLUSH:
case TCFLSH: /* if arg is 0, flush the input queue, if 1, */
/* flush the output queue, if 2, flush both */
i = (int) arg;
if ((i < 0) || (i > 2)) return (EINVAL);
/* buffered file ? If not => return */
if ((_iob[fildes]._flag & _INIT) &&
(_iob[fildes]._fd == fildes))
{
fflush((FILE *) &_iob[fildes]);
}
break;
case TCSBRK: /* wait for the output to drain. If arg is 0,*/
/* then send a break (zero bits for 0.25 sec */
tsleep(10); /* nothing to do (no I$ call) */
break;
case TCXONC: /* start/stop control. If arg is 0, suspend */
/* output; if arg is 1, restart suspended */
/* output */
break; /* nothing to do */
/************************************/
/* 'arg' is of type 'struct termio' */
/************************************/
case TCGETA: /* get the parameters associated with the */
/* terminal and store in the termio structure*/
/* referenced by arg */
arg->c_iflag = 0;
arg->c_oflag = (tty_options->sg_case ?
OLCUC : 0) |
(tty_options->sg_alf ?
ONLCR : 0);
arg->c_cflag = get_baud(tty_options->sg_baud) |
get_csize(tty_options->sg_parity) |
get_stopb(tty_options->sg_parity) |
get_parity(tty_options->sg_parity);
arg->c_lflag = get_echo(tty_options);
arg->c_cc[VINTR] = tty_options->sg_kbich;
arg->c_cc[VQUIT] = tty_options->sg_kbach;
arg->c_cc[VERASE] = tty_options->sg_bspch;
arg->c_cc[VKILL] = tty_options->sg_dlnch;
arg->c_cc[VEOF] = tty_options->sg_eofch;
arg->c_cc[VEOL] = tty_options->sg_eorch;
arg->c_cc[VSUSP] = tty_options->sg_pause;
break;
case TCSETA: /* Set the parameters associated with the */
/* terminal from the structure arg */
tty_options->sg_echo = (arg->c_lflag & ECHO)
? TRUE : FALSE;
tty_options->sg_backsp = (arg->c_lflag & ECHOE)
? TRUE : FALSE;
tty_options->sg_case = (arg->c_iflag & IUCLC)
? 1 : 0;
tty_options->sg_kbich = arg->c_cc[VINTR];
tty_options->sg_kbach = arg->c_cc[VQUIT];
tty_options->sg_bspch = arg->c_cc[VERASE];
tty_options->sg_dlnch = arg->c_cc[VKILL];
tty_options->sg_eofch = arg->c_cc[VEOF];
tty_options->sg_eorch = arg->c_cc[VEOL];
tty_options->sg_pause = arg->c_cc[VSUSP];
if (set_mode_bits(arg->c_cflag))
{
/* baud rate, character size, parity...
* have changed!! We have NO function
* calls to change one of the above
* on an open path under OS9.
* So we must
* a) close the path
* b) modify the device descriptor
* c) re-open the device
*/
if (change_device_mode(fildes))
{
/* something failed!!! */
return (ERROR);
}
}
/* set the new terminal mode */
if (_ss_opt(fildes,tty_options) == ERROR)
{
return (ERROR);
}
break;
/****************************/
/* 'arg' is of type 'long' */
/****************************/
case FIONREAD:/* get # of bytes in the read buffer */
l = (long *) arg;
if ((i=_gs_rdy(fildes)) == ERROR)
{
errno = 0;
*l = 0L;
}
else
{
*l = (long) i;
}
break;
default: /* invalid request */
#ifdef DEBUG
fprintf(stderr,
"\nioctl: invalid request (%d)\n",
request);
#endif
return (EINVAL);
} /* end switch (request) */
return (0);
} /* end of ioctl */
#ifdef STATIC
static
#endif
int get_baud(rate)
int rate;
{
register int baudrate;
switch (rate & 0xFF)
{
case 0: baudrate = B50;
break;
case 1: baudrate = B75;
break;
case 2: baudrate = B110;
break;
case 3: baudrate = B134;
break;
case 4: baudrate = B150;
break;
case 5: baudrate = B300;
break;
case 6: baudrate = B600;
break;
case 7: baudrate = B1200;
break;
case 8: baudrate = B1800;
break;
case 10: baudrate = B2400;
break;
case 12: baudrate = B4800;
break;
case 14: baudrate = B9600;
break;
case 15: baudrate = B19200;
break;
case 256: baudrate = EXTB;
break;
default: baudrate = B0;
}
return (baudrate);
} /* end of get_baud */
#ifdef STATIC
static
#endif
int get_csize(size)
int size;
{
register int csize;
switch ((size >> 2) & 0x03)
{
case 0: csize = CS8;
break;
case 1: csize = CS7;
break;
case 2: csize = CS6;
break;
case 3: csize = CS5;
}
return (csize);
} /* end of get_csize */
#ifdef STATIC
static
#endif
int get_stopb(stopbits)
register int stopbits;
{
if (((stopbits >> 4) & 0x03) == 2) stopbits = CSTOPB;
else stopbits = 0;
return (stopbits);
} /* end of get_stopb */
#ifdef STATIC
static
#endif
int get_parity(parity)
register int parity;
{
switch (parity & 3)
{
case 2:
case 0: parity = 0; /* no parity */
break;
case 1: parity = PARENB | PARODD;
break;
case 3: parity = PARENB;
}
return (parity);
} /* end of get_parity */
#ifdef STATIC
static
#endif
int get_echo(options)
register struct sgbuf *options;
{
register int echo = 0;
if (options->sg_echo) echo = ECHO; /* echo input */
if (options->sg_backsp) echo |= ECHOE; /* echo BS-SP-BS */
return (echo);
} /* end of get_echo */
#ifdef STATIC
static
#endif
int set_mode_bits(mode)
unsigned short mode;
{
register FLAG modified = FALSE;
register int old_value, i;
register struct sgbuf *tty_options;
tty_options = &_tty_opt_;
old_value = (int) tty_options->sg_baud;
tty_options->sg_baud = 0;
switch ((int) (mode & CBAUD))
{
case B50: i = 0;
break;
case B75: i = 1;
break;
case B110: i = 2;
break;
case B134: i = 3;
break;
case B150: i = 4;
break;
case B300: i = 5;
break;
case B600: i = 6;
break;
case B1200: i = 7;
break;
case B1800: i = 8;
break;
case B2400: i = 10;
break;
case B4800: i = 12;
break;
default:
case B9600: i = 14;
break;
case B19200: i = 15;
break;
case EXTB: i = 0xFF;
}
tty_options->sg_baud = i;
if (i != old_value) modified = TRUE;
/* get character size */
old_value = (int) (tty_options->sg_parity & 0x3F);
i = (int) (mode & (CS8|CS7|CS6));
if (i == CS8) i = 0x00;
else if (i == CS7) i = 0x04;
else if (i == CS6) i = 0x08;
else if (i == CS5) i = 0x0C;
else i = 0x00;
tty_options->sg_parity = i;
/* get stop bits */
if (mode & CSTOPB) tty_options->sg_parity |= 0x20;
/* get parity */
i = (int) (mode & (PARENB|PARODD));
if (i == (PARENB|PARODD)) i = 0x01; /* odd parity */
else if (i == PARENB) i = 0x03; /* even parity */
else i = 0x00; /* no parity */
tty_options->sg_parity |= i;
if ((int) tty_options->sg_parity != old_value) modified = TRUE;
return (modified);
} /* end of set_mode_bits */
#ifdef STATIC
static
#endif
int change_device_mode(fildes)
int fildes;
{
char device_name[34];
register int i;
register FLAG buffered = FALSE;
register struct sgbuf *tty_options;
register char *module;
if (_gs_devn(fildes,&device_name[1]) == ERROR) return (ERROR);
if (_iob[fildes]._flag & _INIT)
{
buffered = TRUE;
if (fclose((FILE *) &_iob[fildes]) == ERROR) return (ERROR);
}
else
{
if (close(fildes) == ERROR) return (ERROR);
}
/* link the device descriptor */
if ((module=modlink(&device_name[1],0)) == (char *) ERROR)
return (ERROR);
tty_options = &_tty_opt_;
*(module+0x5C) = tty_options->sg_parity;
*(module+0x5D) = tty_options->sg_baud;
munlink(module);
device_name[0] = '/';
if (buffered)
{
FILE *files[_NFILE];
FILE *f;
for (i=0 ; i < _NFILE ; i++) files[i] = (FILE *) 0;
i = 0;
do
{
if ((f = fopen(device_name,"w+")) == (FILE *) 0)
return (ERROR);
if (fileno(f) == fildes) break;
files[fileno(f)] = f;
i++;
} while (i < _NFILE) ;
for (i=0 ; i < _NFILE ; i++)
{
if (files[i])
{
if (fclose(files[i]) == ERROR) return (ERROR);
}
}
}
else
{ /* unbuffered */
int files[_NFILE];
int f;
for (i=0 ; i < _NFILE ; i++) files[i] = -1;
i = 0;
do
{
if ((f = open(device_name,_READ|_WRITE)) == ERROR)
return (ERROR);
if (f == fildes) break;
files[f] = f;
i++;
} while (i < _NFILE) ;
for (i=0 ; i < _NFILE ; i++)
{
if (files[i] != -1)
{
if (close(files[i]) == ERROR) return (ERROR);
}
}
}
return (0);
} /* end of change_device_mode */