Example #1
0
void iott_close(io_desc *v, mval *pp)
{
	d_tt_struct	*ttptr;
	params		ch;
	int		status;
	int		p_offset;
	boolean_t	ch_set;

	assert(v->type == tt);
	if (v->state != dev_open)
		return;
	ESTABLISH_GTMIO_CH(&v->pair, ch_set);
	iott_flush(v);
	if (v->pair.in != v)
		assert(v->pair.out == v);
	ttptr = (d_tt_struct *)v->dev_sp;
	if (v->pair.out != v)
		assert(v->pair.in == v);
	v->state = dev_closed;
	resetterm(v);

	p_offset = 0;
	while (*(pp->str.addr + p_offset) != iop_eol)
	{
		if ((ch = *(pp->str.addr + p_offset++)) == iop_exception)
		{
			v->error_handler.len = *(pp->str.addr + p_offset);
			v->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
			s2pool(&v->error_handler);
		}
		p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
			(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
	}
	if (v == io_std_device.in || (v == io_std_device.out))
	{
		REVERT_GTMIO_CH(&v->pair, ch_set);
		return;
	}

	CLOSEFILE_RESET(ttptr->fildes, status);	/* resets "ttptr->fildes" to FD_INVALID */
	if (0 != status)
	{
		assert(status == errno);
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
				RTS_ERROR_LITERAL("iott_close(CLOSEFILE)"), CALLFROM, status);
	}
	if (ttptr->recall_buff.addr)
	{
		free(ttptr->recall_buff.addr);
		ttptr->recall_buff.addr = NULL;
	}
	REVERT_GTMIO_CH(&v->pair, ch_set);
	return;
}
Example #2
0
void outofband_action(bool lnfetch_or_start)
{
	error_def(ERR_CTRAP);
	error_def(ERR_CTRLC);
	error_def(ERR_CTRLY);
	error_def(ERR_JOBINTRRQST);

	if (outofband)
	{
		if (io_std_device.in->type == tt)
			iott_flush(io_std_device.in);
		if (lnfetch_or_start)
		{
			restart_pc = (int) frame_pointer->mpc;
			restart_ctxt = frame_pointer->ctxt;
		}

		switch(outofband)
		{
			case (ctrly):
				rts_error(VARLSTCNT(1) ERR_CTRLY);
				break;
			case (ctrlc):
				rts_error(VARLSTCNT(1) ERR_CTRLC);
				break;
			case (ctrap):
				rts_error(VARLSTCNT(3) ERR_CTRAP, 1, ctrap_action_is);
				break;
			case (tptimeout):
				/*
				 * Currently following is nothing but an rts_error.
				 * Function pointer is used flexibility.
				 */
				(*tp_timeout_action_ptr)();
				break;
			case (jobinterrupt):
				rts_error(VARLSTCNT(1) ERR_JOBINTRRQST);
				break;
			default:
				GTMASSERT;
				break;
		}
	}
}
Example #3
0
void dm_read(mval *v)
{
	boolean_t	done;
	unsigned short	iosb[4];
	int		cl, index;
	uint4		max_width, save_modifiers, save_term_msk, status;
	read_iosb	stat_blk;
	io_desc		*io_ptr;
	t_cap		s_mode;
	d_tt_struct	*tt_ptr;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	if (tt == io_curr_device.out->type)
		iott_flush(io_curr_device.out);
	if (!comline_base)
	{
		comline_base = malloc(MAX_RECALL * SIZEOF(mstr));
		memset(comline_base, 0, (MAX_RECALL * SIZEOF(mstr)));
	}
	io_ptr = io_curr_device.in;
	assert(tt == io_ptr->type);
	assert(dev_open == io_ptr->state);
	if (io_ptr->dollar.zeof)
		op_halt();
	if (outofband)
	{
		outofband_action(FALSE);
		assert(FALSE);
	}
	tt_ptr = (d_tt_struct *)io_ptr->dev_sp;
	max_width = (io_ptr->width > tt_ptr->in_buf_sz) ? io_ptr->width : tt_ptr->in_buf_sz;
	assert(stringpool.free >= stringpool.base);
	assert(stringpool.free <= stringpool.top);
	ENSURE_STP_FREE_SPACE(max_width);
	active_device = io_ptr;
	index = 0;
	/* the following section of code puts the terminal in "easy of use" mode */
	status = sys$qiow(EFN$C_ENF, tt_ptr->channel, IO$_SENSEMODE,
		&stat_blk, 0, 0, &s_mode, 12, 0, 0, 0, 0);
	if (SS$_NORMAL == status)
		status = stat_blk.status;
	if (SS$_NORMAL != status)
		rts_error(VARLSTCNT(1) status);
	if ((s_mode.ext_cap & TT2$M_PASTHRU) ||
		!(s_mode.ext_cap & TT2$M_EDITING) ||
		!(s_mode.term_char & TT$M_ESCAPE) ||
		!(s_mode.term_char & TT$M_TTSYNC))
	{
		s_mode.ext_cap &= (~TT2$M_PASTHRU);
		s_mode.ext_cap |= TT2$M_EDITING;
		s_mode.term_char |= (TT$M_ESCAPE | TT$M_TTSYNC);
		status = sys$qiow(EFN$C_ENF, tt_ptr->channel,
			IO$_SETMODE, &stat_blk, 0, 0, &s_mode, 12, 0, 0, 0, 0);
		if (SS$_NORMAL == status)
			status = stat_blk.status;
		if (SS$_NORMAL != status)
			/* The following error is probably going to cause the terminal state to get mucked up */
			rts_error(VARLSTCNT(1) status);
		/* the following flag is normally used by iott_rdone, iott_readfl and iott_use but dm_read resets it when done */
		tt_ptr->term_chars_twisted = TRUE;
	}
	save_modifiers = (unsigned)tt_ptr->item_list[0].addr;
	tt_ptr->item_list[0].addr = (unsigned)tt_ptr->item_list[0].addr | TRM$M_TM_NORECALL & (~TRM$M_TM_NOECHO);
	tt_ptr->item_list[1].addr = NO_M_TIMEOUT;			/* reset key click timeout */
	save_term_msk = ((io_termmask *)tt_ptr->item_list[2].addr)->mask[0];
	((io_termmask *)tt_ptr->item_list[2].addr)->mask[0] = TERM_MSK | (SHFT_MSK << CTRL_B) | (SHFT_MSK << CTRL_Z);
	tt_ptr->item_list[4].buf_len = (TREF(gtmprompt)).len;
	do
	{
		done = TRUE;
		assert(0 <= index && index <= MAX_RECALL + 1);
		cl = clmod(comline_index - index);
		if ((0 == index) || (MAX_RECALL + 1 == index))
			tt_ptr->item_list[5].buf_len	= 0;
		else
		{
			tt_ptr->item_list[5].buf_len	= comline_base[cl].len;
			tt_ptr->item_list[5].addr	= comline_base[cl].addr;
		}
		status = sys$qiow(EFN$C_ENF, tt_ptr->channel, tt_ptr->read_mask, &stat_blk, 0, 0,
			stringpool.free, tt_ptr->in_buf_sz, 0, 0, tt_ptr->item_list, 6 * SIZEOF(item_list_struct));
		if (outofband)
			break;
		if (SS$_NORMAL != status)
		{
			if (io_curr_device.in == io_std_device.in && io_curr_device.out == io_std_device.out)
			{
				if (prin_in_dev_failure)
					sys$exit(status);
				else
					prin_in_dev_failure = TRUE;
			}
			break;
		}
		if (stat_blk.term_length > ESC_LEN - 1)
		{
			stat_blk.term_length = ESC_LEN - 1;
			if (SS$_NORMAL == stat_blk.status)
				stat_blk.status = SS$_PARTESCAPE;
		}
		if (SS$_NORMAL != stat_blk.status)
		{
			if (ctrlu_occurred)
			{
				index = 0;
				done = FALSE;
				ctrlu_occurred = FALSE;
				iott_wtctrlu(stat_blk.char_ct + (TREF(gtmprompt)).len, io_ptr);
			} else
			{
				status = stat_blk.status;
				break;
			}
		} else
		{
			if ((CTRL_B == stat_blk.term_char) ||
				(stat_blk.term_length == tt_ptr->key_up_arrow.len &&
				!memcmp(tt_ptr->key_up_arrow.addr, stringpool.free + stat_blk.char_ct,
				tt_ptr->key_up_arrow.len)))
			{
				done = FALSE;
				if ((MAX_RECALL + 1 != index) && (comline_base[cl].len || !index))
					index++;
			} else
			{
				if (stat_blk.term_length == tt_ptr->key_down_arrow.len &&
					!memcmp(tt_ptr->key_down_arrow.addr, stringpool.free + stat_blk.char_ct,
					tt_ptr->key_down_arrow.len))
				{
					done = FALSE;
					if (index)
						--index;
				}
			}
			if (!done)
			{
				status = sys$qiow(EFN$C_ENF, tt_ptr->channel,
					IO$_WRITEVBLK, &iosb, NULL, 0,
					tt_ptr->erase_to_end_line.addr, tt_ptr->erase_to_end_line.len,
					0, CCRECALL, 0, 0);
			} else
			{
				if (stat_blk.char_ct > 0
					&& (('R' == *stringpool.free) || ('r' == *stringpool.free)) &&
					(TRUE == m_recall(stat_blk.char_ct, stringpool.free, &index, tt_ptr->channel)))
				{
					assert(-1 <= index && index <= MAX_RECALL);
					done = FALSE;
					flush_pio();
					status = sys$qiow(EFN$C_ENF, tt_ptr->channel,
						IO$_WRITEVBLK, &iosb, NULL, 0,
						0, 0, 0, CCPROMPT, 0, 0);
					if ((-1 == index) || (CTRL_Z == stat_blk.term_char))
						index = 0;
				}
			}
			if (!done)
			{
				if (SS$_NORMAL == status)
					status = iosb[0];
				if (SS$_NORMAL != status)
					break;
			} else
			{
				if (CTRL_Z == stat_blk.term_char)
					io_curr_device.in->dollar.zeof = TRUE;
			}
		}
	} while (!done);
	/* put the terminal back the way the user had it set up */
	tt_ptr->item_list[0].addr = save_modifiers;
	((io_termmask *)tt_ptr->item_list[2].addr)->mask[0] = save_term_msk;
	if (tt_ptr->term_chars_twisted)
	{
		s_mode.ext_cap &= (~TT2$M_PASTHRU & ~TT2$M_EDITING);
		s_mode.ext_cap |= (tt_ptr->ext_cap & (TT2$M_PASTHRU | TT2$M_EDITING));
		s_mode.term_char &= (~TT$M_ESCAPE);
		s_mode.term_char |= (tt_ptr->term_char & TT$M_ESCAPE);
		status = sys$qiow(EFN$C_ENF, tt_ptr->channel,
			IO$_SETMODE, iosb, 0, 0, &s_mode, 12, 0, 0, 0, 0);
		if (SS$_NORMAL == status)
			status = iosb[0];
		tt_ptr->term_chars_twisted = FALSE;
	}
	if (SS$_NORMAL != status)
		rts_error(VARLSTCNT(1) status);
	if (outofband)
	{
		/* outofband not going to help more than a error so it's checked 2nd */
		outofband_action(FALSE);
		assert(FALSE);
	}
	v->mvtype = MV_STR;
	v->str.len = stat_blk.char_ct;
	v->str.addr = stringpool.free;
	if (stat_blk.char_ct)
	{
		cl = clmod(comline_index - 1);
		if (stat_blk.char_ct != comline_base[cl].len || memcmp(comline_base[cl].addr, stringpool.free, stat_blk.char_ct))
		{
			comline_base[comline_index] = v->str;
			comline_index = clmod(comline_index + 1);
		}
		stringpool.free += stat_blk.char_ct;
	}
	assert(stringpool.free <= stringpool.top);
	if ((io_ptr->dollar.x += stat_blk.char_ct) > io_ptr->width && io_ptr->wrap)
	{
		/* dm_read doesn't maintain the other io status isv's,
		 but it does $x and $y so the user can find out where they wound up */
		io_ptr->dollar.y += io_ptr->dollar.x / io_ptr->width;
		if (io_ptr->length)
			io_ptr->dollar.y %= io_ptr->length;
		io_ptr->dollar.x %= io_ptr->width;
	}
	active_device = 0;
}
Example #4
0
short	iott_readfl (mval *v, int4 length, int4 timeout)	/* timeout in seconds */
{
	boolean_t	ret, nonzerotimeout, timed;
	uint4		mask;
	unsigned char	inchar, *temp;
#ifdef __MVS__
	unsigned char	asc_inchar;
#endif
	int		dx, msk_in, msk_num, outlen, rdlen, save_errno, selstat, status, width;
	int4		msec_timeout;			/* timeout in milliseconds */
	io_desc		*io_ptr;
	d_tt_struct	*tt_ptr;
	io_terminator	outofbands;
	io_termmask	mask_term;
	unsigned char	*zb_ptr, *zb_top;
	ABS_TIME	cur_time, end_time;
	fd_set		input_fd;
	struct timeval	input_timeval;
	struct timeval	save_input_timeval;

	error_def(ERR_CTRAP);
	error_def(ERR_IOEOF);
	error_def(ERR_NOPRINCIO);

	assert(stringpool.free >= stringpool.base);
	assert(stringpool.free <= stringpool.top);
	io_ptr = io_curr_device.in;
	tt_ptr = (d_tt_struct *)(io_ptr->dev_sp);
	assert(dev_open == io_ptr->state);
	iott_flush(io_curr_device.out);
	width = io_ptr->width;
	if (stringpool.free + length > stringpool.top)
		stp_gcol (length);
	outlen = 0;
	/* ---------------------------------------------------------
	 * zb_ptr is be used to fill-in the value of $zb as we go
	 * If we drop-out with error or otherwise permaturely,
	 * consider $zb to be null.
	 * ---------------------------------------------------------
	 */
	zb_ptr = io_ptr->dollar.zb;
	zb_top = zb_ptr + sizeof(io_ptr->dollar.zb) - 1;
	*zb_ptr = 0;
	io_ptr->esc_state = START;
	io_ptr->dollar.za = 0;
	io_ptr->dollar.zeof = FALSE;
	v->str.len = 0;
	dx = (int)io_ptr->dollar.x;
	ret = TRUE;
	temp = stringpool.free;
	mask = tt_ptr->term_ctrl;
	mask_term = tt_ptr->mask_term;
	if (mask & TRM_NOTYPEAHD)
		TCFLUSH(tt_ptr->fildes, TCIFLUSH, status);
	if (mask & TRM_READSYNC)
	{
		DOWRITERC(tt_ptr->fildes, &dc1, 1, status);
		if (0 != status)
		{
			io_ptr->dollar.za = 9;
			rts_error(VARLSTCNT(1) status);
		}
	}
	nonzerotimeout = FALSE;
	if (NO_M_TIMEOUT == timeout)
	{
		timed = FALSE;
		input_timeval.tv_sec = 100;
		msec_timeout = NO_M_TIMEOUT;
	} else
	{
		timed = TRUE;
		input_timeval.tv_sec = timeout;
		msec_timeout = timeout2msec(timeout);
		if (!msec_timeout)
			iott_mterm(io_ptr);
		else
		{
			nonzerotimeout = TRUE;
   			sys_get_curr_time(&cur_time);
			add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
		}
	}
	input_timeval.tv_usec = 0;
	do
	{
		if (outofband)
		{
			outlen = 0;
			if (!msec_timeout)
				iott_rterm(io_ptr);
			outofband_action(FALSE);
			break;
		}
		errno = 0;
		FD_ZERO(&input_fd);
		FD_SET(tt_ptr->fildes, &input_fd);
		assert(0 != FD_ISSET(tt_ptr->fildes, &input_fd));
		/* the checks for EINTR below are valid and should not be converted to EINTR
		 * wrapper macros, since the select/read is not retried on EINTR.
		 */
		save_input_timeval = input_timeval;	/* take a copy and pass it because select() below might change it */
		selstat = select(tt_ptr->fildes + 1, (void *)&input_fd, (void *)NULL, (void *)NULL, &save_input_timeval);
		if (selstat < 0)
		{
			if (EINTR != errno)
				goto term_error;
		} else if (0 == selstat)
		{
			if (timed)
			{
				ret = FALSE;
				break;
			}
			continue;	/* select() timeout; keep going */
		} else if (0 < (rdlen = read(tt_ptr->fildes, &inchar, 1)))	/* This read is protected */
		{
			assert(0 != FD_ISSET(tt_ptr->fildes, &input_fd));
			/* --------------------------------------------------
			 * set prin_in_dev_failure to FALSE to indicate that
			 * input device is working now.
			 * --------------------------------------------------
			 */
			prin_in_dev_failure = FALSE;
			if (tt_ptr->canonical)
			{
				if (0 == inchar)
				{
					/* --------------------------------------
					 * This means that the device has hungup
					 * --------------------------------------
					 */
					io_ptr->dollar.zeof = TRUE;
					io_ptr->dollar.x = 0;
					io_ptr->dollar.za = 9;
					io_ptr->dollar.y++;
					if (io_ptr->error_handler.len > 0)
						rts_error(VARLSTCNT(1) ERR_IOEOF);
					break;
				} else
					io_ptr->dollar.zeof = FALSE;
			}
			if (mask & TRM_CONVERT)
				NATIVE_CVT2UPPER(inchar, inchar);
                        GETASCII(asc_inchar,inchar);
			if ((dx >= width) && io_ptr->wrap && !(mask & TRM_NOECHO))
			{
				DOWRITE(tt_ptr->fildes, NATIVE_TTEOL, strlen(NATIVE_TTEOL));
				dx = 0;
			}
			if ((' ' > INPUT_CHAR) && (tt_ptr->enbld_outofbands.mask & (1 << INPUT_CHAR)))
			{
				outlen = 0;
				io_ptr->dollar.za = 9;
				std_dev_outbndset(INPUT_CHAR);	/* it needs ASCII?	*/
				outofband = 0;
				if (!msec_timeout)
					iott_rterm(io_ptr);
				rts_error(VARLSTCNT(3) ERR_CTRAP, 1, ctrap_action_is);
				break;
			}
			if ((0 != (mask & TRM_ESCAPE))
			     && ((NATIVE_ESC == inchar) || (START != io_ptr->esc_state)))
			{
				if (zb_ptr >= zb_top)
				{	/* $zb overflow */
					io_ptr->dollar.za = 2;
					break;
				}
				*zb_ptr++ = inchar;
				iott_escape(zb_ptr - 1, zb_ptr, io_ptr);
				*(zb_ptr - 1) = INPUT_CHAR;     /* need to store ASCII value    */
				if (FINI == io_ptr->esc_state)
					break;
				if (BADESC == io_ptr->esc_state)
				{	/* Escape sequence failed parse */
					io_ptr->dollar.za = 2;
					break;
				}
				/* --------------------------------------------------------------------
				 * In escape sequence...do not process further, but get next character
				 * --------------------------------------------------------------------
				 */
			} else
			{	/* SIMPLIFY THIS! */
				msk_num = (uint4)INPUT_CHAR / NUM_BITS_IN_INT4;
				msk_in = (1 << ((uint4)INPUT_CHAR % NUM_BITS_IN_INT4));
				if (msk_in & mask_term.mask[msk_num])
				{
					*zb_ptr++ = INPUT_CHAR;
					break;
				}
				if (((int)inchar == tt_ptr->ttio_struct->c_cc[VERASE]) && !(mask & TRM_PASTHRU))
				{
					if ((0< outlen) && (0 < dx))
					{
						outlen--;
						dx--;
						*temp--;
						if (!(mask & TRM_NOECHO))
						{
							DOWRITERC(tt_ptr->fildes, eraser, sizeof(eraser), status);
							if (0 != status)
								goto term_error;
						}
					}
				} else
				{
					if (!(mask & TRM_NOECHO))
					{
						DOWRITERC(tt_ptr->fildes, &inchar, 1, status);
						if (0 != status)
							goto term_error;
					}
					*temp++ = inchar;
					outlen++;
					dx++;
				}
			}
		} else if (0 == rdlen)
		{
			if (0 < selstat)
			{	/* this should be the only possibility */
				io_ptr->dollar.zeof = TRUE;
				io_ptr->dollar.x = 0;
				io_ptr->dollar.za = 0;
				io_ptr->dollar.y++;
				if (io_curr_device.in == io_std_device.in)
				{
					if (!prin_in_dev_failure)
						prin_in_dev_failure = TRUE;
					else
					{
                                        	send_msg(VARLSTCNT(1) ERR_NOPRINCIO);
                                        	stop_image_no_core();
					}
                                }
				if (io_ptr->dollar.zeof)
				{
					io_ptr->dollar.za = 9;
					rts_error(VARLSTCNT(1) ERR_IOEOF);
				} else
				{
					io_ptr->dollar.zeof = TRUE;
					io_ptr->dollar.za = 0;
					if (0 < io_ptr->error_handler.len)
						rts_error(VARLSTCNT(1) ERR_IOEOF);
				}
				break;
			}
			if (0 == errno)
			{	/* eof */
				io_ptr->dollar.zeof = TRUE;
				io_ptr->dollar.x = 0;
				io_ptr->dollar.za = 0;
				io_ptr->dollar.y++;
				if (0 < io_ptr->error_handler.len)
					rts_error(VARLSTCNT(1) ERR_IOEOF);
				break;
			}
		} else if (EINTR != errno)	/* rdlen < 0 */
			goto term_error;
		if (nonzerotimeout)
		{
			sys_get_curr_time(&cur_time);
			cur_time = sub_abs_time(&end_time, &cur_time);
			if (0 > cur_time.at_sec)
			{
				ret = FALSE;
				break;
			}
			input_timeval.tv_sec = cur_time.at_sec;
			input_timeval.tv_usec = cur_time.at_usec;
		}
	} while (outlen < length);
	*zb_ptr++ = 0;
	if (!msec_timeout)
	{
		iott_rterm(io_ptr);
		if (0 == outlen)
			ret = FALSE;
	}
	if (mask & TRM_READSYNC)
	{
		DOWRITERC(tt_ptr->fildes, &dc3, 1, status);
		if (0 != status)
		{
			io_ptr->dollar.za = 9;
			rts_error(VARLSTCNT(1) status);
		}
	}
	if (outofband)
	{
		v->str.len = 0;
		io_ptr->dollar.za = 9;
		return(FALSE);
	}
	v->str.len = outlen;
	v->str.addr = (char *)stringpool.free;
	if (!(mask & TRM_NOECHO))
	{
		if ((io_ptr->dollar.x += v->str.len) >= io_ptr->width && io_ptr->wrap)
		{
			io_ptr->dollar.y += (io_ptr->dollar.x / io_ptr->width);
			if (io_ptr->length)
				io_ptr->dollar.y %= io_ptr->length;
			io_ptr->dollar.x %= io_ptr->width;
			if (0 == io_ptr->dollar.x)
				DOWRITE(tt_ptr->fildes, NATIVE_TTEOL, strlen(NATIVE_TTEOL));
		}
	}
	return ((short)ret);

term_error:
	save_errno = errno;
	io_ptr->dollar.za = 9;
	if (!msec_timeout)
		iott_rterm(io_ptr);
	rts_error(VARLSTCNT(1) save_errno);
	return FALSE;
}
Example #5
0
void iott_use(io_desc *iod, mval *pp)
{
	boolean_t		flush_input;
	char			dc1, *ttab;
	d_tt_struct		*temp_ptr, *tt_ptr;
	int			p_offset, fil_type, save_errno, status;
	int4			length, width;
	io_desc			*d_in, *d_out;
	io_termmask		mask_term;
	struct sigaction	act;
	struct termios		t;
	uint4			mask_in;
	unsigned char		ch, len;
	boolean_t		ch_set;

	p_offset = 0;
	assert(iod->state == dev_open);
	ESTABLISH_GTMIO_CH(&iod->pair, ch_set);
	iott_flush(iod);
	tt_ptr = (d_tt_struct *)iod->dev_sp;
	if (*(pp->str.addr + p_offset) != iop_eol)
	{
		if (tt_ptr->mupintr)
			if (dollar_zininterrupt)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO);
			else
			{	/* The interrupted read was not properly resumed so clear it now */
				tt_ptr->mupintr = FALSE;
				tt_ptr->tt_state_save.who_saved = ttwhichinvalid;
				io_find_mvstent(iod, TRUE);
			}
		status = tcgetattr(tt_ptr->fildes, &t);
		if (0 != status)
		{
			save_errno = errno;
			ISSUE_NOPRINCIO_IF_NEEDED_TT(io_curr_device.out);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TCGETATTR, 1, tt_ptr->fildes, save_errno);
		}
		flush_input = FALSE;
		d_in = iod->pair.in;
		d_out = iod->pair.out;
		temp_ptr = (d_tt_struct *)d_in->dev_sp;
		mask_in = temp_ptr->term_ctrl;
		mask_term = temp_ptr->mask_term;
		while (*(pp->str.addr + p_offset) != iop_eol)
		{
			switch (ch = *(pp->str.addr + p_offset++))
			{
				case iop_canonical:
					tt_ptr->canonical = TRUE;
					t.c_lflag |= ICANON;
					break;
				case iop_nocanonical:
					tt_ptr->canonical = FALSE;
					t.c_lflag &= ~(ICANON);
					break;
				case iop_empterm:
					tt_ptr->ext_cap |= TT_EMPTERM;
					break;
				case iop_noempterm:
					tt_ptr->ext_cap &= ~TT_EMPTERM;
					break;
				case iop_cenable:
					if (!ctrlc_on)
					{	/* if it's already cenable, no need to change */
						temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
						if (tt_ptr->fildes == temp_ptr->fildes)
						{	/* if this is $PRINCIPAL make sure the ctrlc_handler is enabled */
							sigemptyset(&act.sa_mask);
							act.sa_flags = 0;
							act.sa_handler = ctrlc_handler_ptr;
							sigaction(SIGINT, &act, 0);
							ctrlc_on = TRUE;
						}
					}
					break;
				case iop_nocenable:
					if (ctrlc_on)
					{	/* if it's already nocenable, no need to change */
						temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
						if (tt_ptr->fildes == temp_ptr->fildes)
						{	/* if this is $PRINCIPAL may disable the ctrlc_handler */
							if (0 == (CTRLC_MSK & tt_ptr->enbld_outofbands.mask))
							{	/* but only if ctrap=$c(3) is not active */
								sigemptyset(&act.sa_mask);
								act.sa_flags = 0;
								act.sa_handler = SIG_IGN;
								sigaction(SIGINT, &act, 0);
							}
							ctrlc_on = FALSE;
						}
					}
					break;
				case iop_clearscreen:
					if (NULL != CLR_EOS)
						gtm_tputs(CLR_EOS, 1, outc);
					break;
				case iop_convert:
					mask_in |= TRM_CONVERT;
					break;
				case iop_noconvert:
					mask_in &= ~TRM_CONVERT;
					break;
				case iop_ctrap:
					GET_LONG(tt_ptr->enbld_outofbands.mask, pp->str.addr + p_offset);
					if (!ctrlc_on)
					{	/* if cenable, ctrlc_handler active anyway, otherwise, depends on ctrap=$c(3) */
						sigemptyset(&act.sa_mask);
						act.sa_flags = 0;
						act.sa_handler = (CTRLC_MSK & tt_ptr->enbld_outofbands.mask)
							? ctrlc_handler_ptr : SIG_IGN;
						sigaction(SIGINT, &act, 0);
					}
					break;
				case iop_downscroll:
					if (d_out->dollar.y > 0)
					{
						d_out->dollar.y--;
						if (NULL != CURSOR_ADDRESS)
							gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1,
								  outc);
					}
					break;
				case iop_echo:
					mask_in &= (~TRM_NOECHO);
					break;
				case iop_noecho:
					mask_in |= TRM_NOECHO;
					break;
				case iop_editing:
					if (io_curr_device.in == io_std_device.in)
					{	/* $PRINCIPAL only */
						tt_ptr->ext_cap |= TT_EDITING;
						if (!tt_ptr->recall_buff.addr)
						{
							assert(tt_ptr->in_buf_sz);
							tt_ptr->recall_buff.addr = malloc(tt_ptr->in_buf_sz);
							tt_ptr->recall_size = tt_ptr->in_buf_sz;
							tt_ptr->recall_buff.len = 0;    /* nothing in buffer */
						}
					}
					break;
				case iop_noediting:
					if (io_curr_device.in == io_std_device.in)
						tt_ptr->ext_cap &= ~TT_EDITING;	/* $PRINCIPAL only */
					break;
				case iop_escape:
					mask_in |= TRM_ESCAPE;
					break;
				case iop_noescape:
					mask_in &= (~TRM_ESCAPE);
					default:
					break;
				case iop_eraseline:
					if (NULL != CLR_EOL)
						gtm_tputs(CLR_EOL, 1, outc);
					break;
				case iop_exception:
					iod->error_handler.len = *(pp->str.addr + p_offset);
					iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1);
					s2pool(&iod->error_handler);
					break;
				case iop_filter:
					len = *(pp->str.addr + p_offset);
					ttab = pp->str.addr + p_offset + 1;
					if ((fil_type = namelook(filter_index, filter_names, ttab, len)) < 0)
					{
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TTINVFILTER);
						return;
					}
					switch (fil_type)
					{
					case 0:
						iod->write_filter |= CHAR_FILTER;
						break;
					case 1:
						iod->write_filter |= ESC1;
						break;
					case 2:
						iod->write_filter &= ~CHAR_FILTER;
						break;
					case 3:
						iod->write_filter &= ~ESC1;
						break;
					}
					break;
				case iop_nofilter:
					iod->write_filter = 0;
					break;
				case iop_flush:
					flush_input = TRUE;
					break;
				case iop_hostsync:
					t.c_iflag |= IXOFF;
					break;
				case iop_nohostsync:
					t.c_iflag &= ~IXOFF;
					break;
				case iop_insert:
					if (io_curr_device.in == io_std_device.in)
						tt_ptr->ext_cap &= ~TT_NOINSERT;	/* $PRINCIPAL only */
					break;
				case iop_noinsert:
					if (io_curr_device.in == io_std_device.in)
						tt_ptr->ext_cap |= TT_NOINSERT;	/* $PRINCIPAL only */
					break;
				case iop_length:
					GET_LONG(length, pp->str.addr + p_offset);
					if (0 > length)
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG);
					d_out->length = length;
					break;
				case iop_pasthru:
					mask_in |= TRM_PASTHRU;
					break;
				case iop_nopasthru:
					mask_in &= (~TRM_PASTHRU);
					break;
				case iop_readsync:
					mask_in |= TRM_READSYNC;
					break;
				case iop_noreadsync:
					dc1 = (char)17;
					temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp;
					DOWRITERC(temp_ptr->fildes, &dc1, 1, status);
					if (0 != status)
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status);
					mask_in &= (~TRM_READSYNC);
					break;
				case iop_terminator:
					memcpy(&mask_term.mask[0], (pp->str.addr + p_offset), SIZEOF(io_termmask));
					temp_ptr = (d_tt_struct *)d_in->dev_sp;
					if (mask_term.mask[0] == NUL &&
						mask_term.mask[1] == NUL &&
						mask_term.mask[2] == NUL &&
						mask_term.mask[3] == NUL &&
						mask_term.mask[4] == NUL &&
						mask_term.mask[5] == NUL &&
						mask_term.mask[6] == NUL &&
						mask_term.mask[7] == NUL)
					{
						temp_ptr->default_mask_term = TRUE;
						if (CHSET_UTF8 == d_in->ichset)
						{
							mask_term.mask[0] = TERM_MSK_UTF8_0;
							mask_term.mask[4] = TERM_MSK_UTF8_4;
						} else
							mask_term.mask[0] = TERM_MSK;
					} else
						temp_ptr->default_mask_term = FALSE;
						break;
				case iop_noterminator:
					temp_ptr = (d_tt_struct *)d_in->dev_sp;
					temp_ptr->default_mask_term = FALSE;
					memset(&mask_term.mask[0], 0, SIZEOF(io_termmask));
					break;
				case iop_ttsync:
					t.c_iflag |= IXON;
					break;
				case iop_nottsync:
					t.c_iflag &= ~IXON;
					break;
				case iop_typeahead:
					mask_in &= (~TRM_NOTYPEAHD);
					break;
				case iop_notypeahead:
					mask_in |= TRM_NOTYPEAHD;
					break;
				case iop_upscroll:
					d_out->dollar.y++;
					if (d_out->length)
						d_out->dollar.y %= d_out->length;
					if (NULL != CURSOR_ADDRESS)
						gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
					break;
				case iop_width:
					GET_LONG(width, pp->str.addr + p_offset);
					if (0 > width)
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG);
					/* Do not allow a WIDTH of 1 if UTF mode (ICHSET or OCHSET is not M) */
					if ((1 == width) && ((CHSET_M != d_in->ochset) || (CHSET_M != d_in->ichset)))
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_WIDTHTOOSMALL);
					if (0 == width)
					{
						d_out->wrap = FALSE;
						d_out->width = TTDEF_PG_WIDTH;
					} else
					{
						d_out->width = width;
						d_out->wrap = TRUE;
					}
					break;
				case iop_wrap:
					d_out->wrap = TRUE;
					break;
				case iop_nowrap:
					d_out->wrap = FALSE;
					break;
				case iop_x:
					GET_LONG(d_out->dollar.x, pp->str.addr + p_offset);
					if (0 > (int4)d_out->dollar.x)
						d_out->dollar.x = 0;
					if (d_out->dollar.x > d_out->width && d_out->wrap)
					{
						d_out->dollar.y += (d_out->dollar.x / d_out->width);
						if (d_out->length)
							d_out->dollar.y %= d_out->length;
						d_out->dollar.x	%= d_out->width;
					}
					if (NULL != CURSOR_ADDRESS)
						gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
					break;
				case iop_y:
					GET_LONG(d_out->dollar.y, pp->str.addr + p_offset);
					if (0 > (int4)d_out->dollar.y)
						d_out->dollar.y = 0;
					if (d_out->length)
						d_out->dollar.y %= d_out->length;
					if (NULL != CURSOR_ADDRESS)
						gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc);
					break;
				case iop_ipchset:
					{
#						ifdef KEEP_zOS_EBCDIC
						if ( (iconv_t)0 != iod->input_conv_cd )
						{
							ICONV_CLOSE_CD(iod->input_conv_cd);
						}
						SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1));
						if (DEFAULT_CODE_SET != iod->in_code_set)
							ICONV_OPEN_CD(iod->input_conv_cd,
								(char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
#						endif
						break;
					}
				case iop_opchset:
					{
#						ifdef KEEP_zOS_EBCDIC
						if ( (iconv_t)0 != iod->output_conv_cd)
						{
							ICONV_CLOSE_CD(iod->output_conv_cd);
						}
						SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1));
						if (DEFAULT_CODE_SET != iod->out_code_set)
							ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET,
								(char *)(pp->str.addr + p_offset + 1));
#						endif
						break;
					}
			}
			p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
				(unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
		}
		temp_ptr = (d_tt_struct *)d_in->dev_sp;
		Tcsetattr(tt_ptr->fildes, TCSANOW, &t, status, save_errno);
		if (0 != status)
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TCSETATTR, 1, tt_ptr->fildes, save_errno);
		temp_ptr->term_ctrl = mask_in;
		memcpy(&temp_ptr->mask_term, &mask_term, SIZEOF(io_termmask));
		if (flush_input)
		{
			TCFLUSH(tt_ptr->fildes, TCIFLUSH, status);
			if (0 != status)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LIT_AND_LEN("tcflush input"),
					CALLFROM, errno);
		}
	} else if (tt_ptr->mupintr && !dollar_zininterrupt)
	{	/* The interrupted read was not properly resumed so clear it now */
		tt_ptr->mupintr = FALSE;
		tt_ptr->tt_state_save.who_saved = ttwhichinvalid;
		io_find_mvstent(iod, TRUE);	/* clear mv stack entry */
	}
	REVERT_GTMIO_CH(&iod->pair, ch_set);
	return;
}