
GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 1
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)



    1        	 
    2        	/*
    3        	 *	This is the VMS implementation of unix's ioctl.  For simplicity purposes
    4        	 *	and because I don't want to write a complete terminal driver, I will let
    5        	 *	the VMS terminal driver do as much as possible.  Because of this, some
    6        	 *	ioctl functionality will be lost.  The following list shows what is currently
    7        	 *	implemented.  Those preceded by an asterisk (*) need special VMS I/O
    8        	 *	processing.
    9        	 *		The following input control flags are recognized:
   10        	 *		    *	BRKINT	- implemented to flag cbreak (crmode) condition.
   11        	 *			ISTRIP	- implemented to flag "EIGHTBIT" VMS terminal characteristic.
   12        	 *		    *	INLCR	- implemented.
   13        	 *			ICRNL	- implemented.
   14        	 *		    *	IUCLC	- implemented.
   15        	 *			IXON	- implemented to flag "TTSYNC" VMS terminal characteristic.
   16        	 *			IXOFF	- implemented to flag "HOSTSYNC" VMS terminal characteristic.
   17        	 *		The following output control flags are recognized:
   18        	 *			OPOST	- implemented to flag raw condition.
   19        	 *		    *	OLCUC	- implemented.
   20        	 *			ONLCR	- implemented.
   21        	 *		    *	OCRNL	- implemented.
   22        	 *			TAB3	- implemented to flag "TAB" expansion VMS terminal characteristic.
   23        	 *		The following hardware control flags are recognized:
   24        	 *			CBAUD	- implemented for all baud information common to unix and VMS.
   25        	 *			HUPCL	- implemented to flag "HANGUP" VMS terminal characteristic.
   26        	 *			CLOCAL	- implemented to flag "MODEM" VMS terminal characteristic.
   27        	 *		The following line-discipline control flags are recognized:
   28        	 *			ECHO	- implemented to flag "ECHO" VMS terminal characteristic.
   29        	 */
   30        	 
   31        	# include	<descrip.h>
  403        	# include	<dcdef.h>
  657        	# include	<dvidef.h>
  861        	# include	<errno.h>
  904        	# include	<iodef.h>
 1289        	# include	<setjmp.h>
 1296        	# include	<signal.h>
 1360        	# include	<ssdef.h>
 1769        	# include	"sys_struct.h"
 1809        	# include	<ttdef.h>
 1948        	# include	<tt2def.h>
 2014        	# include	"vmstermio.h"	/* Only structures defined. */
 2308        	# define	bool	char
 2309        	# define	reg	register
 2310        	 
 2311        	 
 2312        	/*	Primary data structures used to control VMS termio functions. */
 2313        	globaldef noshare struct vms_term_data	*vms_term_data_head = 0;	/* Head of vms terminal data list. */
 2314        	globaldef noshare struct vms_term_data	def1_vms_term_data;		/* Default terminal data list for fd 1. */
 2315        	globaldef noshare struct vms_term_data	def2_vms_term_data;		/* Default terminal data list for fd 2. */
 2316        	globalref         struct _iobuf		**IO_POINTER;			/* VAX C pointer to I/O buffers. */
 2317        	 
 2318        	/*	Secondary data structures used with vmstermio. */
 2319        	globaldef noshare struct termio 	_tty = {0, 0, 0, 0, 0, {0x03, 0, 0x7f, 0x14, 0x1a, 0, 0, 0}};
 2320        	globaldef noshare struct termio		_res_tty;	/* used to save terminal settings for restoration. */

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 2
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2321        	globaldef noshare int			_tty_ch = 1;
 2322        	 
 2323        	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2324        	 *
 2325        	 *	The following definitions, data structures and procedures specifically deal with
 2326        	 *	implementing the ioctl routine.
 2327        	 *
 2328        	 */
 2329        		/* Forward references. */
 2330        	extern void			ioctl_return();		/* Routine for force exit from ioctl function. */
 2331        	extern void			sighandler();		/* Function for handling any signal during ioctl. */
 2332        	extern void			sigcatchall();		/* Function to set up signal handler for all signals. */
 2333        	extern void			sigresetall();		/* Function to revert signal handlers to previous ones. */
 2334        	extern struct vms_term_data	*get_vms_term_data();	/* Function to link a fildes to a vms term data block. */
 2335        	extern struct vms_term_data	*new_vms_term_data();	/* Function to create a new vms terminal data block. */
 2336        	extern unsigned short		connect();		/* Connect a channel to a file. */
 2337        	extern bool			vms_TCGETA();		/* Function to get current terminal characteristics. */
 2338        	extern bool			vms_TCSETA();		/* Function to set terminal characteristics. */
 2339        	extern bool			vms_TCSBRK();		/* Function to wait for output to flush. */
 2340        	extern bool			vms_TCXONC();		/* Function to control XON/XOFF protocol. */
 2341        	extern bool			vms_TCFLSH();		/* Function to flush input/output queues. */
 2342        	 
 2343        		/* Signal processing stuff. */
 2344        	jmp_buf		ioctl_return_vector;	/* Environment for setjmp/longjmp return vector. */
 2345        	bool		signal_blocked;		/* TRUE if signals have been blocked. */
 2346        	unsigned int	signal_mask;		/* Mask of signals that should be re-established if signals are blocked. */
 2347        	/*
 2348        	 *	Entry points for signal processing routines for various signals.
 2349        	 */
 2350        	int		*hup_entry, *int_entry, *quit_entry, *ill_entry, *trap_entry,
 2351        			*iot_entry, *emt_entry, *fpe_entry, *kill_entry, *bus_entry,
 2352        			*segv_entry, *sys_entry, *pipe_entry, *alrm_entry, *term_entry;
 2353        	 
 2354        	 
 2355        	int
 2356        	ioctl (fildes, request, arg)
 2357        		int	fildes;
 2358        		int	request;
 2359        	{
 2360    1   	#define		arg_struc	((struct termio *) arg)		/* When arg is used as a termio structure. */
 2361    1   	#define		arg_int		((int) arg)			/* When arg is simply an integer. */
 2362    1   		struct vms_term_data	*index;				/* Index into VMS terminal data block. */
 2363    1   		int			return_val;			/* Return value for "setjmp":
 2364    1   									      0 - initialization of return vector.
 2365    1   									      1 - Return with "success" status.
 2366    1   									     -1 - Return with "failure" status. */
 2367    1   	 
 2368    1   			/* Set up ioctl common return vector. */
 2369    1   		if ((return_val = setjmp (ioctl_return_vector)) == 1)
 2370    1   			return (0);
 2371    1   		else if (return_val == -1)
 2372    1   			return (-1);
 2373    1   	 
 2374    1   			/* Catch all signals */
 2375    1   		sigcatchall ();
 2376    1   	 
 2377    1   			/* Make sure file for which ioctl is called is a terminal. */

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 3
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2378    1   		if (!isatty(fildes))
 2379    1   			ioctl_return ((errno == ENOTTY) ? 0 : errno);
 2380    1   	/*		ioctl_return (ENOTTY); */
 2381    1   	 
 2382    1   			/* Establish the proper vms control block. */
 2383    1   		if (!(index = get_vms_term_data (fildes)))
 2384    1   			ioctl_return (-1);
 2385    1   	 
 2386    1   			/* Connect the I/O buffer and make this an active data block if it isn't already. */
 2387    1   		if (!index->_iobuf)
 2388    1   			index->_iobuf = IO_POINTER[fildes+1];	/* This is the VAX C I/O buffer stuff. */
 2389    1   		index->active = TRUE;
 2390    1   	 
 2391    1   			/* Process the request. */
 2392    1   		switch (request)
 2393    1   		{	case TCGETA:
 2394    2   				if (arg < 0x200) ioctl_return (EINVAL);
 2395    2   	 			if (!vms_TCGETA (index, arg_struc)) ioctl_return (-1);	/* Load parameters into arg. */
 2396    2   				break;
 2397    2   			case TCSETA:
 2398    2   				if (arg < 0x200) ioctl_return (EINVAL);
 2399    2   				if (!vms_TCSETA (index, arg_struc)) ioctl_return (-1);	/* Set parameters from arg. */
 2400    2   				break;
 2401    2   			case TCSETAW:
 2402    2   				if (arg < 0x200) ioctl_return (EINVAL);
 2403    2   				if (!vms_TCSBRK (index)) ioctl_return (-1);		/* Wait for output drain. */
 2404    2   				if (!vms_TCSETA (index, arg_struc)) ioctl_return (-1);	/* Set parameters from arg. */
 2405    2   				break;
 2406    2   			case TCSETAF:
 2407    2   				if (arg < 0x200) ioctl_return (EINVAL);
 2408    2   				if (!vms_TCSBRK (index)) ioctl_return (-1);		/* Wait for output drain. */
 2409    2   				if (!vms_TCFLSH (index, 0)) ioctl_return (-1);		/* Flush input queue. */
 2410    2   				if (!vms_TCSETA (index, arg_struc)) ioctl_return (-1);	/* Set parameters from arg. */
 2411    2   				break;
 2412    2   	 
 2413    2   			case TCSBRK:
 2414    2   				if (!vms_TCSBRK (index)) ioctl_return (-1);		/* Wait for output drain. */
 2415    2   				break;
 2416    2   			case TCXONC:
 2417    2   				if (!vms_TCXONC (index, arg_int)) ioctl_return (-1);	/* Suspend/start output. */
 2418    2   				break;
 2419    2   			case TCFLSH:
 2420    2   				if (!vms_TCFLSH (index, arg_int)) ioctl_return (-1);	/* Flush input, output, or both */
 2421    2   				break;
 2422    2   			default:
 2423    2   				ioctl_return (EINVAL);
 2424    2   		}
 2425    1   	 
 2426    1   			/* Exit through a common routine. */
 2427    1   		ioctl_return (0);
 2428    1   	}
 2429        	 
 2430        	 
 2431        	void
 2432        	ioctl_return (val)
 2433        		int	val;
 2434        	{

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 4
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2435    1   		sigresetall();
 2436    1   		if (val == 0)
 2437    1   			longjmp (ioctl_return_vector, 1);
 2438    1   		else if (val != -1)
 2439    1   			errno = val;
 2440    1   		longjmp (ioctl_return_vector, -1);
 2441    1   	}
 2442        	 
 2443        	 
 2444        	void
 2445        	sighandler ()
 2446        	{
 2447    1   		signal_mask = sigblock (-1);	/* Prevent other signals from interfering at this point. */
 2448    1   		signal_blocked = TRUE;		/* Signals have now been blocked. */
 2449    1   		ioctl_return (EINTR);		/* Force ioctl to exit. */
 2450    1   	}
 2451        	 
 2452        	 
 2453        	void
 2454        	sigcatchall ()
 2455        	{
 2456    1   		signal_blocked = FALSE;		/* Signals have not been blocked yet. */
 2457    1   		hup_entry =  signal (SIGHUP,  sighandler);
 2458    1   		int_entry =  signal (SIGINT,  sighandler);
 2459    1   		quit_entry = signal (SIGQUIT, sighandler);
 2460    1   		ill_entry =  signal (SIGILL,  sighandler);
 2461    1   		trap_entry = signal (SIGTRAP, sighandler);
 2462    1   		iot_entry =  signal (SIGIOT,  sighandler);
 2463    1   		emt_entry =  signal (SIGEMT,  sighandler);
 2464    1   		fpe_entry =  signal (SIGFPE,  sighandler);
 2465    1   		kill_entry = signal (SIGKILL, sighandler);
 2466    1   		bus_entry =  signal (SIGBUS,  sighandler);
 2467    1   		segv_entry = signal (SIGSEGV, sighandler);
 2468    1   		sys_entry =  signal (SIGSYS,  sighandler);
 2469    1   		pipe_entry = signal (SIGPIPE, sighandler);
 2470    1   		alrm_entry = signal (SIGALRM, sighandler);
 2471    1   		term_entry = signal (SIGTERM, sighandler);
 2472    1   	}
 2473        	 
 2474        	 
 2475        	void
 2476        	sigresetall ()
 2477        	{
 2478    1   		signal (SIGHUP,  hup_entry);
 2479    1   		signal (SIGINT,  int_entry);
 2480    1   		signal (SIGQUIT, quit_entry);
 2481    1   		signal (SIGILL,  ill_entry);
 2482    1   		signal (SIGTRAP, trap_entry);
 2483    1   		signal (SIGIOT,  iot_entry);
 2484    1   		signal (SIGEMT,  emt_entry);
 2485    1   		signal (SIGFPE,  fpe_entry);
 2486    1   		signal (SIGKILL, kill_entry);
 2487    1   		signal (SIGBUS,  bus_entry);
 2488    1   		signal (SIGSEGV, segv_entry);
 2489    1   		signal (SIGSYS,  sys_entry);
 2490    1   		signal (SIGPIPE, pipe_entry);
 2491    1   		signal (SIGALRM, alrm_entry);

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 5
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2492    1   		signal (SIGTERM, term_entry);
 2493    1   		if (signal_blocked)
 2494    1   			sigsetmask (~signal_mask);
 2495    1   		signal_blocked = FALSE;
 2496    1   	}
 2497        	 
 2498        	 
 2499        	/*
 2500        	 *	This procedure gets the proper vms terminal data structure depending on
 2501        	 *	fildes.  If there currently is no structure for fildes, one is allocated
 2502        	 *	from free memory and assign to it.
 2503        	 */
 2504        	struct vms_term_data *
 2505        	get_vms_term_data (fildes)
 2506        		int	fildes;
 2507        	{
 2508    1   		struct vms_term_data	*back_ptr, *ptr;		/* Ptr to next terminal on list. */
 2509    1   	 
 2510    1   		if (!vms_term_data_head)				/* No terminals on list yet! */
 2511    1   		{	vms_term_data_head = new_vms_term_data (fildes);
 2512    2   			return (vms_term_data_head);
 2513    2   		}
 2514    1   		else							/* At least one on list; find correct one */
 2515    1   		{	for (ptr=vms_term_data_head;  ptr;  )
 2516    2   			{	if (ptr->fildes == fildes)		/* Got it! ... */
 2517    3   					return (ptr);			/* ...return its address. */
 2518    3   				back_ptr = ptr;
 2519    3   				ptr = ptr->next;
 2520    3   			}
 2521    2   			ptr = new_vms_term_data (fildes);		/* Couldn't find it; create one and... */
 2522    2   			back_ptr->next = ptr;				/* ...link it to the list. */
 2523    2   			return (ptr);
 2524    2   		}
 2525    1   	}
 2526        	 
 2527        	 
 2528        	/*
 2529        	 *	This routine creates and initializes the data in a new vms terminal data
 2530        	 *	structure.  The unix termio data (->termio) and vms device dependent
 2531        	 *	characteristics (->vmstermio->char_buff) will be left un-initialized their
 2532        	 *	initialization depends on the ioctl function parameters and will
 2533        	 *	be done later.
 2534        	 */
 2535        	struct vms_term_data *
 2536        	new_vms_term_data (fildes)
 2537        		int	fildes;
 2538        	{
 2539    1   		struct vms_term_data	*ptr;		/* Main terminal data block. */
 2540    1   	 
 2541    1   		ptr = calloc (1, sizeof(*ptr));
 2542    1   		if (ptr)
 2543    1   		{	ptr->fildes = fildes;		/* This is the new fildes. */
 2544    2   			ptr->next = 0;			/* This will be linked to end of list. */
 2545    2   			ptr->vmstermio = calloc(1, sizeof(*ptr->vmstermio));	/* This is VMS termio data. */
 2546    2   			if (ptr->vmstermio)
 2547    2   			{	ptr->vmstermio->chan = connect(fildes);	/* Connect a channel for QIO processing. */
 2548    3   				if (!(ptr->vmstermio->chan))		/* If we couldn't assign a channel ... */

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 6
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2549    3   				{	cfree (ptr->vmstermio);		/*    Deallocate memory. */
 2550    4   					cfree (ptr);
 2551    4   					return (0);			/*    Return the "failure" status. */
 2552    4   				}
 2553    3   			}
 2554    2   			else
 2555    2   			{	cfree (ptr);
 2556    3   				return (0);
 2557    3   			}
 2558    2   		}
 2559    1   		return (ptr);
 2560    1   	}
 2561        	 
 2562        	 
 2563        	unsigned short
 2564        	connect (fildes)
 2565        		int	fildes;
 2566        	{
 2567    1   		static char		tt_name[256];		/* Name of terminal. */
 2568    1   		static $DESCRIPTOR	(tt_descr, tt_name);	/* Descriptor of above. */
 2569    1   		unsigned short int	chan;			/* Channel number for terminal. */
 2570    1   	 
 2571    1   		unsigned int		dev_class;
 2572    1   		int			ret_len;
 2573    1   		struct item_list_struct	item_list[2] = 	{
 2574    1   								{ 4, DVI$_DEVCLASS, &dev_class, &ret_len},
 2575    1   								{ 0, 0, 0, 0},
 2576    1   							};
 2577    1   		struct iosb_struct	iosb;
 2578    1   	 
 2579    1   			/* Get the terminal name. */
 2580    1   		getname (fildes, tt_name, 1);
 2581    1   	 
 2582    1   			/* See if it really is a terminal. */
 2583    1   		if ((vaxc$errno = sys$getdviw(0, 0, &tt_descr, item_list, &iosb, 0, 0, 0)) != SS$_NORMAL)
 2584    1   		{	errno = EVMSERR;
 2585    2   			return (0);
 2586    2   		}
 2587    1   		if ((vaxc$errno = iosb.cond) != SS$_NORMAL)
 2588    1   		{	errno = EVMSERR;
 2589    2   			return (0);
 2590    2   		}
 2591    1   	 
 2592    1   			/* Assign a channel to it. */
 2593    1   		if ((vaxc$errno = sys$assign(&tt_descr, &chan, 0, 0)) != SS$_NORMAL)
 2594    1   		{	errno = EVMSERR;
 2595    2   			return (0);
 2596    2   		}
 2597    1   	 
 2598    1   			/* Return the channel assignment. */
 2599    1   		return (chan);
 2600    1   	}
 2601        	 
 2602        	 
 2603        	 
 2604        	# define	termio_SETBITS(flag,mask)	(index->termio->flag |= mask)
 2605        	# define	termio_RESETBITS(flag,mask)	(index->termio->flag &= ~mask)

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 7
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2606        	# define	termio_TOGGLEBITS(flag,mask)	(index->termio->flag ^= mask)
 2607        	# define	termio_BITS(flag,mask)		(index->termio->flag & mask)
 2608        	# define	termio_BTEST(flag,mask)		(termio_BITS(flag,mask) == mask)
 2609        	# define	termio_BAUD(v)			(termio_BITS(c_cflag, CBAUD) == v)
 2610        	# define	termio_SETBAUD(v)		{	termio_RESETBITS (c_cflag, CBAUD); \
 2611        								termio_SETBITS (c_cflag, (CBAUD & v)); }
 2612        	 
 2613        	# define	SETBITS(flag,mask)		(index->vmstermio->char_buff.flag |= mask)
 2614        	# define	RESETBITS(flag,mask)		(index->vmstermio->char_buff.flag &= ~mask)
 2615        	# define	TOGGLEBITS(flag,mask)		(index->vmstermio->char_buff.flag ^= mask)
 2616        	# define	BITS(flag,mask)			(index->vmstermio->char_buff.flag & mask)
 2617        	# define	BTEST(flag,mask)		(BITS(flag,mask) == mask)
 2618        	# define	BAUD(v)				(index->vmstermio->baud == v)
 2619        	# define	SETBAUD(v)			(index->vmstermio->baud = v)
 2620        	 
 2621        	bool
 2622        	vms_TCGETA (index, arg)
 2623        		struct vms_term_data	*index;
 2624        		struct termio		*arg;
 2625        	{
 2626    1   		unsigned short int	func;
 2627    1   		unsigned short int	chan;
 2628    1   		unsigned int		p1=0, p2=0;
 2629    1   		struct iosb_struct	iosb;
 2630    1   	 
 2631    1   			/* Get the VMS terminal settings. */
 2632    1   		func = IO$_SENSEMODE;			/* Sense current setting of terminal characteristics. */
 2633    1   		chan = index->vmstermio->chan;		/* Channel for this particular QIO. */
 2634    1   		p1 = &(index->vmstermio->char_buff);	/* Address of characteristics buffer. */
 2635    1   		p2 = 12;				/* Length of characteristics buffer. */
 2636    1   		if ((vaxc$errno = sys$qiow (0, chan, func, &iosb, 0, 0, p1, p2, 0, 0, 0, 0)) != SS$_NORMAL)
 2637    1   		{	errno = EVMSERR;
 2638    2   			return (FALSE);
 2639    2   		}
 2640    1   		if ((vaxc$errno = iosb.cond) != SS$_NORMAL)
 2641    1   		{	errno = EVMSERR;
 2642    2   			return (FALSE);
 2643    2   		}
 2644    1   	 
 2645    1   		index->termio = arg;
 2646    1   		index->vmstermio->baud = iosb.variant.sense_mode.t_speed;
 2647    1   	 
 2648    1   			/* Set the appropriate termio input flags. */
 2649    1   		termio_RESETBITS (c_iflag, ISTRIP);		/* These flags will toggle later if they need to. */
 2650    1   		termio_RESETBITS (c_iflag, IXON);
 2651    1   		termio_RESETBITS (c_iflag, IXOFF);
 2652    1   		if (!BTEST (term_char, TT$M_EIGHTBIT))	termio_SETBITS (c_iflag, ISTRIP);
 2653    1   		if (BTEST (term_char, TT$M_TTSYNC))	termio_SETBITS (c_iflag, IXON);
 2654    1   		if (BTEST (term_char, TT$M_HOSTSYNC))	termio_SETBITS (c_iflag, IXOFF);
 2655    1   		if (!BTEST (term_char, TT$M_LOWER))	termio_RESETBITS (c_iflag, IUCLC);
 2656    1   	 
 2657    1   			/* Set the appropriate termio output flags. */
 2658    1   		termio_SETBITS (c_oflag, OPOST);		/* These flags will toggle later if they need to. */
 2659    1   		termio_SETBITS (c_oflag, TAB3);
 2660    1   		if (BTEST (term_char2, TT2$M_PASTHRU))	termio_RESETBITS (c_oflag, OPOST);
 2661    1   		if (!BTEST (term_char, TT$M_LOWER))	termio_SETBITS (c_oflag, OLCUC);
 2662    1   		if (BTEST (term_char, TT$M_MECHTAB))	termio_RESETBITS (c_oflag, TAB3);

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 8
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2663    1   	 
 2664    1   			/* Set the appropriate termio hardware flags. */
 2665    1   		switch (index->vmstermio->baud)	/* Reset it based on current baud rate. B38400 is used for invalid case. */
 2666    1   		{	case TT$C_BAUD_50:	termio_SETBAUD (B50);		break;
 2667    2   			case TT$C_BAUD_75:	termio_SETBAUD (B75);		break;
 2668    2   			case TT$C_BAUD_110:	termio_SETBAUD (B110);		break;
 2669    2   			case TT$C_BAUD_134:	termio_SETBAUD (B134);		break;
 2670    2   			case TT$C_BAUD_150:	termio_SETBAUD (B150);		break;
 2671    2   			case TT$C_BAUD_300:	termio_SETBAUD (B300);		break;
 2672    2   			case TT$C_BAUD_600:	termio_SETBAUD (B600);		break;
 2673    2   			case TT$C_BAUD_1200:	termio_SETBAUD (B1200);		break;
 2674    2   			case TT$C_BAUD_1800:	termio_SETBAUD (B1800);		break;
 2675    2   			case TT$C_BAUD_2000:	termio_SETBAUD (B38400);	break;	/* 2000 is invalid case */
 2676    2   			case TT$C_BAUD_2400:	termio_SETBAUD (B2400);		break;
 2677    2   			case TT$C_BAUD_3600:	termio_SETBAUD (B38400);	break;	/* 3600 is invalid case */
 2678    2   			case TT$C_BAUD_4800:	termio_SETBAUD (B4800);		break;
 2679    2   			case TT$C_BAUD_7200:	termio_SETBAUD (B38400);	break;	/* 7200 is invalid case */
 2680    2   			case TT$C_BAUD_9600:	termio_SETBAUD (B9600);		break;
 2681    2   			case TT$C_BAUD_19200:	termio_SETBAUD (B19200);	break;
 2682    2   			default:		termio_SETBAUD (B38400);	break;	/* all else is invalid case */
 2683    2   		}
 2684    1   		termio_RESETBITS (c_cflag, HUPCL);		/* These flags will toggle later if they need to. */
 2685    1   		termio_RESETBITS (c_cflag, CLOCAL);
 2686    1   		if (BTEST (term_char2, TT2$M_HANGUP))	termio_SETBITS (c_cflag, HUPCL);
 2687    1   		if (!BTEST (term_char, TT$M_MODEM))	termio_SETBITS (c_cflag, CLOCAL);
 2688    1   	 
 2689    1   			/* Set the appropriate termio line-discipline flags. */
 2690    1   		termio_RESETBITS (c_lflag, ECHO);		/* These flags will toggle later if they need to. */
 2691    1   		if (!BTEST (term_char, TT$M_NOECHO))	termio_SETBITS (c_lflag, ECHO);
 2692    1   	 
 2693    1   			/* Return success. */
 2694    1   		return (TRUE);
 2695    1   	}
 2696        	 
 2697        	 
 2698        	bool
 2699        	vms_TCSETA (index, arg)
 2700        		struct vms_term_data	*index;
 2701        		struct termio		*arg;
 2702        	{
 2703    1   	 	unsigned short int	func=0;			/* QIO function code and modifiers. */
 2704    1   		unsigned short int	chan;
 2705    1   		unsigned int		p1=0, p2=0, p3=0;	/* QIO funciton dependent parameters. */
 2706    1   		struct iosb_struct	iosb;			/* I/O status block for call to QIO. */
 2707    1   		bool			changes;		/* TRUE if VMS term. characteristics have changed. */
 2708    1   	 
 2709    1   		index->termio = arg;
 2710    1   	 
 2711    1   			/* Set the VMS control bits according to termio input flags. */
 2712    1   		if (termio_BTEST (c_iflag, ISTRIP) == BTEST (term_char, TT$M_EIGHTBIT))
 2713    1   			{ TOGGLEBITS (term_char, TT$M_EIGHTBIT);  changes = TRUE; }
 2714    1   		if (termio_BTEST (c_iflag, IXON) != BTEST (term_char, TT$M_TTSYNC))
 2715    1   			{ TOGGLEBITS (term_char, TT$M_TTSYNC);  changes = TRUE; }
 2716    1   		if (termio_BTEST (c_iflag, IXOFF) != BTEST (term_char, TT$M_HOSTSYNC))
 2717    1   			{ TOGGLEBITS (term_char, TT$M_HOSTSYNC);  changes = TRUE; }
 2718    1   		if (termio_BTEST (c_iflag, IUCLC) && !BTEST (term_char, TT$M_LOWER))
 2719    1   			{ SETBITS (term_char, TT$M_LOWER);  changes = TRUE; }

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 9
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2720    1   	 
 2721    1   			/* Set the VMS control bits according to termio output flags. */
 2722    1   		if (termio_BTEST (c_oflag, OPOST) == BTEST (term_char2, TT2$M_PASTHRU))
 2723    1   			{ TOGGLEBITS (term_char2, TT2$M_PASTHRU);  changes = TRUE; }
 2724    1   		if (!termio_BTEST (c_oflag, OLCUC) && !BTEST (term_char, TT$M_LOWER))
 2725    1   			{ SETBITS (term_char, TT$M_LOWER);  changes = TRUE; }
 2726    1   		if (termio_BTEST (c_oflag, TAB3) == BTEST (term_char, TT$M_MECHTAB))
 2727    1   			{ TOGGLEBITS (term_char, TT$M_MECHTAB);  changes = TRUE; }
 2728    1   	 
 2729    1   			/* Set the VMS control bits according to termio hardware flags. */
 2730    1   		switch (termio_BITS (c_cflag, CBAUD))
 2731    1   		{	case B0:	break;	/* This could possibly be used to cause a "hangup". */
 2732    2   			case B50:	if (!BAUD(TT$C_BAUD_50)) {SETBAUD (TT$C_BAUD_50); changes = TRUE;}	break;
 2733    2   			case B75:	if (!BAUD(TT$C_BAUD_75)) {SETBAUD (TT$C_BAUD_75); changes = TRUE;}	break;
 2734    2   			case B110:	if (!BAUD(TT$C_BAUD_110)) {SETBAUD (TT$C_BAUD_110); changes = TRUE;}	break;
 2735    2   			case B134:	if (!BAUD(TT$C_BAUD_134)) {SETBAUD (TT$C_BAUD_134); changes = TRUE;}	break;
 2736    2   			case B150:	if (!BAUD(TT$C_BAUD_150)) {SETBAUD (TT$C_BAUD_150); changes = TRUE;}	break;
 2737    2   			case B200:	ioctl_return (EINVAL);
 2738    2   			case B300:	if (!BAUD(TT$C_BAUD_300)) {SETBAUD (TT$C_BAUD_300); changes = TRUE;}	break;
 2739    2   			case B600:	if (!BAUD(TT$C_BAUD_600)) {SETBAUD (TT$C_BAUD_600); changes = TRUE;}	break;
 2740    2   			case B1200:	if (!BAUD(TT$C_BAUD_1200)) {SETBAUD (TT$C_BAUD_1200); changes = TRUE;}	break;
 2741    2   			case B1800:	if (!BAUD(TT$C_BAUD_1800)) {SETBAUD (TT$C_BAUD_1800); changes = TRUE;}	break;
 2742    2   			case B2400:	if (!BAUD(TT$C_BAUD_2400)) {SETBAUD (TT$C_BAUD_2400); changes = TRUE;}	break;
 2743    2   			case B4800:	if (!BAUD(TT$C_BAUD_4800)) {SETBAUD (TT$C_BAUD_4800); changes = TRUE;}	break;
 2744    2   			case B9600:	if (!BAUD(TT$C_BAUD_9600)) {SETBAUD (TT$C_BAUD_9600); changes = TRUE;}	break;
 2745    2   			case B19200:	if (!BAUD(TT$C_BAUD_19200)) {SETBAUD (TT$C_BAUD_19200); changes = TRUE;} break;
 2746    2   			case B38400:	break;	/* This is used for VMS speed that unix can't handle. */
 2747    2   			default:	ioctl_return (EINVAL);
 2748    2   		}
 2749    1   		if (termio_BTEST (c_cflag, HUPCL) != BTEST (term_char2, TT2$M_HANGUP))
 2750    1   			{ TOGGLEBITS (term_char2, TT2$M_HANGUP);  changes = TRUE; }
 2751    1   		if (termio_BTEST (c_cflag, CLOCAL) == BTEST (term_char, TT$M_MODEM))
 2752    1   			{ TOGGLEBITS (term_char, TT$M_MODEM);  changes = TRUE; }
 2753    1   	 
 2754    1   			/* Set the VMS control bits according to termio line-discipline flags. */
 2755    1   		if (termio_BTEST (c_lflag, ECHO) == BTEST (term_char, TT$M_NOECHO))
 2756    1   			{ TOGGLEBITS (term_char, TT$M_NOECHO);  changes = TRUE; }
 2757    1   	 
 2758    1   			/* Set the VMS terminal characteristics. */
 2759    1   	/*
 2760    1   	 * As it turns out, it may be important to set the terminal characteristics
 2761    1   	 * even if it looks like nothing has changed.  This is due to the fact that
 2762    1   	 * different I/O streams may access the same terminal.  You may have changed
 2763    1   	 * the attributes on stdout, thus changing the terminal characteristics for
 2764    1   	 * stdin and stderr.  These sorts of cross-stream changes are impossible to
 2765    1   	 * track, so I will always set the attributes based on the current values
 2766    1   	 * in "termio".  For this reason, the following line has been commented out!
 2767    1   	 *
 2768    1   		if (changes)
 2769    1   	 */
 2770    1   		{	func = IO$_SETMODE;			/* Set current terminal characteristics. */
 2771    2   			chan = index->vmstermio->chan;		/* Channel for this particular QIO. */
 2772    2   			p1 = &(index->vmstermio->char_buff);	/* Address of characteristics buffer. */
 2773    2   			p2 = 12;				/* Length of characteristics buffer. */
 2774    2   			p3 = index->vmstermio->baud;		/* The (possibly new) baud rate. */
 2775    2   			if ((vaxc$errno = sys$qiow (0, chan, func, &iosb, 0, 0, p1, p2, p3, 0, 0, 0)) != SS$_NORMAL)
 2776    2   			{	errno = EVMSERR;

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 10
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2777    3   				return (FALSE);
 2778    3   			}
 2779    2   			if ((vaxc$errno = iosb.cond) != SS$_NORMAL)
 2780    2   			{	errno = EVMSERR;
 2781    3   				return (FALSE);
 2782    3   			}
 2783    2   		}
 2784    1   	 
 2785    1   			/* Return success. */
 2786    1   		return (TRUE);
 2787    1   	}
 2788        	 
 2789        	 
 2790        	/*
 2791        	 *	This function causes the process to "hang" until all output to the
 2792        	 *	specified file gets written.  I don't see an immediate use for this
 2793        	 *	so it simply returns success.  I will let the device driver handle
 2794        	 *	queuing up output and stopping on its own if it needs to.
 2795        	 */
 2796        	bool
 2797        	vms_TCSBRK (index)
 2798        		struct vms_term_data	*index;
 2799        	{
 2800    1   		return (TRUE);
 2801    1   	}
 2802        	 
 2803        	 
 2804        	/*
 2805        	 *	This function controls XON/XOFF protocol by suspending/resuming output
 2806        	 *	on the output file based on the value 0/1 for arg.  Currently, I will
 2807        	 *	assume the VMS device driver will handle this and simply returns success;
 2808        	 *	when in "raw" mode...tough luck...handle it yourself or fix this code to
 2809        	 *	do it!
 2810        	 */
 2811        	bool
 2812        	vms_TCXONC (index, arg)
 2813        		struct vms_term_data	*index;
 2814        		int			arg;
 2815        	{
 2816    1   		if (arg != 0  &&  arg != 1)
 2817    1   			ioctl_return (EINVAL);
 2818    1   		return (TRUE);
 2819    1   	}
 2820        	 
 2821        	 
 2822        	/*
 2823        	 *	This routine has three functions flush input/flush output/flush both based
 2824        	 *	on the value of 0/1/2 for arg.
 2825        	 */
 2826        	bool
 2827        	vms_TCFLSH (index, arg)
 2828        		struct vms_term_data	*index;
 2829        		int			arg;
 2830        	{
 2831    1   		switch (arg)
 2832    1   		{	case 0:
 2833    2   				return ( gvg$do_flush_read (index) );

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 11
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2834    2   				break;
 2835    2   			case 1:
 2836    2   				return ( gvg$do_flush_write (index) );
 2837    2   				break;
 2838    2   			case 2:
 2839    2   				return ( gvg$do_flush_read (index) &&
 2840    2   					 gvg$do_flush_write (index) );
 2841    2   				break;
 2842    2   			default:
 2843    2   				ioctl_return (EINVAL);
 2844    2   		}
 2845    1   	}
 2846        	 
 2847        	 
 2848        	vms_dup012 (fd)
 2849        		int	fd;	/* File descriptor to be duplicated. */
 2850        	{	
 2851    1   		struct vms_term_data	*ptr, *back_ptr, *save_ptr;	/* Misc. pointers. */
 2852    1   		int			fdA,fdB;			/* File descr. that need duplication. */
 2853    1   	 
 2854    1   			/* Get file descriptors to duplicate to. */
 2855    1   		switch (fd)
 2856    1   		{	case 0:		fdA = 1;  fdB = 2;	break;
 2857    2   			case 1:		fdA = 0;  fdB = 2;	break;
 2858    2   			case 2: 	fdA = 0;  fdB = 1;	break;
 2859    2   			default:	return(0);
 2860    2   		}
 2861    1   	 
 2862    1   			/* Get the pointer to the structure for file descriptor 0. */
 2863    1   		for (save_ptr=0, ptr=vms_term_data_head;  ptr;  ptr=ptr->next)
 2864    1   			if (ptr->fildes == fd)
 2865    1   			{	save_ptr = ptr;
 2866    2   				break;
 2867    2   			}
 2868    1   	 
 2869    1   			/* If no fd on list, just return. */
 2870    1   		if (!save_ptr)
 2871    1   			return (0);
 2872    1   	 
 2873    1   			/* Find fd A if there is one! */
 2874    1   		for (ptr=vms_term_data_head;  ptr;  ptr=ptr->next)
 2875    1   			if (ptr->fildes == fdA)
 2876    1   				break;
 2877    1   	 
 2878    1   			/* If it's out there, merely swap existing pointers.  Note, in
 2879    1   			   this case, I don't even use the default structures.  Note
 2880    1   			   also that I don't free the old pointer to vmstermio if it
 2881    1   			   was there.  This is because it is possible that somewhere
 2882    1   			   there is still a pointer to that data area.  If I were to
 2883    1   			   free that memory, the next time that data area is accessed
 2884    1   			   they could get an access violation.  Better to waste memory
 2885    1   			   than screw someone over later! */
 2886    1   		if (ptr)
 2887    1   		{	ptr->vmstermio = save_ptr->vmstermio;
 2888    2   			ptr->termio = save_ptr->termio;
 2889    2   			ptr->_iobuf = IO_POINTER[fdA+1];
 2890    2   			ptr->active = TRUE;

GVG$IOCTL                                                       30-MAR-1989 15:51:10    VAX C      V2.2-015                 Page 12
V1.0                                                            30-MAR-1989 15:48:45    GVG$IOCTL.C;1 (1)

 2891    2   			save_ptr = ptr;		/* I want to chain fd B onto fd A. */
 2892    2   		}
 2893    1   		else
 2894    1   		{	def1_vms_term_data = *save_ptr;
 2895    2   			def1_vms_term_data.fildes = fdA;
 2896    2   			def1_vms_term_data._iobuf = IO_POINTER[fdA+1];
 2897    2   			def1_vms_term_data.active = TRUE;
 2898    2   			save_ptr->next = &def1_vms_term_data;
 2899    2   			save_ptr = &def1_vms_term_data;		/* I want to chain fd B onto fd A. */
 2900    2   		}
 2901    1   	 
 2902    1   			/* Find fd B if there is one! */
 2903    1   		for (ptr=vms_term_data_head;  ptr;  ptr=ptr->next)
 2904    1   			if (ptr->fildes == fdB)
 2905    1   				break;
 2906    1   	 
 2907    1   			/* If it's out there, merely swap existing pointers.  Note, in
 2908    1   				this case, I don't even use the default structures. */
 2909    1   		if (ptr)
 2910    1   		{	ptr->vmstermio = save_ptr->vmstermio;
 2911    2   			ptr->termio = save_ptr->termio;
 2912    2   			ptr->_iobuf = IO_POINTER[fdB+1];
 2913    2   			ptr->active = TRUE;
 2914    2   		}
 2915    1   		else
 2916    1   		{	def2_vms_term_data = *save_ptr;
 2917    2   			def2_vms_term_data.fildes = fdB;
 2918    2   			def2_vms_term_data._iobuf = IO_POINTER[fdB+1];
 2919    2   			def2_vms_term_data.active = TRUE;
 2920    2   			save_ptr->next = &def2_vms_term_data;
 2921    2   		}
 2922    1   	}

 
 
Command Line
------------
 
CC/LIST GVG$IOCTL.C+IOCTL.C

