示例#1
0
文件: iosocket_wait.c 项目: 5HT/mumps
boolean_t iosocket_wait(io_desc *iod, int4 timepar)
{
	struct 	timeval  	utimeout;
	ABS_TIME		cur_time, end_time;
	struct 	sockaddr_in     peer;           /* socket address + port */
        fd_set    		tcp_fd;
        d_socket_struct 	*dsocketptr;
        socket_struct   	*socketptr, *newsocketptr;
	socket_interrupt	*sockintr;
        char            	*errptr;
        int4            	errlen, ii, msec_timeout;
	int			rv, max_fd, len;
	GTM_SOCKLEN_TYPE	size;
	boolean_t		zint_restart;
	mv_stent		*mv_zintdev;
	short			retry_num;
        error_def(ERR_SOCKACPT);
        error_def(ERR_SOCKWAIT);
        error_def(ERR_TEXT);
	error_def(ERR_SOCKMAX);
	error_def(ERR_ZINTRECURSEIO);
        error_def(ERR_STACKCRIT);
        error_def(ERR_STACKOFLOW);

	/* check for validity */
        assert(iod->type == gtmsocket);
        dsocketptr = (d_socket_struct *)iod->dev_sp;
	sockintr = &dsocketptr->sock_save_state;

	/* Check for restart */
        if (!dsocketptr->mupintr)
                /* Simple path, no worries*/
                zint_restart = FALSE;
        else
        {       /* We have a pending wait restart of some sort - check we aren't recursing on this device */
                if (sockwhich_invalid == sockintr->who_saved)
                        GTMASSERT;	/* Interrupt should never have an invalid save state */
                if (dollar_zininterrupt)
                        rts_error(VARLSTCNT(1) ERR_ZINTRECURSEIO);
                if (sockwhich_wait != sockintr->who_saved)
                        GTMASSERT;      /* ZINTRECURSEIO should have caught */
                SOCKET_DEBUG(PRINTF("socwait: *#*#*#*#*#*#*#  Restarted interrupted wait\n"); DEBUGSOCKFLUSH);
                mv_zintdev = io_find_mvstent(iod, FALSE);
                if (mv_zintdev)
                {
                        if (sockintr->end_time_valid)
                                /* Restore end_time for timeout */
                                end_time = sockintr->end_time;

                        /* Done with this mv_stent. Pop it off if we can, else mark it inactive. */
                        if (mv_chain == mv_zintdev)
                                POP_MV_STENT();         /* pop if top of stack */
                        else
                        {       /* else mark it unused */
                                mv_zintdev->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
                                mv_zintdev->mv_st_cont.mvs_zintdev.io_ptr = NULL;
                        }
			zint_restart = TRUE;
			SOCKET_DEBUG(PRINTF("socwait: mv_stent found - endtime: %d/%d\n", end_time.at_sec, end_time.at_usec);
				     DEBUGSOCKFLUSH);
                } else
			SOCKET_DEBUG(PRINTF("socwait: no mv_stent found !!\n"); DEBUGSOCKFLUSH);
                dsocketptr->mupintr = FALSE;
		sockintr->who_saved = sockwhich_invalid;
        }
示例#2
0
boolean_t iosocket_wait(io_desc *iod, int4 timepar)
{
	struct 	timeval  	utimeout;
	ABS_TIME		cur_time, end_time;
	struct 	sockaddr_storage    	peer;           /* socket address + port */
	fd_set    		tcp_fd;
	d_socket_struct 	*dsocketptr;
	socket_struct   	*socketptr, *newsocketptr;
	socket_interrupt	*sockintr;
	char            	*errptr;
	int4            	errlen, ii, msec_timeout;
	int			rv, max_fd, len;
	GTM_SOCKLEN_TYPE	size;
	boolean_t		zint_restart;
	mv_stent		*mv_zintdev;
	int			retry_num;
	struct sockaddr		*peer_sa_ptr;
	char			port_buffer[NI_MAXSERV], ipaddr[SA_MAXLEN + 1];
	int			errcode;

	/* check for validity */
	assert(iod->type == gtmsocket);
	dsocketptr = (d_socket_struct *)iod->dev_sp;
	sockintr = &dsocketptr->sock_save_state;
	peer_sa_ptr = ((struct sockaddr *)(&peer));

	/* Check for restart */
	if (!dsocketptr->mupintr)
		/* Simple path, no worries*/
		zint_restart = FALSE;
	else
	{       /* We have a pending wait restart of some sort - check we aren't recursing on this device */
		if (sockwhich_invalid == sockintr->who_saved)
			GTMASSERT;	/* Interrupt should never have an invalid save state */
		if (dollar_zininterrupt)
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO);
		if (sockwhich_wait != sockintr->who_saved)
			GTMASSERT;      /* ZINTRECURSEIO should have caught */
		DBGSOCK((stdout, "socwait: *#*#*#*#*#*#*#  Restarted interrupted wait\n"));
		mv_zintdev = io_find_mvstent(iod, FALSE);
		if (mv_zintdev)
		{
			if (sockintr->end_time_valid)
				/* Restore end_time for timeout */
				end_time = sockintr->end_time;

			/* Done with this mv_stent. Pop it off if we can, else mark it inactive. */
			if (mv_chain == mv_zintdev)
				POP_MV_STENT();         /* pop if top of stack */
			else
			{       /* else mark it unused */
				mv_zintdev->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
				mv_zintdev->mv_st_cont.mvs_zintdev.io_ptr = NULL;
			}
			zint_restart = TRUE;
			DBGSOCK((stdout, "socwait: mv_stent found - endtime: %d/%d\n", end_time.at_sec, end_time.at_usec));
		} else
			DBGSOCK((stdout, "socwait: no mv_stent found !!\n"));
		dsocketptr->mupintr = FALSE;
		sockintr->who_saved = sockwhich_invalid;
	}
	/* check for events */
	FD_ZERO(&tcp_fd);
	while (TRUE)
	{
		max_fd = 0;
		for (ii = 0; ii < dsocketptr->n_socket; ii++)
		{
			socketptr = dsocketptr->socket[ii];
			if ((socket_listening == socketptr->state) || (socket_connected == socketptr->state))
			{
				FD_SET(socketptr->sd, &tcp_fd);
				max_fd = MAX(max_fd, socketptr->sd);
			}
		}
		utimeout.tv_sec = timepar;
		utimeout.tv_usec = 0;
		msec_timeout = timeout2msec(timepar);
		sys_get_curr_time(&cur_time);
		if (!zint_restart || !sockintr->end_time_valid)
			add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
		else
		{       /* end_time taken from restart data. Compute what msec_timeout should be so timeout timer
					   gets set correctly below.
			*/
			DBGSOCK((stdout, "socwait: Taking timeout end time from wait restart data\n"));
			cur_time = sub_abs_time(&end_time, &cur_time);
			if (0 > cur_time.at_sec)
			{
				msec_timeout = -1;
				utimeout.tv_sec = 0;
				utimeout.tv_usec = 0;
			} else
			{
				msec_timeout = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000);
				utimeout.tv_sec = cur_time.at_sec;
				utimeout.tv_usec = (gtm_tv_usec_t)cur_time.at_usec;
			}
		}
		sockintr->end_time_valid = FALSE;
		for ( ; ; )
		{
			rv = select(max_fd + 1, (void *)&tcp_fd, (void *)0, (void *)0,
				    (timepar == NO_M_TIMEOUT ? (struct timeval *)0 : &utimeout));
			if (0 > rv && EINTR == errno)
			{
				if (0 != outofband)
				{
					DBGSOCK((stdout, "socwait: outofband interrupt received (%d) -- "
						 "queueing mv_stent for wait intr\n", outofband));
					PUSH_MV_STENT(MVST_ZINTDEV);
					mv_chain->mv_st_cont.mvs_zintdev.io_ptr = iod;
					mv_chain->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
					sockintr->who_saved = sockwhich_wait;
					sockintr->end_time = end_time;
					sockintr->end_time_valid = TRUE;
					dsocketptr->mupintr = TRUE;
					socketus_interruptus++;
					DBGSOCK((stdout, "socwait: mv_stent queued - endtime: %d/%d  interrupts: %d\n",
						 end_time.at_sec, end_time.at_usec, socketus_interruptus));
					outofband_action(FALSE);
					GTMASSERT;      /* Should *never* return from outofband_action */
					return FALSE;   /* For the compiler.. */
				}
				sys_get_curr_time(&cur_time);
				cur_time = sub_abs_time(&end_time, &cur_time);
				if (0 > cur_time.at_sec)
				{
					rv = 0;		/* time out */
					break;
				}
				utimeout.tv_sec = cur_time.at_sec;
				utimeout.tv_usec = (gtm_tv_usec_t)cur_time.at_usec;
			} else
				break;	/* either other error or done */
		}
		if (rv == 0)
		{
			iod->dollar.key[0] = '\0';
			return FALSE;
		} else  if (rv < 0)
		{
			errptr = (char *)STRERROR(errno);
			errlen = STRLEN(errptr);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKWAIT, 0, ERR_TEXT, 2, errlen, errptr);
			return FALSE;
		}
		/* find out which socket is ready */
		for (ii = 0; ii < dsocketptr->n_socket; ii++)
		{
			socketptr = dsocketptr->socket[ii];
			if (0 != FD_ISSET(socketptr->sd, &tcp_fd))
				break;
		}
		assert(ii < dsocketptr->n_socket);
		if (socket_listening == socketptr->state)
		{
			if (gtm_max_sockets <= dsocketptr->n_socket)
			{
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
				return FALSE;
			}

			size = SIZEOF(struct sockaddr_storage);
			rv = tcp_routines.aa_accept(socketptr->sd, peer_sa_ptr, &size);
			if (-1 == rv)
			{
#				ifdef __hpux
				if (ENOBUFS == errno)
					continue;	/* On HP-UX, ENOBUFS may indicate a transient condition; retry */
#				endif
				errptr = (char *)STRERROR(errno);
				errlen = STRLEN(errptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKACPT, 0, ERR_TEXT, 2, errlen, errptr);
				return FALSE;
			}
			SOCKET_DUP(socketptr, newsocketptr);
			newsocketptr->sd = rv;
			SOCKET_ADDR_COPY(newsocketptr->remote, peer_sa_ptr, size);
			/* translate internal address to numeric ip address */
			GETNAMEINFO(peer_sa_ptr, size, ipaddr, SA_MAXLEN, NULL, 0, NI_NUMERICHOST, errcode);
			if (0 != errcode)
			{
				SOCKET_FREE(newsocketptr);
				RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
				return FALSE;
			}
			if (NULL != newsocketptr->remote.saddr_ip)
				free(newsocketptr->remote.saddr_ip);
			STRNDUP(ipaddr, SA_MAXLEN, newsocketptr->remote.saddr_ip);
			/* translate internal address to port number*/
			GETNAMEINFO(peer_sa_ptr, size, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV, errcode);
			if (0 != errcode)
			{
				SOCKET_FREE(newsocketptr);
				RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
				return FALSE;
			}
			newsocketptr->remote.port = ATOI(port_buffer);
			newsocketptr->state = socket_connected;
			newsocketptr->passive = FALSE;
			newsocketptr->first_read = newsocketptr->first_write = TRUE;
			/* put the new-born socket to the list and create a handle for it */
			iosocket_handle(newsocketptr->handle, &newsocketptr->handle_len, TRUE, dsocketptr);
			dsocketptr->socket[dsocketptr->n_socket++] = newsocketptr;
			dsocketptr->current_socket = dsocketptr->n_socket - 1;
			len = SIZEOF(CONNECTED) - 1;
			memcpy(&iod->dollar.key[0], CONNECTED, len);
			iod->dollar.key[len++] = '|';
			memcpy(&iod->dollar.key[len], newsocketptr->handle, newsocketptr->handle_len);
			len += newsocketptr->handle_len;
			iod->dollar.key[len++] = '|';
			strncpy(&iod->dollar.key[len], newsocketptr->remote.saddr_ip, DD_BUFLEN - 1 - len);
			iod->dollar.key[DD_BUFLEN-1] = '\0';		/* In case we fill the buffer */
		} else
		{
			assert(socket_connected == socketptr->state);
			dsocketptr->current_socket = ii;
			len = SIZEOF(READ) - 1;
			memcpy(&iod->dollar.key[0], READ, len);
			iod->dollar.key[len++] = '|';
			memcpy(&iod->dollar.key[len], socketptr->handle, socketptr->handle_len);
			len += socketptr->handle_len;
			iod->dollar.key[len++] = '|';
			if (NULL != socketptr->remote.saddr_ip)
			{
				strncpy(&iod->dollar.key[len], socketptr->remote.saddr_ip, DD_BUFLEN - 1 - len);
				iod->dollar.key[DD_BUFLEN-1] = '\0';
			} else
				iod->dollar.key[len] = '\0';
		}
		break;
	}
示例#3
0
void	iosocket_use(io_desc *iod, mval *pp)
{
    unsigned char	ch, len;
    int		handled_len, handlea_len, handles_len;
    int4		length, width, new_len;
    d_socket_struct *dsocketptr;
    socket_struct	*socketptr, newsocket;
    char		handlea[MAX_HANDLE_LEN], handles[MAX_HANDLE_LEN], handled[MAX_HANDLE_LEN];
    char            addr[SA_MAXLITLEN], *errptr, sockaddr[SA_MAXLITLEN],
                    temp_addr[SA_MAXLITLEN], ioerror;
    unsigned char	delimiter_buffer[MAX_N_DELIMITER * (MAX_DELIM_LEN + 1)];
    unsigned char	zff_buffer[MAX_ZFF_LEN];
    boolean_t	attach_specified = FALSE,
                detach_specified = FALSE,
                connect_specified = FALSE,
                ioerror_specified = FALSE,
                listen_specified = FALSE,
                socket_specified = FALSE,
                delay_specified = FALSE,
                nodelay_specified = FALSE,
                bfsize_specified = FALSE,
                ibfsize_specified = FALSE,
                moreread_specified = FALSE,
                create_new_socket;
    int4 		index, n_specified, zff_len, delimiter_len, moreread_timeout;
    int		fil_type, nodelay, p_offset = 0;
    uint4		bfsize = DEFAULT_SOCKET_BUFFER_SIZE, ibfsize;
    char		*tab;
    int		save_errno;
    size_t		d_socket_struct_len;
    mstr		lcl_zff;

    assert(iod->state == dev_open);
    assert(iod->type == gtmsocket);
    dsocketptr = (d_socket_struct *)(iod->dev_sp);
    /* ---------------------------------- parse the command line ------------------------------------ */
    n_specified = 0;
    zff_len = -1; /* indicates neither ZFF nor ZNOFF specified */
    delimiter_len = -1; /* indicates neither DELIM nor NODELIM specified */

    /* A read or wait was interrupted for this device. Allow only parmless use in $zinterrupt code for
       and interrupted device.
    */
    if (iop_eol != *(pp->str.addr + p_offset))
    {   /* Parameters were specified */
        if (dsocketptr->mupintr)
        {   /* And if we are in $zinterrupt code this is not allowed */
            if (dollar_zininterrupt)
                rts_error(VARLSTCNT(1) ERR_ZINTRECURSEIO);
            /* We are not in $zinterrupt code and this device was not resumed properly
               so clear its restartability.
            */
            io_find_mvstent(iod, TRUE);
            dsocketptr->mupintr = FALSE;
        }
    } else if (dsocketptr->mupintr && !dollar_zininterrupt)
    {   /* The interrupted read was not properly resumed so clear it now */
        dsocketptr->mupintr = FALSE;
        dsocketptr->sock_save_state.who_saved = sockwhich_invalid;
        io_find_mvstent(iod, TRUE);
    }

    while (iop_eol != (ch = *(pp->str.addr + p_offset++)))
    {
        assert((params)ch < (params)n_iops);
        switch (ch)
        {
        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);
            tab = pp->str.addr + p_offset + 1;
            if ((fil_type = namelook(filter_index, filter_names, tab, len)) < 0)
            {
                rts_error(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_attach:
            n_specified++;
            attach_specified = TRUE;
            handlea_len = (int)(*(pp->str.addr + p_offset));
            memcpy(handlea, (char *)(pp->str.addr + p_offset + 1), handlea_len);
            break;
        case iop_detach:
            n_specified++;
            detach_specified = TRUE;
            handled_len = (int)(*(pp->str.addr + p_offset));
            memcpy(handled, (char *)(pp->str.addr + p_offset + 1), handled_len);
            break;
        case iop_connect:
            n_specified++;
            connect_specified = TRUE;
            len = *(pp->str.addr + p_offset);
            if (len < SA_MAXLITLEN)
            {
                memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), len);
                sockaddr[len] = '\0';
            } else
                rts_error(VARLSTCNT(6) ERR_ADDRTOOLONG,
                          4, len, pp->str.addr + p_offset + 1, len, SA_MAXLITLEN);
            break;
        case iop_delimiter:
            n_specified++;
            delimiter_len = (int4)(unsigned char)*(pp->str.addr + p_offset);
            if (((MAX_DELIM_LEN + 1) * MAX_N_DELIMITER) >= delimiter_len)
                memcpy(delimiter_buffer, (pp->str.addr + p_offset + 1), delimiter_len);
            else
                rts_error(VARLSTCNT(1) ERR_DELIMSIZNA);
            break;
        case	iop_nodelimiter:
            delimiter_len = 0;
            break;
        case	iop_zdelay:
            delay_specified = TRUE;
            break;
        case	iop_znodelay:
            nodelay_specified = TRUE;
            break;
        case	iop_zbfsize:
            bfsize_specified = TRUE;
            GET_ULONG(bfsize, pp->str.addr + p_offset);
            if ((0 == bfsize) || (MAX_SOCKET_BUFFER_SIZE < bfsize))
                rts_error(VARLSTCNT(3) ERR_ILLESOCKBFSIZE, 1, bfsize);
            break;
        case	iop_zibfsize:
            ibfsize_specified = TRUE;
            GET_ULONG(ibfsize, pp->str.addr + p_offset);
            if ((0 == ibfsize) || (MAX_INTERNAL_SOCBUF_SIZE < ibfsize))
                rts_error(VARLSTCNT(3) ERR_ILLESOCKBFSIZE, 1, ibfsize);
            break;
        case iop_ioerror:
            n_specified++;
            ioerror_specified = TRUE;
            ioerror = *(char *)(pp->str.addr + p_offset + 1);
            break;
        case iop_zlisten:
            n_specified++;
            listen_specified = TRUE;
            len = *(pp->str.addr + p_offset);
            if (len < SA_MAXLITLEN)
            {
                memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), len);
                sockaddr[len] = '\0';
            } else
                rts_error(VARLSTCNT(6) ERR_ADDRTOOLONG,
                          4, len, pp->str.addr + p_offset + 1, len, SA_MAXLITLEN);
            break;
        case iop_socket:
            n_specified++;
            socket_specified = TRUE;
            handles_len = (int)(*(pp->str.addr + p_offset));
            memcpy(handles, (char *)(pp->str.addr + p_offset + 1), handles_len);
            break;
        case iop_ipchset:
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
            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, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1));
#endif
            break;
        case iop_opchset:
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
            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, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET);
#endif
            break;
        case iop_zff:
            if (MAX_ZFF_LEN >= (zff_len = (int4)(unsigned char)*(pp->str.addr + p_offset)))
                memcpy(zff_buffer, (char *)(pp->str.addr + p_offset + 1), zff_len);
            else
                rts_error(VARLSTCNT(4) ERR_ZFF2MANY, 2, zff_len, MAX_ZFF_LEN);
            break;
        case iop_znoff:
            zff_len = 0;
            break;
        case iop_length:
            GET_LONG(length, pp->str.addr + p_offset);
            if (length < 0)
                rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
            iod->length = length;
            break;
        case iop_width:
            /* SOCKET WIDTH is handled the same way as TERMINAL WIDTH */
            GET_LONG(width, pp->str.addr + p_offset);
            if (width < 0)
                rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
            if (0 == width)
            {
                iod->width = TCPDEF_WIDTH;
                iod->wrap = FALSE;
            } else
            {
                iod->width = width;
                iod->wrap = TRUE;
            }
            break;
        case iop_wrap:
            iod->wrap = TRUE;
            break;
        case iop_nowrap:
            iod->wrap = FALSE;
            break;
        case iop_morereadtime:
            /* Time in milliseconds socket read will wait for more data before returning */
            GET_LONG(moreread_timeout, pp->str.addr + p_offset);
            if (-1 == moreread_timeout)
                moreread_timeout = DEFAULT_MOREREAD_TIMEOUT;
            else if (-1 > moreread_timeout)
                rts_error(VARLSTCNT(1) ERR_DEVPARMNEG);
            else if (MAX_MOREREAD_TIMEOUT < moreread_timeout)
                rts_error(VARLSTCNT(3) ERR_MRTMAXEXCEEDED, 1, MAX_MOREREAD_TIMEOUT);
            moreread_specified = TRUE;
            break;
        default:
            /* ignore deviceparm */
            break;
        }
        p_offset += ((io_params_size[ch] == IOP_VAR_SIZE) ?
                     (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
    }
    /* ------ return immediately if no flag, worth a check because it is mostly true ------------ */
    if (1 == p_offset)
        return;
    /* ------------------------------ compatibility verification -------------------------------- */
    if ((socket_specified) && ((n_specified > 2) || ((2 == n_specified) && (0 >= delimiter_len))))
    {
        rts_error(VARLSTCNT(8) ERR_ACOMPTBINC, 6, LEN_AND_LIT("SOCKET"), LEN_AND_LIT("DELIMITER"), LEN_AND_LIT("USE"));
        return;
    }
    if (connect_specified && listen_specified)
    {
        rts_error(VARLSTCNT(8) ERR_ABNCOMPTINC, 6, LEN_AND_LIT("CONNECT"), LEN_AND_LIT("ZLISTEN"), LEN_AND_LIT("USE"));
        return;
    }
    if (delay_specified && nodelay_specified)
    {
        rts_error(VARLSTCNT(8) ERR_ABNCOMPTINC, 6, LEN_AND_LIT("DELAY"), LEN_AND_LIT("NODELAY"), LEN_AND_LIT("OPEN"));
        return;
    }
    /* ------------------ make a local copy of device structure to play with -------------------- */
    d_socket_struct_len = SIZEOF(d_socket_struct) + (SIZEOF(socket_struct) * (gtm_max_sockets - 1));
    memcpy(newdsocket, dsocketptr, d_socket_struct_len);
    /* --------------- handle the two special cases attach/detach first ------------------------- */
    if (detach_specified)
    {
        if (1 < n_specified)
        {
            rts_error(VARLSTCNT(6) ERR_ANCOMPTINC, 4, LEN_AND_LIT("DETACH"), LEN_AND_LIT("USE"));
            return;
        }
        if (NULL == socket_pool)
            iosocket_poolinit();
        iosocket_switch(handled, handled_len, newdsocket, socket_pool);
        memcpy(dsocketptr, newdsocket, d_socket_struct_len);
        if (0 > dsocketptr->current_socket)
        {
            io_curr_device.in = io_std_device.in;
            io_curr_device.out = io_std_device.out;
        }
        return; /* detach can only be specified by itself */
    }
    if (attach_specified)
    {   /* NOTE: A socket could be moved from one device to another using DETACH/ATTACH. A socket does not carry I[O]CHSET with
         * it while being moved. Such a socket will use the I[O]CHSET of the device it is ATTACHed to. If there is input still
         * buffered, this may cause unintentional consequences in the application if I[O]CHSET changes. GT.M does not detect
         * (or report) a change in I[O]CHSET due to DETACH/ATTACH.
         */
        if (1 < n_specified)
        {
            rts_error(VARLSTCNT(6) ERR_ANCOMPTINC, 4, LEN_AND_LIT("ATTACH"), LEN_AND_LIT("USE"));
            return;
        }
        if (NULL == socket_pool)
        {
            rts_error(VARLSTCNT(4) ERR_SOCKNOTFND, 2, handlea_len, handlea);
            return;
        }
        iosocket_switch(handlea, handlea_len, socket_pool, newdsocket);
        memcpy(dsocketptr, newdsocket, d_socket_struct_len);
        return; /* attach can only be specified by itself */
    }
    /* ------------ create/identify the socket to work on and make a local copy ----------------- */
    if (create_new_socket = (listen_specified || connect_specified))	/* real "=" */
    {
        /* allocate the structure for a new socket */
        if (NULL == (socketptr = iosocket_create(sockaddr, bfsize, -1)))
            return;
        /* give the new socket a handle */
        iosocket_handle(handles, &handles_len, TRUE, dsocketptr);
        socketptr->handle_len = handles_len;
        memcpy(socketptr->handle, handles, handles_len);
        socketptr->dev = newdsocket;	/* use newdsocket temporarily for the sake of bind/connect */
    } else
    {
        if (socket_specified)
        {
            /* use the socket flag to identify which socket to apply changes */
            if (0 > (index = iosocket_handle(handles, &handles_len, FALSE, newdsocket)))
            {
                rts_error(VARLSTCNT(4) ERR_SOCKNOTFND, 2, handles_len, handles);
                return;
            }
            newdsocket->current_socket = index;
            socketptr = newdsocket->socket[index];
        } else
        {
            socketptr = newdsocket->socket[newdsocket->current_socket];
            if (newdsocket->n_socket <= newdsocket->current_socket)
            {
                assert(FALSE);
                rts_error(VARLSTCNT(4) ERR_CURRSOCKOFR, 2, newdsocket->current_socket, newdsocket->n_socket);
                return;
            }
        }
    }
    newsocket = *socketptr;
    /* ---------------------- apply changes to the local copy of the socket --------------------- */
    if (0 <= delimiter_len)
    {
        iosocket_delimiter(delimiter_buffer, delimiter_len, &newsocket, (0 == delimiter_len));
        /* The delimiter has changed. The iosocket_readfl/write routine won't notice so we have to do
           the UTF16xx conversion since we changed it.
        */
        DBGSOCK2((stdout, "socuse: Delimiter(s) replaced - num delims: %d  delimiter_len: %d  ichset: %d  ochset: %d\n",
                  newsocket.n_delimiter, delimiter_len, iod->ichset, iod->ochset));
        if  (0 < delimiter_len)
        {
            if (!newsocket.first_read && (CHSET_UTF16BE == iod->ichset || CHSET_UTF16LE == iod->ichset))
            {   /* We have been reading with this socket so convert this new delimiter set */
                DBGSOCK2((stdout, "socuse: Converting new delimiters for input\n"));
                iosocket_delim_conv(&newsocket, iod->ichset);
            }
            if (!newsocket.first_write && (CHSET_UTF16BE == iod->ochset || CHSET_UTF16LE == iod->ochset))
            {   /* We have been writing with this socket so convert the new default output delimiter */
                DBGSOCK2((stdout, "socuse: Converting new delimiters for output\n"));
                if (newsocket.first_read || (CHSET_UTF16BE != iod->ichset && CHSET_UTF16LE != iod->ichset))
                {   /* Need to do conversion as iosocket_delim_conv above didn't do it for us */
                    DBGSOCK2((stdout, "socuse: running convert for write since input didn't do it\n"));
                    new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset],
                                       &newsocket.delimiter[0], NULL, NULL);
                    if (MAX_DELIM_LEN < new_len)
                    {
                        rts_error(VARLSTCNT(1) ERR_DELIMSIZNA);
                        return;
                    }
                } else
                {
                    DBGSOCK2((stdout, "socuse: using previous length from read conversion\n"));
                    new_len = newsocket.idelimiter[0].len;
                }
                newsocket.odelimiter0.len = new_len;
                UNICODE_ONLY(newsocket.odelimiter0.char_len = newsocket.delimiter[0].char_len);
                newsocket.odelimiter0.addr = malloc(new_len);
                memcpy(newsocket.odelimiter0.addr,
                       (newsocket.first_read ? (char *)stringpool.free : newsocket.idelimiter[0].addr),
                       new_len);
            }
        }
    }
    if (iod->wrap && 0 != newsocket.n_delimiter && iod->width < newsocket.delimiter[0].len)
        rts_error(VARLSTCNT(4) ERR_DELIMWIDTH, 2, iod->width, newsocket.delimiter[0].len);
    if (0 <= zff_len && /* ZFF or ZNOFF specified */
            0 < (newsocket.zff.len = zff_len)) /* assign the new ZFF len, might be 0 from ZNOFF, or ZFF="" */
    {   /* ZFF="non-zero-len-string" specified */
        if (CHSET_UTF16BE == iod->ochset || CHSET_UTF16LE == iod->ochset) /* need conversion of ZFF */
        {
            DBGSOCK2((stdout, "socuse: Converting zff\n"));
            lcl_zff.addr = (char *)zff_buffer;
            lcl_zff.len = zff_len;
            new_len = gtm_conv(chset_desc[CHSET_UTF8], chset_desc[iod->ochset], &lcl_zff, NULL, NULL);
            if (MAX_ZFF_LEN < new_len)
                rts_error(VARLSTCNT(4) ERR_ZFF2MANY, 2, new_len, MAX_ZFF_LEN);
            if (NULL == newsocket.zff.addr) /* we rely on newsocket.zff.addr being set to 0 in iosocket_create() */
                newsocket.zff.addr = (char *)malloc(MAX_ZFF_LEN);
            newsocket.zff.len = new_len;
            UNICODE_ONLY(newsocket.zff.char_len = 0); /* don't care */
            memcpy(newsocket.zff.addr, stringpool.free, new_len);

        } else
        {   /* Store parm without conversion */
            if (gtm_utf8_mode) /* Check if ZFF has any invalid UTF-8 character */
            {   /* Note: the ZFF string originates from the source program, so is in UTF-8 mode or M mode
                   regardless of OCHSET of this device. ZFF is output on WRITE # command, and MUST contain
                   valid UTF-8 sequence. This validation is handled by gtm_conv in the path above.
                */
                utf8_len_strict(zff_buffer, zff_len);
            }
            if (NULL == newsocket.zff.addr) /* we rely on newsocket.zff.addr being set to 0 in iosocket_create() */
                newsocket.zff.addr = (char *)malloc(MAX_ZFF_LEN);
            memcpy(newsocket.zff.addr, zff_buffer, zff_len);
        }
    }
    if (ioerror_specified)
        newsocket.ioerror = ('T' == ioerror || 't' == ioerror);
    if (nodelay_specified || delay_specified)
        newsocket.nodelay = nodelay_specified;	/* defaults to DELAY */
    if (ibfsize_specified)
        newsocket.bufsiz = ibfsize;
    if (moreread_specified)
    {
        newsocket.moreread_timeout = moreread_timeout;
        newsocket.def_moreread_timeout = TRUE;	/* need to know this was user-defined in iosocket_readfl.c */
    }
    if (!create_new_socket)
    {
        /* these changes apply to only pre-existing sockets */
        if (bfsize_specified)
            newsocket.buffer_size = bfsize;
#ifdef TCP_NODELAY
        nodelay = newsocket.nodelay ? 1 : 0;
        if ((socketptr->nodelay != newsocket.nodelay) &&
                (-1 == tcp_routines.aa_setsockopt(newsocket.sd, IPPROTO_TCP,
                        TCP_NODELAY, &nodelay, SIZEOF(nodelay))))
        {
            save_errno = errno;
            errptr = (char *)STRERROR(save_errno);
            rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("TCP_NODELAY"), save_errno, LEN_AND_STR(errptr));
            return;
        }
#endif
        if ((socketptr->bufsiz != newsocket.bufsiz) &&
                (-1 == tcp_routines.aa_setsockopt(newsocket.sd, SOL_SOCKET,
                        SO_RCVBUF, &newsocket.bufsiz, SIZEOF(newsocket.bufsiz))))
        {
            save_errno = errno;
            errptr = (char *)STRERROR(save_errno);
            rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("SO_RCVBUF"), save_errno, LEN_AND_STR(errptr));
            return;
        }
        if (socketptr->buffer_size != newsocket.buffer_size)
        {
            if (socketptr->buffered_length > bfsize)
                rts_error(VARLSTCNT(4) ERR_SOCKBFNOTEMPTY, 2, bfsize, socketptr->buffered_length);
            newsocket.buffer = (char *)malloc(bfsize);
            if (0 < socketptr->buffered_length)
            {
                memcpy(newsocket.buffer, socketptr->buffer + socketptr->buffered_offset,
                       socketptr->buffered_length);
                newsocket.buffered_offset = 0;
            }
        }
    }
    /* -------------------------------------- action -------------------------------------------- */
    if ((listen_specified && (!iosocket_bind(&newsocket, NO_M_TIMEOUT, ibfsize_specified))) ||
            (connect_specified && (!iosocket_connect(&newsocket, 0, ibfsize_specified))))
    {   /* error message should be printed from bind/connect */
        if (socketptr->sd > 0)
            (void)tcp_routines.aa_close(socketptr->sd);
        iosocket_delimiter((unsigned char *)NULL, 0, &newsocket, TRUE);
        if (NULL != socketptr->zff.addr)
            free(socketptr->zff.addr);
        if (NULL != socketptr->buffer)
            free(socketptr->buffer);
        free(socketptr);
        return;
    }
    /* ------------------------------------ commit changes -------------------------------------- */
    if (create_new_socket)
    {
        if (gtm_max_sockets <= newdsocket->n_socket)
        {
            rts_error(VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
            return;
        }
        /* a new socket is created. so add to the list */
        newsocket.dev = dsocketptr;
        newdsocket->socket[newdsocket->n_socket++] = socketptr;
        newdsocket->current_socket = newdsocket->n_socket - 1;
    }
    else if (socketptr->buffer_size != newsocket.buffer_size)
        free(socketptr->buffer);
    *socketptr = newsocket;
    memcpy(dsocketptr, newdsocket, d_socket_struct_len);
    return;
}
示例#4
0
short	iosocket_open(io_log_name *dev, mval *pp, int file_des, mval *mspace, int4 timepar)
{
	char			addr[SA_MAXLITLEN], *errptr, sockaddr[SA_MAXLITLEN],
		                temp_addr[SA_MAXLITLEN], dev_type[MAX_DEV_TYPE_LEN];
	unsigned char		ch, *c, *next, *top;
	int			handle_len, moreread_timeout, len;
	unsigned short		port;
	int4			errlen, msec_timeout, real_errno, p_offset = 0, zff_len, delimiter_len;
	int			d_socket_struct_len;
	ABS_TIME		cur_time, end_time;
	io_desc			*ioptr;
	struct sockaddr_in	peer;		/* socket address + port */
	fd_set			tcp_fd;
	uint4			bfsize = DEFAULT_SOCKET_BUFFER_SIZE, ibfsize;
        d_socket_struct         *dsocketptr;
	socket_struct		*socketptr;
	mv_stent		*mv_zintdev;
	boolean_t		zint_conn_restart = FALSE;
	socket_interrupt	*sockintr;
	mstr			chset_mstr;
	boolean_t		attach_specified = FALSE,
		                listen_specified = FALSE,
		                connect_specified = FALSE,
	                	ioerror_specified = FALSE,
		                delay_specified = FALSE,
		                nodelay_specified = FALSE,
		                ibfsize_specified = FALSE,
		                moreread_specified = FALSE,
		                is_principal = FALSE,	/* called from inetd */
		                ichset_specified,
		                ochset_specified;
	unsigned char 		delimiter_buffer[MAX_N_DELIMITER * (MAX_DELIM_LEN + 1)], zff_buffer[MAX_ZFF_LEN];
	char			ioerror, ip[3], tcp[4],
 		                sock_handle[MAX_HANDLE_LEN], delimiter[MAX_DELIM_LEN + 1];

	error_def(ERR_DELIMSIZNA);
	error_def(ERR_ADDRTOOLONG);
	error_def(ERR_SOCKETEXIST);
	error_def(ERR_ABNCOMPTINC);
	error_def(ERR_DEVPARINAP);
	error_def(ERR_DEVPARMNEG);
	error_def(ERR_ILLESOCKBFSIZE);
	error_def(ERR_ZFF2MANY);
	error_def(ERR_DELIMWIDTH);
	error_def(ERR_SOCKMAX);
	error_def(ERR_ZINTRECURSEIO);
	error_def(ERR_MRTMAXEXCEEDED);

	ioptr = dev->iod;
	assert((params) *(pp->str.addr + p_offset) < (unsigned char)n_iops);
	assert(ioptr != 0);
	assert(ioptr->state >= 0 && ioptr->state < n_io_dev_states);
	assert(ioptr->type == gtmsocket);
	if ((ioptr->state == dev_closed) && mspace && mspace->str.len && mspace->str.addr)
	{
		lower_to_upper((uchar_ptr_t)dev_type, (uchar_ptr_t)mspace->str.addr, mspace->str.len);
		if (STR_LIT_LEN("SOCKET") != mspace->str.len || 0 != memcmp(dev_type, "SOCKET", STR_LIT_LEN("SOCKET")))
		{
			if (ioptr->dev_sp)
				free(ioptr->dev_sp);
			ioptr->state = dev_never_opened;
		}
	}
	d_socket_struct_len = SIZEOF(d_socket_struct) + (SIZEOF(socket_struct) * (gtm_max_sockets - 1));
	if (ioptr->state == dev_never_opened)
	{
		dsocketptr = ioptr->dev_sp = (void *)malloc(d_socket_struct_len);
		memset(dsocketptr, 0, d_socket_struct_len);
		dsocketptr->iod = ioptr;
	} else
		dsocketptr = (d_socket_struct *)ioptr->dev_sp;

	if (ioptr->state == dev_never_opened)
	{
		ioptr->state	= dev_closed;
		ioptr->width	= TCPDEF_WIDTH;
		ioptr->length	= TCPDEF_LENGTH;
		ioptr->wrap	= TRUE;
		if (-1 == iotcp_fillroutine())
			assert(FALSE);
		if (!io_std_device.in)
			/* called from io_init */
			is_principal = TRUE;
	}
        if (dsocketptr->mupintr)
	{	/* check if connect was interrupted */
		sockintr = &dsocketptr->sock_save_state;
		if (sockwhich_invalid == sockintr->who_saved)
			GTMASSERT;	/* Interrupt should never have an invalid save state */
		if (dollar_zininterrupt)
		{
			dsocketptr->mupintr = FALSE;
			sockintr->who_saved = sockwhich_invalid;
			rts_error(VARLSTCNT(1) ERR_ZINTRECURSEIO);
		}
		if (sockwhich_connect != sockintr->who_saved)
			GTMASSERT;	/* ZINTRECURSEIO should have caught */
		mv_zintdev = io_find_mvstent(dsocketptr->iod, FALSE);
		if (mv_zintdev && mv_zintdev->mv_st_cont.mvs_zintdev.buffer_valid)
		{	/* mupintr will be reset and mvstent popped in iosocket_connect */
			connect_specified = TRUE;
			ibfsize_specified = sockintr->ibfsize_specified;
			assert(newdsocket);
			assert(newdsocket == sockintr->newdsocket);
			memcpy(newdsocket, (d_socket_struct *)mv_zintdev->mv_st_cont.mvs_zintdev.curr_sp_buffer.addr,
					d_socket_struct_len);
			socketptr = newdsocket->socket[newdsocket->current_socket];
			assert(socketptr == (socket_struct *)mv_zintdev->mv_st_cont.mvs_zintdev.socketptr);
			zint_conn_restart = TRUE;	/* skip what we already did, state == dev_closed */
		}
	} else
	{
		ioptr->dollar.zeof = FALSE;
		if (NULL == newdsocket)
			newdsocket = (d_socket_struct *)malloc(d_socket_struct_len);
		memcpy(newdsocket, dsocketptr, d_socket_struct_len);
		memcpy(newdsocket->dollar_device, "0", SIZEOF("0"));
		zff_len = -1; /* indicates neither ZFF nor ZNOFF specified */
		delimiter_len = -1; /* indicates neither DELIM nor NODELIM specified */
		ichset_specified = ochset_specified = FALSE;
		while (iop_eol != (ch = *(pp->str.addr + p_offset++)))
		{
			switch(ch)
			{
				case iop_delimiter:
					delimiter_len = (int4)(unsigned char)*(pp->str.addr + p_offset);
					if (((MAX_DELIM_LEN + 1) * MAX_N_DELIMITER) >= delimiter_len)
						memcpy(delimiter_buffer, (pp->str.addr + p_offset + 1), delimiter_len);
					else
						rts_error(VARLSTCNT(1) ERR_DELIMSIZNA);
					break;
				case iop_ipchset:
					UNICODE_ONLY(
						if (gtm_utf8_mode)
					        {	/* Only change ipchset if in UTF8 mode */
							chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
							chset_mstr.len = *(pp->str.addr + p_offset);
							SET_ENCODING(ioptr->ichset, &chset_mstr);
							ichset_specified = TRUE;
						}
					);
					break;
				case iop_opchset:
					UNICODE_ONLY(
						if (gtm_utf8_mode)
		 				{       /* Only change ipchset if in UTF8 mode */
							chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
							chset_mstr.len = *(pp->str.addr + p_offset);
							SET_ENCODING(ioptr->ochset, &chset_mstr);
							ochset_specified = TRUE;
						}
					);
					break;
                        	case iop_chset:
					UNICODE_ONLY(
						if (gtm_utf8_mode)
						{       /* Only change ipchset/opchset if in UTF8 mode */
							chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1);
							chset_mstr.len = *(pp->str.addr + p_offset);
							SET_ENCODING(ioptr->ichset, &chset_mstr);
							ioptr->ochset = ioptr->ichset;
							ichset_specified = ochset_specified = TRUE;
                                        	}
					);
					break;
			/* Note the following 4 cases (iop_m/utf16/utf16be/utf16le) have no corresponding device parameter
			   but are included here because they can be easily used in internal processing.
			*/
				case iop_m:
					UNICODE_ONLY(
						ioptr->ichset = ioptr->ochset = CHSET_M;
						ichset_specified = ochset_specified = TRUE;
					);
示例#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;
}
示例#6
0
boolean_t iosocket_connect(socket_struct *socketptr, int4 timepar, boolean_t update_bufsiz)
{
	int		temp_1 = 1;
	char		*errptr;
	int4            errlen, msec_timeout, real_errno;
	boolean_t	no_time_left = FALSE;
	short		len;
	io_desc		*iod;
	d_socket_struct *dsocketptr;
        socket_interrupt *sockintr;
	ABS_TIME        cur_time, end_time;
        mv_stent        *mv_zintdev;
	GTM_SOCKLEN_TYPE	sockbuflen;

	error_def(ERR_SOCKINIT);
	error_def(ERR_OPENCONN);
	error_def(ERR_TEXT);
	error_def(ERR_GETSOCKOPTERR);
	error_def(ERR_SETSOCKOPTERR);
	error_def(ERR_ZINTRECURSEIO);
	error_def(ERR_STACKCRIT);
	error_def(ERR_STACKOFLOW);

	SOCKET_DEBUG(PRINTF("socconn: ************* Entering socconn - timepar: %d\n",timepar); DEBUGSOCKFLUSH);
        /* check for validity */
	dsocketptr = socketptr->dev;
        assert(NULL != dsocketptr);
        sockintr = &dsocketptr->sock_save_state;
	iod = dsocketptr->iod;

        dsocketptr->dollar_key[0] = '\0';

#ifdef SOCK_INTR_CONNECT
	/*
	***** Note this code and the code further down is #ifdef'd out because this approach to handling jobinterrupts
              during connect was not feasible because we are always dealing with a new sockintr device on the restart
	      of an OPEN statement. There is no device to continue using so this approach needs to be changed.
	      The code is left here in case it is useful when this is fixed.
	*/
        /* Check for restart */
        if (dsocketptr->mupintr)
        {       /* We have a pending read restart of some sort - check we aren't recursing on this device */
                if (sockwhich_invalid == sockintr->who_saved)
                        GTMASSERT;      /* Interrupt should never have an invalid save state */
                if (dollar_zininterrupt)
                        rts_error(VARLSTCNT(1) ERR_ZINTRECURSEIO);
                if (sockwhich_connect != sockintr->who_saved)
                        GTMASSERT;      /* ZINTRECURSEIO should have caught */
                SOCKET_DEBUG(PRINTF("socconn: *#*#*#*#*#*#*#  Restarted interrupted connect\n"); DEBUGSOCKFLUSH);
                mv_zintdev = io_find_mvstent(iod, FALSE);
                if (mv_zintdev)
                {
                        if (sockintr->end_time_valid)
                                /* Restore end_time for timeout */
                                end_time = sockintr->end_time;

                        /* Done with this mv_stent. Pop it off if we can, else mark it inactive. */
                        if (mv_chain == mv_zintdev)
                                POP_MV_STENT();         /* pop if top of stack */
                        else
                        {       /* else mark it unused */
                                mv_zintdev->mv_st_cont.mvs_zintdev.buffer_valid = FALSE;
                                mv_zintdev->mv_st_cont.mvs_zintdev.io_ptr = NULL;
                        }
                        SOCKET_DEBUG(PRINTF("socconn: mv_stent found - endtime: %d/%d\n", end_time.at_sec, end_time.at_usec);
                                     DEBUGSOCKFLUSH);
                } else
                        SOCKET_DEBUG(PRINTF("socconn: no mv_stent found !!\n"); DEBUGSOCKFLUSH);
                dsocketptr->mupintr = FALSE;
                sockintr->who_saved = sockwhich_invalid;
        }