예제 #1
0
boolean_t iosocket_switch(char *handle, int handle_len, d_socket_struct *from, d_socket_struct *to)
{
	int4 		index, ii;
	socket_struct	*socketptr;

	if ((NULL == from) ||
		(0 > (index = iosocket_handle(handle, &handle_len, FALSE, from))))
	{
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKNOTFND, 2, handle_len, handle);
		return FALSE;
	} else
	{
		/* attach the socket to "to" and set it to current */

		assert(NULL != to);
		if (0 <= iosocket_handle(handle, &handle_len, FALSE, to))
		{
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKETEXIST, 2, handle_len, handle);
			return FALSE;
		}
                if (gtm_max_sockets <= to->n_socket)
                {
                        rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
                        return FALSE;
                }
		socketptr = from->socket[index];
		socketptr->dev = to;
		to->socket[to->n_socket++] = socketptr;
		to->current_socket = to->n_socket - 1;

		/* detach it from "from" */

		if (from->current_socket >= index)
			from->current_socket--;

		for(ii = index; ii < from->n_socket - 1; ii++)
		{
			from->socket[ii] = from->socket[ii + 1];
		}
		from->n_socket--;
		from->socket[from->n_socket] = NULL;
	}
	return TRUE;
}
예제 #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
void ojparams (char *p, job_params_type *job_params)
{
	unsigned char		ch;
	int4			status;
	mstr_len_t		handle_len;

		/* Initializations */
	job_params->baspri = 0;
	job_params->input.len = 0;
	job_params->output.len = 0;
	job_params->error.len = 0;
	job_params->gbldir.len = 0;
	job_params->startup.len = 0;
	job_params->directory.len = 0;
	job_params->directory.addr = 0;
	job_params->cmdline.len = 0;
	job_params->cmdline.addr = 0;
	job_params->passcurlvn = FALSE;

		/* Process parameter list */
	while (*p != jp_eol)
	{
		switch (ch = *p++)
		{
		case jp_default:
			if (*p != 0)
			{
				job_params->directory.len = (int)((unsigned char) *p);
				job_params->directory.addr = (p + 1);
			}
			break;

		case jp_error:
			if (*p != 0)
			{
				job_params->error.len = (int)((unsigned char) *p);
				job_params->error.addr = (p + 1);
			}
			break;

		case jp_gbldir:
			if (*p != 0)
			{
				job_params->gbldir.len = (int)((unsigned char) *p);
				job_params->gbldir.addr = (p + 1);
			}
			break;

		case jp_input:
			if (*p != 0)
			{
				job_params->input.len = (int)((unsigned char) *p);
				job_params->input.addr = p + 1;
			}
			break;

		case jp_output:
			if (*p != 0)
			{
				job_params->output.len = (int)((unsigned char) *p);
				job_params->output.addr = p + 1;
			}
			break;

		case jp_priority:
			job_params->baspri = (int4)(*((int4 *)p));
			break;

		case jp_startup:
			if (*p != 0)
			{
				job_params->startup.len = (int)((unsigned char) *p);
				job_params->startup.addr = p + 1;
			}
			break;

		case jp_cmdline:
			if(*p != 0)
			{
				job_params->cmdline.len = (int)((unsigned char) *p);
				job_params->cmdline.addr = p + 1;
			}
			break;

		case jp_passcurlvn:
			job_params->passcurlvn = TRUE;
			break;
		case jp_account:
		case jp_detached:
		case jp_image:
		case jp_logfile:
		case jp_noaccount:
		case jp_nodetached:
		case jp_noswapping:
		case jp_process_name:
		case jp_schedule:
		case jp_swapping:
			break;
		default:
		        assertpro(ch != ch);
		}

		switch (job_param_datatypes[ch])
		{
		case jpdt_nul:
			break;

		case jpdt_num:
			p += SIZEOF(int4);
			break;

		case jpdt_str:
			p += ((int)((unsigned char)*p)) + 1;
			break;
		default:
			assertpro((jpdt_nul == job_param_datatypes[ch])
				|| (jpdt_num == job_param_datatypes[ch])
				|| (jpdt_str == job_param_datatypes[ch]));
		}
	}

/* Defaults and Checks */

/*
 * Input file
 */
	if (job_params->input.len == 0)
	{
		job_params->input.len = STRLEN(definput);
		job_params->input.addr = definput;
	}
	else if (IS_JOB_SOCKET(job_params->input.addr, job_params->input.len))
	{
		handle_len = JOB_SOCKET_HANDLE_LEN(job_params->input.len);
		if ((NULL == socket_pool) || (-1 == iosocket_handle(JOB_SOCKET_HANDLE(job_params->input.addr),
									&handle_len, FALSE, socket_pool)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 5, "INPUT",
				job_params->input.len, job_params->input.addr);
	}
	else
		if (!(status = ojchkfs (job_params->input.addr,
		  job_params->input.len, TRUE)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 5, "INPUT",
			job_params->input.len, job_params->input.addr);

/*
 * Output file
 */
	if (job_params->output.len == 0)
	{
		if (!defoutbuf)
			defoutbuf = malloc(MAX_FILSPC_LEN);
		memcpy (&defoutbuf[0], job_params->routine.addr,
		  job_params->routine.len);
		memcpy (&defoutbuf[job_params->routine.len],
		  defoutext.addr, defoutext.len);
		if (*defoutbuf == '%')
			*defoutbuf = '_';
		job_params->output.len = job_params->routine.len
		  + defoutext.len;
		job_params->output.addr = &defoutbuf[0];
	}
	else if (IS_JOB_SOCKET(job_params->output.addr, job_params->output.len))
	{
		handle_len = JOB_SOCKET_HANDLE_LEN(job_params->output.len);
		if ((NULL == socket_pool) || (-1 == iosocket_handle(JOB_SOCKET_HANDLE(job_params->output.addr),
									&handle_len, FALSE, socket_pool)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 5, "OUTPUT",
				job_params->output.len, job_params->output.addr);
	}
	else
		if (!(status = ojchkfs (job_params->output.addr,
		  job_params->output.len, FALSE)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 6,
				"OUTPUT", job_params->output.len,
				job_params->output.addr);
/*
 * Error file
 */
	if (job_params->error.len == 0)
	{
		if (!deferrbuf)
			deferrbuf = malloc(MAX_FILSPC_LEN);
		memcpy (&deferrbuf[0], job_params->routine.addr,
		  job_params->routine.len);
		memcpy (&deferrbuf[job_params->routine.len],
		  deferrext.addr, deferrext.len);
		if (*deferrbuf == '%')
			*deferrbuf = '_';
		job_params->error.len = job_params->routine.len
		  + deferrext.len;
		job_params->error.addr = &deferrbuf[0];
	}
	else if (IS_JOB_SOCKET(job_params->error.addr, job_params->error.len))
	{
		handle_len = JOB_SOCKET_HANDLE_LEN(job_params->error.len);
		if ((NULL == socket_pool) || (-1 == iosocket_handle(JOB_SOCKET_HANDLE(job_params->error.addr),
									&handle_len, FALSE, socket_pool)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 5, "ERROR",
				job_params->error.len, job_params->error.addr);
	}
	else
		if (!(status = ojchkfs (job_params->error.addr,
		  job_params->error.len, FALSE)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 5, "ERROR",
			  job_params->error.len,
			  job_params->error.addr);
/*
 * Global Directory
 */
	if (job_params->gbldir.len)
		if (!(status = ojchkfs (job_params->gbldir.addr,
		  job_params->gbldir.len, FALSE)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 6, "GBLDIR",
			  job_params->gbldir.len, job_params->gbldir.addr);
/*
 * Startup
 */
	if (job_params->startup.len)
		if (!(status = ojchkfs (job_params->startup.addr,
		  job_params->startup.len, TRUE)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 7, "STARTUP",
			  job_params->startup.len, job_params->startup.addr);
/*
 * Default Directory
 */
	if (job_params->directory.len)
		if (!(status = ojchkfs (job_params->directory.addr,
		  job_params->directory.len, FALSE)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_PARFILSPC, 4, 7, "DEFAULT",
			  job_params->directory.len, job_params->directory.addr);
}
예제 #5
0
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;
        char            	*errptr;
        int4            	errlen, ii, msec_timeout;
	int			rv, size, max_fd;
	short			len;
        error_def(ERR_SOCKACPT);
        error_def(ERR_SOCKWAIT);
        error_def(ERR_TEXT);
	/* check for validity */
        assert(iod->type == gtmsocket);
        dsocketptr = (d_socket_struct *)iod->dev_sp;
	/* check for events */
	max_fd = 0;
	FD_ZERO(&tcp_fd);
	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);
	add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
	for ( ; ; )
	{
		rv = tcp_routines.aa_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 (OUTOFBANDNOW(outofband))
			{
				rv = 0;		/* treat as time out */
				break;
			}
			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 = cur_time.at_usec;
		}
		else
			break;	/* either other error or done */
	}
	if (rv == 0)
	{
		dsocketptr->dollar_key[0] = '\0';
		return FALSE;
	}
	else  if (rv < 0)
	{
		errptr = (char *)STRERROR(errno);
		errlen = strlen(errptr);
		rts_error(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)
	{
		size = sizeof(struct sockaddr_in);
		rv = tcp_routines.aa_accept(socketptr->sd, &peer, &size);
		if (rv == -1)
		{
			errptr = (char *)STRERROR(errno);
			errlen = strlen(errptr);
			rts_error(VARLSTCNT(6) ERR_SOCKACPT, 0, ERR_TEXT, 2, errlen, errptr);
			return FALSE;
		}
		/* got the connection, create a new socket in the device socket list */
		newsocketptr = (socket_struct *)malloc(sizeof(socket_struct));
		*newsocketptr = *socketptr;
		newsocketptr->sd = rv;
		memcpy(&newsocketptr->remote.sin, &peer, sizeof(struct sockaddr_in));
		SPRINTF(newsocketptr->remote.saddr_ip, "%s", tcp_routines.aa_inet_ntoa(peer.sin_addr));
		newsocketptr->remote.port = GTM_NTOHS(peer.sin_port);
		newsocketptr->state = socket_connected;
		newsocketptr->passive = FALSE;
		for (ii = 0; ii < newsocketptr->n_delimiter; ii++)
		{
			newsocketptr->delimiter[ii].addr = (char *)malloc(socketptr->delimiter[ii].len);
			memcpy(newsocketptr->delimiter[ii].addr, socketptr->delimiter[ii].addr, socketptr->delimiter[ii].len);
		}
		newsocketptr->buffer = (char *)malloc(socketptr->buffer_size);
		newsocketptr->buffer_size = socketptr->buffer_size;
		newsocketptr->buffered_length = socketptr->buffered_offset = 0;
		/* 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(&dsocketptr->dollar_key[0], CONNECTED, len);
		dsocketptr->dollar_key[len++] = '|';
		memcpy(&dsocketptr->dollar_key[len], newsocketptr->handle, newsocketptr->handle_len);
		len += newsocketptr->handle_len;
		dsocketptr->dollar_key[len++] = '|';
		memcpy(&dsocketptr->dollar_key[len], newsocketptr->remote.saddr_ip, strlen(newsocketptr->remote.saddr_ip));
		len += strlen(newsocketptr->remote.saddr_ip);
		dsocketptr->dollar_key[len] = '\0';
	}
	else
	{
		assert(socket_connected == socketptr->state);
		dsocketptr->current_socket = ii;
		len = sizeof(READ) - 1;
		memcpy(&dsocketptr->dollar_key[0], READ, len);
		dsocketptr->dollar_key[len++] = '|';
		memcpy(&dsocketptr->dollar_key[len], socketptr->handle, socketptr->handle_len);
                len += socketptr->handle_len;
                dsocketptr->dollar_key[len++] = '|';
                memcpy(&dsocketptr->dollar_key[len], socketptr->remote.saddr_ip, strlen(socketptr->remote.saddr_ip));
                len += strlen(socketptr->remote.saddr_ip);
                dsocketptr->dollar_key[len] = '\0';
	}
	return TRUE;
}
예제 #6
0
void iosocket_close(io_desc *iod, mval *pp)
{
    boolean_t	socket_specified = FALSE;
    unsigned char	ch;
    int		handle_len;
    d_socket_struct	*dsocketptr;
    socket_struct	*socketptr;
    char		sock_handle[MAX_HANDLE_LEN];
    int4		ii, jj, start, end, index;
    int		p_offset = 0;
    boolean_t socket_destroy = FALSE;

    assert(iod->type == gtmsocket);
    dsocketptr = (d_socket_struct *)iod->dev_sp;

    while (iop_eol != (ch = *(pp->str.addr + p_offset++)))
    {
        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_socket:
            handle_len = (short)(*(pp->str.addr + p_offset));
            assert(handle_len > 0);
            memcpy(sock_handle, (char *)(pp->str.addr + p_offset + 1), handle_len);
            socket_specified = TRUE;
            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_destroy:
            socket_destroy = TRUE;
            break;
        case iop_nodestroy:
            socket_destroy = FALSE;
            break;
        default:
            break;
        }
        p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ?
                     (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]);
    }
    if (socket_specified)
    {
        if (0 > (index = iosocket_handle(sock_handle, &handle_len, FALSE, dsocketptr)))
        {
            rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKNOTFND, 2, handle_len, sock_handle);
            return;
        }
        start = end = index;
    }
    else
    {
        start = dsocketptr->n_socket - 1;
        end = 0;
    }
    for (ii = start; ii >= end; ii--)
    {
        socketptr = dsocketptr->socket[ii];
        tcp_routines.aa_close(socketptr->sd);
        SOCKET_FREE(socketptr);
        if (dsocketptr->current_socket >= ii)
            dsocketptr->current_socket--;
        for (jj = ii + 1; jj <= dsocketptr->n_socket - 1; jj++)
            dsocketptr->socket[jj - 1] = dsocketptr->socket[jj];
        dsocketptr->n_socket--;
    }
    if (!socket_specified)
    {
        iod->state = dev_closed;
        if (socket_destroy)
        {
            active_device = 0;
            iosocket_destroy(iod);
        }
    }
}