From:	CSBVAX::CSBVAX::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  9-NOV-1988 04:34
To:	MRGATE::"ARISIA::EVERHART"
Subj:	VAXCIO (VAXCIO.SHAR2_OF_5) Source.


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Tue,  8 NOV 88 19:25:56 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Tue, 8 Nov 88 19:18:28 PST
Received: by ucbvax.Berkeley.EDU (5.59/1.31)
	id AA07454; Mon, 7 Nov 88 23:26:10 PST
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 7 Nov 88 19:00:36 GMT
From: tektronix!gvgpsa!gvgpvd!tony@ucbvax.Berkeley.EDU  (Tony Ivanov)
Organization: Grass Valley Group, Inc., Grass Valley, CA
Subject: VAXCIO (VAXCIO.SHAR2_OF_5) Source.
Message-Id: <889@gvgpvd.GVG.TEK.COM>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

------------------ cut here -----------------
$Part2:
$ File_is="IOCTL.C"
$ Check_Sum_is=392536630
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X *`009This is the VMS implementation of unix's ioctl.  For simplicity purposes
X *`009and because I don't want to write a complete terminal driver, I will let
X *`009the VMS terminal driver do as much as possible.  Because of this, some
V *`009ioctl functionality will be lost.  The following list shows what is curre
Xntly
X *`009implemented.  Those preceded by an asterisk (*) need special VMS I/O
X *`009processing.
X *`009`009The following input control flags are recognized:
X *`009`009    *`009BRKINT`009- implemented to flag cbreak (crmode) condition.
V *`009`009`009ISTRIP`009- implemented to flag "EIGHTBIT" VMS terminal character
Xistic.
X *`009`009    *`009INLCR`009- implemented.
X *`009`009`009ICRNL`009- implemented.
X *`009`009    *`009IUCLC`009- implemented.
V *`009`009`009IXON`009- implemented to flag "TTSYNC" VMS terminal characteristi
Xc.
V *`009`009`009IXOFF`009- implemented to flag "HOSTSYNC" VMS terminal characteri
Xstic.
X *`009`009The following output control flags are recognized:
X *`009`009`009OPOST`009- implemented to flag raw condition.
X *`009`009    *`009OLCUC`009- implemented.
X *`009`009`009ONLCR`009- implemented.
X *`009`009    *`009OCRNL`009- implemented.
V *`009`009`009TAB3`009- implemented to flag "TAB" expansion VMS terminal charac
Xteristic.
X *`009`009The following hardware control flags are recognized:
V *`009`009`009CBAUD`009- implemented for all baud information common to unix an
Xd VMS.
V *`009`009`009HUPCL`009- implemented to flag "HANGUP" VMS terminal characterist
Xic.
V *`009`009`009CLOCAL`009- implemented to flag "MODEM" VMS terminal characterist
Xic.
X *`009`009The following line-discipline control flags are recognized:
X *`009`009`009ECHO`009- implemented to flag "ECHO" VMS terminal characteristic.
X */
X
X# include`009<descrip.h>
X# include`009<dcdef.h>
X# include`009<dvidef.h>
X# include`009<errno.h>
X# include`009<iodef.h>
X# include`009<setjmp.h>
X# include`009<signal.h>
X# include`009<ssdef.h>
X# include`009"sys_struct.h"
X# include`009<ttdef.h>
X# include`009<tt2def.h>
X# include`009"vmstermio.h"`009/* Only structures defined. */
X# define`009bool`009char
X# define`009reg`009register
X
X
X/*`009Primary data structures used to control VMS termio functions. */
Vglobaldef noshare struct vms_term_data`009*vms_term_data_head = 0;`009/* Head o
Xf vms terminal data list. */
Vglobaldef noshare struct vms_term_data`009def1_vms_term_data;`009`009/* Default
X terminal data list for fd 1. */
Vglobaldef noshare struct vms_term_data`009def2_vms_term_data;`009`009/* Default
X terminal data list for fd 2. */
Vglobalref         struct _iobuf`009`009**IO_POINTER;`009`009`009/* VAX C pointe
Xr to I/O buffers. */
X
X/*`009Secondary data structures used with vmstermio. */
Vglobaldef noshare struct termio `009_tty = {0, 0, 0, 0, 0, {0x03, 0, 0x7f, 0x14
X, 0x1a, 0, 0, 0}};
Vglobaldef noshare struct termio`009`009_res_tty;`009/* used to save terminal se
Xttings for restoration. */
Xglobaldef noshare int`009`009`009_tty_ch = 1;
X
V/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
X~~~~~~~~~~~~~~~
X *
V *`009The following definitions, data structures and procedures specifically de
Xal with
X *`009implementing the ioctl routine.
X *
X */
X`009/* Forward references. */
Vextern void`009`009`009ioctl_return();`009`009/* Routine for force exit from io
Xctl function. */
Vextern void`009`009`009sighandler();`009`009/* Function for handling any signal
X during ioctl. */
Vextern void`009`009`009sigcatchall();`009`009/* Function to set up signal handl
Xer for all signals. */
Vextern void`009`009`009sigresetall();`009`009/* Function to revert signal handl
Xers to previous ones. */
Vextern struct vms_term_data`009*get_vms_term_data();`009/* Function to link a f
Xildes to a vms term data block. */
Vextern struct vms_term_data`009*new_vms_term_data();`009/* Function to create a
X new vms terminal data block. */
Vextern unsigned short`009`009connect();`009`009/* Connect a channel to a file. 
X*/
Vextern bool`009`009`009vms_TCGETA();`009`009/* Function to get current terminal
X characteristics. */
Vextern bool`009`009`009vms_TCSETA();`009`009/* Function to set terminal charact
Xeristics. */
Vextern bool`009`009`009vms_TCSBRK();`009`009/* Function to wait for output to f
Xlush. */
Vextern bool`009`009`009vms_TCXONC();`009`009/* Function to control XON/XOFF pro
Xtocol. */
Vextern bool`009`009`009vms_TCFLSH();`009`009/* Function to flush input/output q
Xueues. */
X
X`009/* Signal processing stuff. */
Vjmp_buf`009`009ioctl_return_vector;`009/* Environment for setjmp/longjmp return
X vector. */
Xbool`009`009signal_blocked;`009`009/* TRUE if signals have been blocked. */
Vunsigned int`009signal_mask;`009`009/* Mask of signals that should be re-establ
Xished if signals are blocked. */
X/*
X *`009Entry points for signal processing routines for various signals.
X */
Xint`009`009*hup_entry, *int_entry, *quit_entry, *ill_entry, *trap_entry,
X`009`009*iot_entry, *emt_entry, *fpe_entry, *kill_entry, *bus_entry,
X`009`009*segv_entry, *sys_entry, *pipe_entry, *alrm_entry, *term_entry;
X
X
Xint
Xioctl (fildes, request, arg)
X`009int`009fildes;
X`009int`009request;
X{
V#define`009`009arg_struc`009((struct termio *) arg)`009`009/* When arg is used 
Xas a termio structure. */
V#define`009`009arg_int`009`009((int) arg)`009`009`009/* When arg is simply an i
Xnteger. */
V`009struct vms_term_data`009*index;`009`009`009`009/* Index into VMS terminal d
Xata block. */
X`009int`009`009`009return_val;`009`009`009/* Return value for "setjmp":
X`009`009`009`009`009`009`009`009      0 - initialization of return vector.
X`009`009`009`009`009`009`009`009      1 - Return with "success" status.
X`009`009`009`009`009`009`009`009     -1 - Return with "failure" status. */
X
X`009`009/* Set up ioctl common return vector. */
X`009if ((return_val = setjmp (ioctl_return_vector)) == 1)
X`009`009return (0);
X`009else if (return_val == -1)
X`009`009return (-1);
X
X`009`009/* Catch all signals */
X`009sigcatchall ();
X
X`009`009/* Make sure file for which ioctl is called is a terminal. */
X`009if (!isatty(fildes))
X`009`009ioctl_return ((errno == ENOTTY) ? 0 : errno);
X/*`009`009ioctl_return (ENOTTY); */
X
X`009`009/* Establish the proper vms control block. */
X`009if (!(index = get_vms_term_data (fildes)))
X`009`009ioctl_return (-1);
X
V`009`009/* Connect the I/O buffer and make this an active data block if it isn'
Xt already. */
X`009if (!index->_iobuf)
V`009`009index->_iobuf = IO_POINTER[fildes+1];`009/* This is the VAX C I/O buffe
Xr stuff. */
X`009index->active = TRUE;
X
X`009`009/* Process the request. */
X`009switch (request)
X`009{`009case TCGETA:
X`009`009`009if (arg < 0x200) ioctl_return (EINVAL);
V `009`009`009if (!vms_TCGETA (index, arg_struc)) ioctl_return (-1);`009/* Load 
Xparameters into arg. */
X`009`009`009break;
X`009`009case TCSETA:
X`009`009`009if (arg < 0x200) ioctl_return (EINVAL);
V`009`009`009if (!vms_TCSETA (index, arg_struc)) ioctl_return (-1);`009/* Set pa
Xrameters from arg. */
X`009`009`009break;
X`009`009case TCSETAW:
X`009`009`009if (arg < 0x200) ioctl_return (EINVAL);
V`009`009`009if (!vms_TCSBRK (index)) ioctl_return (-1);`009`009/* Wait for outp
Xut drain. */
V`009`009`009if (!vms_TCSETA (index, arg_struc)) ioctl_return (-1);`009/* Set pa
Xrameters from arg. */
X`009`009`009break;
X`009`009case TCSETAF:
X`009`009`009if (arg < 0x200) ioctl_return (EINVAL);
V`009`009`009if (!vms_TCSBRK (index)) ioctl_return (-1);`009`009/* Wait for outp
Xut drain. */
V`009`009`009if (!vms_TCFLSH (index, 0)) ioctl_return (-1);`009`009/* Flush inpu
Xt queue. */
V`009`009`009if (!vms_TCSETA (index, arg_struc)) ioctl_return (-1);`009/* Set pa
Xrameters from arg. */
X`009`009`009break;
X
X`009`009case TCSBRK:
V`009`009`009if (!vms_TCSBRK (index)) ioctl_return (-1);`009`009/* Wait for outp
Xut drain. */
X`009`009`009break;
X`009`009case TCXONC:
V`009`009`009if (!vms_TCXONC (index, arg_int)) ioctl_return (-1);`009/* Suspend/
Xstart output. */
X`009`009`009break;
X`009`009case TCFLSH:
V`009`009`009if (!vms_TCFLSH (index, arg_int)) ioctl_return (-1);`009/* Flush in
Xput, output, or both */
X`009`009`009break;
X`009`009default:
X`009`009`009ioctl_return (EINVAL);
X`009}
X
X`009`009/* Exit through a common routine. */
X`009ioctl_return (0);
X}
X
X
Xvoid
Xioctl_return (val)
X`009int`009val;
X{
X`009sigresetall();
X`009if (val == 0)
X`009`009longjmp (ioctl_return_vector, 1);
X`009else if (val != -1)
X`009`009errno = val;
X`009longjmp (ioctl_return_vector, -1);
X}
X
X
Xvoid
Xsighandler ()
X{
V`009signal_mask = sigblock (-1);`009/* Prevent other signals from interfering a
Xt this point. */
X`009signal_blocked = TRUE;`009`009/* Signals have now been blocked. */
X`009ioctl_return (EINTR);`009`009/* Force ioctl to exit. */
X}
X
X
Xvoid
Xsigcatchall ()
X{
X`009signal_blocked = FALSE;`009`009/* Signals have not been blocked yet. */
X`009hup_entry =  signal (SIGHUP,  sighandler);
X`009int_entry =  signal (SIGINT,  sighandler);
X`009quit_entry = signal (SIGQUIT, sighandler);
X`009ill_entry =  signal (SIGILL,  sighandler);
X`009trap_entry = signal (SIGTRAP, sighandler);
X`009iot_entry =  signal (SIGIOT,  sighandler);
X`009emt_entry =  signal (SIGEMT,  sighandler);
X`009fpe_entry =  signal (SIGFPE,  sighandler);
X`009kill_entry = signal (SIGKILL, sighandler);
X`009bus_entry =  signal (SIGBUS,  sighandler);
X`009segv_entry = signal (SIGSEGV, sighandler);
X`009sys_entry =  signal (SIGSYS,  sighandler);
X`009pipe_entry = signal (SIGPIPE, sighandler);
X`009alrm_entry = signal (SIGALRM, sighandler);
X`009term_entry = signal (SIGTERM, sighandler);
X}
X
X
Xvoid
Xsigresetall ()
X{
X`009signal (SIGHUP,  hup_entry);
X`009signal (SIGINT,  int_entry);
X`009signal (SIGQUIT, quit_entry);
X`009signal (SIGILL,  ill_entry);
X`009signal (SIGTRAP, trap_entry);
X`009signal (SIGIOT,  iot_entry);
X`009signal (SIGEMT,  emt_entry);
X`009signal (SIGFPE,  fpe_entry);
X`009signal (SIGKILL, kill_entry);
X`009signal (SIGBUS,  bus_entry);
X`009signal (SIGSEGV, segv_entry);
X`009signal (SIGSYS,  sys_entry);
X`009signal (SIGPIPE, pipe_entry);
X`009signal (SIGALRM, alrm_entry);
X`009signal (SIGTERM, term_entry);
X`009if (signal_blocked)
X`009`009sigsetmask (~signal_mask);
X`009signal_blocked = FALSE;
X}
X
X
X/*
X *`009This procedure gets the proper vms terminal data structure depending on
X *`009fildes.  If there currently is no structure for fildes, one is allocated
X *`009from free memory and assign to it.
X */
Xstruct vms_term_data *
Xget_vms_term_data (fildes)
X`009int`009fildes;
X{
V`009struct vms_term_data`009*back_ptr, *ptr;`009`009/* Ptr to next terminal on 
Xlist. */
X
X`009if (!vms_term_data_head)`009`009`009`009/* No terminals on list yet! */
X`009{`009vms_term_data_head = new_vms_term_data (fildes);
X`009`009return (vms_term_data_head);
X`009}
V`009else`009`009`009`009`009`009`009/* At least one on list; find correct one *
X/
X`009{`009for (ptr=vms_term_data_head;  ptr;  )
X`009`009{`009if (ptr->fildes == fildes)`009`009/* Got it! ... */
X`009`009`009`009return (ptr);`009`009`009/* ...return its address. */
X`009`009`009back_ptr = ptr;
X`009`009`009ptr = ptr->next;
X`009`009}
V`009`009ptr = new_vms_term_data (fildes);`009`009/* Couldn't find it; create on
Xe and... */
X`009`009back_ptr->next = ptr;`009`009`009`009/* ...link it to the list. */
X`009`009return (ptr);
X`009}
X}
X
X
X/*
X *`009This routine creates and initializes the data in a new vms terminal data
X *`009structure.  The unix termio data (->termio) and vms device dependent
V *`009characteristics (->vmstermio->char_buff) will be left un-initialized thei
Xr
X *`009initialization depends on the ioctl function parameters and will
X *`009be done later.
X */
Xstruct vms_term_data *
Xnew_vms_term_data (fildes)
X`009int`009fildes;
X{
X`009struct vms_term_data`009*ptr;`009`009/* Main terminal data block. */
X
X`009ptr = calloc (1, sizeof(*ptr));
X`009if (ptr)
X`009{`009ptr->fildes = fildes;`009`009/* This is the new fildes. */
X`009`009ptr->next = 0;`009`009`009/* This will be linked to end of list. */
V`009`009ptr->vmstermio = calloc(1, sizeof(*ptr->vmstermio));`009/* This is VMS 
Xtermio data. */
X`009`009if (ptr->vmstermio)
V`009`009{`009ptr->vmstermio->chan = connect(fildes);`009/* Connect a channel fo
Xr QIO processing. */
V`009`009`009if (!(ptr->vmstermio->chan))`009`009/* If we couldn't assign a chan
Xnel ... */
X`009`009`009{`009cfree (ptr->vmstermio);`009`009/*    Deallocate memory. */
X`009`009`009`009cfree (ptr);
X`009`009`009`009return (0);`009`009`009/*    Return the "failure" status. */
X`009`009`009}
X`009`009}
X`009`009else
X`009`009{`009cfree (ptr);
X`009`009`009return (0);
X`009`009}
X`009}
X`009return (ptr);
X}
X
X
Xunsigned short
Xconnect (fildes)
X`009int`009fildes;
X{
X`009static char`009`009tt_name[256];`009`009/* Name of terminal. */
X`009static $DESCRIPTOR`009(tt_descr, tt_name);`009/* Descriptor of above. */
X`009unsigned short int`009chan;`009`009`009/* Channel number for terminal. */
X
X`009unsigned int`009`009dev_class;
X`009int`009`009`009ret_len;
X`009struct item_list_struct`009item_list[2] = `009{
X`009`009`009`009`009`009`009{ 4, DVI$_DEVCLASS, &dev_class, &ret_len},
X`009`009`009`009`009`009`009{ 0, 0, 0, 0},
X`009`009`009`009`009`009};
X`009struct iosb_struct`009iosb;
X
X`009`009/* Get the terminal name. */
X`009getname (fildes, tt_name, 1);
X
X`009`009/* See if it really is a terminal. */
V`009if ((vaxc$errno = sys$getdviw(0, 0, &tt_descr, item_list, &iosb, 0, 0, 0)) 
X!= SS$_NORMAL)
X`009{`009errno = EVMSERR;
X`009`009return (0);
X`009}
X`009if ((vaxc$errno = iosb.cond) != SS$_NORMAL)
X`009{`009errno = EVMSERR;
X`009`009return (0);
X`009}
X
X`009`009/* Assign a channel to it. */
X`009if ((vaxc$errno = sys$assign(&tt_descr, &chan, 0, 0)) != SS$_NORMAL)
X`009{`009errno = EVMSERR;
X`009`009return (0);
X`009}
X
X`009`009/* Return the channel assignment. */
X`009return (chan);
X}
X
X
X
X# define`009termio_SETBITS(flag,mask)`009(index->termio->flag |= mask)
X# define`009termio_RESETBITS(flag,mask)`009(index->termio->flag &= ~mask)
X# define`009termio_TOGGLEBITS(flag,mask)`009(index->termio->flag ^= mask)
X# define`009termio_BITS(flag,mask)`009`009(index->termio->flag & mask)
X# define`009termio_BTEST(flag,mask)`009`009(termio_BITS(flag,mask) == mask)
X# define`009termio_BAUD(v)`009`009`009(termio_BITS(c_cflag, CBAUD) == v)
X# define`009termio_SETBAUD(v)`009`009{`009termio_RESETBITS (c_cflag, CBAUD); \
X`009`009`009`009`009`009`009termio_SETBITS (c_cflag, (CBAUD & v)); }
X
V# define`009SETBITS(flag,mask)`009`009(index->vmstermio->char_buff.flag |= mask
X)
V# define`009RESETBITS(flag,mask)`009`009(index->vmstermio->char_buff.flag &= ~m
Xask)
V# define`009TOGGLEBITS(flag,mask)`009`009(index->vmstermio->char_buff.flag ^= m
Xask)
V# define`009BITS(flag,mask)`009`009`009(index->vmstermio->char_buff.flag & mask
X)
X# define`009BTEST(flag,mask)`009`009(BITS(flag,mask) == mask)
X# define`009BAUD(v)`009`009`009`009(index->vmstermio->baud == v)
X# define`009SETBAUD(v)`009`009`009(index->vmstermio->baud = v)
X
Xbool
Xvms_TCGETA (index, arg)
X`009struct vms_term_data`009*index;
X`009struct termio`009`009*arg;
X{
X`009unsigned short int`009func;
X`009unsigned short int`009chan;
X`009unsigned int`009`009p1=0, p2=0;
X`009struct iosb_struct`009iosb;
X
X`009`009/* Get the VMS terminal settings. */
V`009func = IO$_SENSEMODE;`009`009`009/* Sense current setting of terminal chara
Xcteristics. */
V`009chan = index->vmstermio->chan;`009`009/* Channel for this particular QIO. *
X/
V`009p1 = &(index->vmstermio->char_buff);`009/* Address of characteristics buffe
Xr. */
X`009p2 = 12;`009`009`009`009/* Length of characteristics buffer. */
V`009if ((vaxc$errno = sys$qiow (0, chan, func, &iosb, 0, 0, p1, p2, 0, 0, 0, 0)
X) != SS$_NORMAL)
X`009{`009errno = EVMSERR;
X`009`009return (FALSE);
X`009}
X`009if ((vaxc$errno = iosb.cond) != SS$_NORMAL)
X`009{`009errno = EVMSERR;
X`009`009return (FALSE);
X`009}
X
X`009index->termio = arg;
X`009index->vmstermio->baud = iosb.variant.sense_mode.t_speed;
X
X`009`009/* Set the appropriate termio input flags. */
V`009termio_RESETBITS (c_iflag, ISTRIP);`009`009/* These flags will toggle later
X if they need to. */
X`009termio_RESETBITS (c_iflag, IXON);
X`009termio_RESETBITS (c_iflag, IXOFF);
X`009if (!BTEST (term_char, TT$M_EIGHTBIT))`009termio_SETBITS (c_iflag, ISTRIP);
X`009if (BTEST (term_char, TT$M_TTSYNC))`009termio_SETBITS (c_iflag, IXON);
X`009if (BTEST (term_char, TT$M_HOSTSYNC))`009termio_SETBITS (c_iflag, IXOFF);
X`009if (!BTEST (term_char, TT$M_LOWER))`009termio_RESETBITS (c_iflag, IUCLC);
X
X`009`009/* Set the appropriate termio output flags. */
V`009termio_SETBITS (c_oflag, OPOST);`009`009/* These flags will toggle later if
X they need to. */
X`009termio_RESETBITS (c_oflag, TAB3);
V`009if (BTEST (term_char2, TT2$M_PASTHRU))`009termio_RESETBITS (c_oflag, OPOST)
X;
X`009if (!BTEST (term_char, TT$M_LOWER))`009termio_SETBITS (c_oflag, OLCUC);
X`009if (BTEST (term_char, TT$M_MECHTAB))`009termio_SETBITS (c_oflag, TAB3);
X
X`009`009/* Set the appropriate termio hardware flags. */
V`009switch (index->vmstermio->baud)`009/* Reset it based on current baud rate. 
XB38400 is used for invalid case. */
X`009{`009case TT$C_BAUD_50:`009termio_SETBAUD (B50);`009`009break;
X`009`009case TT$C_BAUD_75:`009termio_SETBAUD (B75);`009`009break;
X`009`009case TT$C_BAUD_110:`009termio_SETBAUD (B110);`009`009break;
X`009`009case TT$C_BAUD_134:`009termio_SETBAUD (B134);`009`009break;
X`009`009case TT$C_BAUD_150:`009termio_SETBAUD (B150);`009`009break;
X`009`009case TT$C_BAUD_300:`009termio_SETBAUD (B300);`009`009break;
X`009`009case TT$C_BAUD_600:`009termio_SETBAUD (B600);`009`009break;
X`009`009case TT$C_BAUD_1200:`009termio_SETBAUD (B1200);`009`009break;
X`009`009case TT$C_BAUD_1800:`009termio_SETBAUD (B1800);`009`009break;
V`009`009case TT$C_BAUD_2000:`009termio_SETBAUD (B38400);`009break;`009/* 2000 i
Xs invalid case */
X`009`009case TT$C_BAUD_2400:`009termio_SETBAUD (B2400);`009`009break;
V`009`009case TT$C_BAUD_3600:`009termio_SETBAUD (B38400);`009break;`009/* 3600 i
Xs invalid case */
X`009`009case TT$C_BAUD_4800:`009termio_SETBAUD (B4800);`009`009break;
V`009`009case TT$C_BAUD_7200:`009termio_SETBAUD (B38400);`009break;`009/* 7200 i
Xs invalid case */
X`009`009case TT$C_BAUD_9600:`009termio_SETBAUD (B9600);`009`009break;
X`009`009case TT$C_BAUD_19200:`009termio_SETBAUD (B19200);`009break;
V`009`009default:`009`009termio_SETBAUD (B38400);`009break;`009/* all else is in
Xvalid case */
X`009}
V`009termio_RESETBITS (c_cflag, HUPCL);`009`009/* These flags will toggle later 
Xif they need to. */
X`009termio_RESETBITS (c_cflag, CLOCAL);
X`009if (BTEST (term_char2, TT2$M_HANGUP))`009termio_SETBITS (c_cflag, HUPCL);
X`009if (!BTEST (term_char, TT$M_MODEM))`009termio_SETBITS (c_cflag, CLOCAL);
X
X`009`009/* Set the appropriate termio line-discipline flags. */
V`009termio_RESETBITS (c_lflag, ECHO);`009`009/* These flags will toggle later i
Xf they need to. */
X`009if (!BTEST (term_char, TT$M_NOECHO))`009termio_SETBITS (c_lflag, ECHO);
X
X`009`009/* Return success. */
X`009return (TRUE);
X}
X
X
Xbool
Xvms_TCSETA (index, arg)
X`009struct vms_term_data`009*index;
X`009struct termio`009`009*arg;
X{
V `009unsigned short int`009func=0;`009`009`009/* QIO function code and modifier
Xs. */
X`009unsigned short int`009chan;
V`009unsigned int`009`009p1=0, p2=0, p3=0;`009/* QIO funciton dependent paramete
Xrs. */
V`009struct iosb_struct`009iosb;`009`009`009/* I/O status block for call to QIO.
X */
V`009bool`009`009`009changes;`009`009/* TRUE if VMS term. characteristics have c
Xhanged. */
X
X`009index->termio = arg;
X
X`009`009/* Set the VMS control bits according to termio input flags. */
X`009if (termio_BTEST (c_iflag, ISTRIP) == BTEST (term_char, TT$M_EIGHTBIT))
X`009`009{ TOGGLEBITS (term_char, TT$M_EIGHTBIT);  changes = TRUE; }
X`009if (termio_BTEST (c_iflag, IXON) != BTEST (term_char, TT$M_TTSYNC))
X`009`009{ TOGGLEBITS (term_char, TT$M_TTSYNC);  changes = TRUE; }
X`009if (termio_BTEST (c_iflag, IXOFF) != BTEST (term_char, TT$M_HOSTSYNC))
X`009`009{ TOGGLEBITS (term_char, TT$M_HOSTSYNC);  changes = TRUE; }
X`009if (termio_BTEST (c_iflag, IUCLC) && !BTEST (term_char, TT$M_LOWER))
X`009`009{ SETBITS (term_char, TT$M_LOWER);  changes = TRUE; }
X
X`009`009/* Set the VMS control bits according to termio output flags. */
X`009if (termio_BTEST (c_oflag, OPOST) == BTEST (term_char2, TT2$M_PASTHRU))
X`009`009{ TOGGLEBITS (term_char2, TT2$M_PASTHRU);  changes = TRUE; }
X`009if (!termio_BTEST (c_oflag, OLCUC) && !BTEST (term_char, TT$M_LOWER))
X`009`009{ SETBITS (term_char, TT$M_LOWER);  changes = TRUE; }
X`009if (termio_BTEST (c_oflag, TAB3) != BTEST (term_char, TT$M_MECHTAB))
X`009`009{ TOGGLEBITS (term_char, TT$M_MECHTAB);  changes = TRUE; }
X
X`009`009/* Set the VMS control bits according to termio hardware flags. */
X`009switch (termio_BITS (c_cflag, CBAUD))
V`009{`009case B0:`009break;`009/* This could possibly be used to cause a "hangu
Xp". */
V`009`009case B50:`009if (!BAUD(TT$C_BAUD_50)) {SETBAUD (TT$C_BAUD_50); changes 
X= TRUE;}`009break;
V`009`009case B75:`009if (!BAUD(TT$C_BAUD_75)) {SETBAUD (TT$C_BAUD_75); changes 
X= TRUE;}`009break;
V`009`009case B110:`009if (!BAUD(TT$C_BAUD_110)) {SETBAUD (TT$C_BAUD_110); chang
Xes = TRUE;}`009break;
V`009`009case B134:`009if (!BAUD(TT$C_BAUD_134)) {SETBAUD (TT$C_BAUD_134); chang
Xes = TRUE;}`009break;
V`009`009case B150:`009if (!BAUD(TT$C_BAUD_150)) {SETBAUD (TT$C_BAUD_150); chang
Xes = TRUE;}`009break;
X`009`009case B200:`009ioctl_return (EINVAL);
V`009`009case B300:`009if (!BAUD(TT$C_BAUD_300)) {SETBAUD (TT$C_BAUD_300); chang
Xes = TRUE;}`009break;
V`009`009case B600:`009if (!BAUD(TT$C_BAUD_600)) {SETBAUD (TT$C_BAUD_600); chang
Xes = TRUE;}`009break;
V`009`009case B1200:`009if (!BAUD(TT$C_BAUD_1200)) {SETBAUD (TT$C_BAUD_1200); ch
Xanges = TRUE;}`009break;
V`009`009case B1800:`009if (!BAUD(TT$C_BAUD_1800)) {SETBAUD (TT$C_BAUD_1800); ch
Xanges = TRUE;}`009break;
V`009`009case B2400:`009if (!BAUD(TT$C_BAUD_2400)) {SETBAUD (TT$C_BAUD_2400); ch
Xanges = TRUE;}`009break;
V`009`009case B4800:`009if (!BAUD(TT$C_BAUD_4800)) {SETBAUD (TT$C_BAUD_4800); ch
Xanges = TRUE;}`009break;
V`009`009case B9600:`009if (!BAUD(TT$C_BAUD_9600)) {SETBAUD (TT$C_BAUD_9600); ch
Xanges = TRUE;}`009break;
V`009`009case B19200:`009if (!BAUD(TT$C_BAUD_19200)) {SETBAUD (TT$C_BAUD_19200);
X changes = TRUE;} break;
V`009`009case B38400:`009break;`009/* This is used for VMS speed that unix can't
X handle. */
X`009`009default:`009ioctl_return (EINVAL);
X`009}
X`009if (termio_BTEST (c_cflag, HUPCL) != BTEST (term_char2, TT2$M_HANGUP))
X`009`009{ TOGGLEBITS (term_char2, TT2$M_HANGUP);  changes = TRUE; }
X`009if (termio_BTEST (c_cflag, CLOCAL) == BTEST (term_char, TT$M_MODEM))
X`009`009{ TOGGLEBITS (term_char, TT$M_MODEM);  changes = TRUE; }
X
V`009`009/* Set the VMS control bits according to termio line-discipline flags. 
X*/
X`009if (termio_BTEST (c_lflag, ECHO) == BTEST (term_char, TT$M_NOECHO))
X`009`009{ TOGGLEBITS (term_char, TT$M_NOECHO);  changes = TRUE; }
X
X`009`009/* Set the VMS terminal characteristics. */
X/*
X * As it turns out, it may be important to set the terminal characteristics
X * even if it looks like nothing has changed.  This is due to the fact that
X * different I/O streams may access the same terminal.  You may have changed
X * the attributes on stdout, thus changing the terminal characteristics for
X * stdin and stderr.  These sorts of cross-stream changes are impossible to
X * track, so I will always set the attributes based on the current values
X * in "termio".  For this reason, the following line has been commented out!
X *
X`009if (changes)
X */
V`009{`009func = IO$_SETMODE;`009`009`009/* Set current terminal characteristics
X. */
V`009`009chan = index->vmstermio->chan;`009`009/* Channel for this particular QI
XO. */
V`009`009p1 = &(index->vmstermio->char_buff);`009/* Address of characteristics b
Xuffer. */
X`009`009p2 = 12;`009`009`009`009/* Length of characteristics buffer. */
X`009`009p3 = index->vmstermio->baud;`009`009/* The (possibly new) baud rate. */
V`009`009if ((vaxc$errno = sys$qiow (0, chan, func, &iosb, 0, 0, p1, p2, p3, 0, 
X0, 0)) != SS$_NORMAL)
X`009`009{`009errno = EVMSERR;
X`009`009`009return (FALSE);
X`009`009}
X`009`009if ((vaxc$errno = iosb.cond) != SS$_NORMAL)
X`009`009{`009errno = EVMSERR;
X`009`009`009return (FALSE);
X`009`009}
X`009}
X
X`009`009/* Return success. */
X`009return (TRUE);
X}
X
X
X/*
X *`009This function causes the process to "hang" until all output to the
X *`009specified file gets written.  I don't see an immediate use for this
X *`009so it simply returns success.  I will let the device driver handle
X *`009queuing up output and stopping on its own if it needs to.
X */
Xbool
Xvms_TCSBRK (index)
X`009struct vms_term_data`009*index;
X{
X`009return (TRUE);
X}
X
X
X/*
X *`009This function controls XON/XOFF protocol by suspending/resuming output
X *`009on the output file based on the value 0/1 for arg.  Currently, I will
X *`009assume the VMS device driver will handle this and simply returns success;
X *`009when in "raw" mode...tough luck...handle it yourself or fix this code to
X *`009do it!
X */
Xbool
Xvms_TCXONC (index, arg)
X`009struct vms_term_data`009*index;
X`009int`009`009`009arg;
X{
X`009if (arg != 0  &&  arg != 1)
X`009`009ioctl_return (EINVAL);
X`009return (TRUE);
X}
X
X
X/*
V *`009This routine has three functions flush input/flush output/flush both base
Xd
X *`009on the value of 0/1/2 for arg.
X */
Xbool
Xvms_TCFLSH (index, arg)
X`009struct vms_term_data`009*index;
X`009int`009`009`009arg;
X{
X`009switch (arg)
X`009{`009case 0:
X`009`009`009return ( gvg$do_flush_read (index) );
X`009`009`009break;
X`009`009case 1:
X`009`009`009return ( gvg$do_flush_write (index) );
X`009`009`009break;
X`009`009case 2:
X`009`009`009return ( gvg$do_flush_read (index) &&
X`009`009`009`009 gvg$do_flush_write (index) );
X`009`009`009break;
X`009`009default:
X`009`009`009ioctl_return (EINVAL);
X`009}
X}
X
X
Xvms_dup012 (fd)
X`009int`009fd;`009/* File descriptor to be duplicated. */
X{`009
V`009struct vms_term_data`009*ptr, *back_ptr, *save_ptr;`009/* Misc. pointers. *
X/
X`009int`009`009`009fdA,fdB;`009`009`009/* File descr. that need duplication. */
X
X`009`009/* Get file descriptors to duplicate to. */
X`009switch (fd)
X`009{`009case 0:`009`009fdA = 1;  fdB = 2;`009break;
X`009`009case 1:`009`009fdA = 0;  fdB = 2;`009break;
X`009`009case 2: `009fdA = 0;  fdB = 1;`009break;
X`009`009default:`009return(0);
X`009}
X
X`009`009/* Get the pointer to the structure for file descriptor 0. */
X`009for (save_ptr=0, ptr=vms_term_data_head;  ptr;  ptr=ptr->next)
X`009`009if (ptr->fildes == fd)
X`009`009{`009save_ptr = ptr;
X`009`009`009break;
X`009`009}
X
X`009`009/* If no fd on list, just return. */
X`009if (!save_ptr)
X`009`009return (0);
X
X`009`009/* Find fd A if there is one! */
X`009for (ptr=vms_term_data_head;  ptr;  ptr=ptr->next)
X`009`009if (ptr->fildes == fdA)
X`009`009`009break;
X
X`009`009/* If it's out there, merely swap existing pointers.  Note, in
X`009`009   this case, I don't even use the default structures.  Note
X`009`009   also that I don't free the old pointer to vmstermio if it
X`009`009   was there.  This is because it is possible that somewhere
X`009`009   there is still a pointer to that data area.  If I were to
X`009`009   free that memory, the next time that data area is accessed
X`009`009   they could get an access violation.  Better to waste memory
X`009`009   than screw someone over later! */
X`009if (ptr)
X`009{`009ptr->vmstermio = save_ptr->vmstermio;
X`009`009ptr->termio = save_ptr->termio;
X`009`009ptr->_iobuf = IO_POINTER[fdA+1];
X`009`009ptr->active = TRUE;
X`009`009save_ptr = ptr;`009`009/* I want to chain fd B onto fd A. */
X`009}
X`009else
X`009{`009def1_vms_term_data = *save_ptr;
X`009`009def1_vms_term_data.fildes = fdA;
X`009`009def1_vms_term_data._iobuf = IO_POINTER[fdA+1];
X`009`009def1_vms_term_data.active = TRUE;
X`009`009save_ptr->next = &def1_vms_term_data;
V`009`009save_ptr = &def1_vms_term_data;`009`009/* I want to chain fd B onto fd 
XA. */
X`009}
X
X`009`009/* Find fd B if there is one! */
X`009for (ptr=vms_term_data_head;  ptr;  ptr=ptr->next)
X`009`009if (ptr->fildes == fdB)
X`009`009`009break;
X
X`009`009/* If it's out there, merely swap existing pointers.  Note, in
X`009`009`009this case, I don't even use the default structures. */
X`009if (ptr)
X`009{`009ptr->vmstermio = save_ptr->vmstermio;
X`009`009ptr->termio = save_ptr->termio;
X`009`009ptr->_iobuf = IO_POINTER[fdB+1];
X`009`009ptr->active = TRUE;
X`009}
X`009else
X`009{`009def2_vms_term_data = *save_ptr;
X`009`009def2_vms_term_data.fildes = fdB;
X`009`009def2_vms_term_data._iobuf = IO_POINTER[fdB+1];
X`009`009def2_vms_term_data.active = TRUE;
X`009`009save_ptr->next = &def2_vms_term_data;
X`009}
X}
$ GoSub Convert_File
$ Goto Part3
------------------ cut here -----------------
-- 
/* My opinions...               *	Tony Ivanov   MS-4B		*/
/* shared by my company?!...    *	Grass Valley Group, Inc.	*/
/* you've got to be kidding!    *	P.O. Box 1114			*/
/* "tony@gvgpvd.GVG.TEK.COM"    *	Grass Valley, CA  95945		*/

