Beispiel #1
0
boolean_t iosocket_bind(socket_struct *socketptr, int4 timepar, boolean_t update_bufsiz)
{
	int			temp_1 = 1;
	char			*errptr;
	int4			errlen, msec_timeout, real_errno;
	short			len;
	in_port_t		actual_port;
	boolean_t		no_time_left = FALSE;
	d_socket_struct		*dsocketptr;
	struct addrinfo		*ai_ptr;
	char			port_buffer[NI_MAXSERV];
	int			errcode;
	ABS_TIME        	cur_time, end_time;
	GTM_SOCKLEN_TYPE	addrlen;
	GTM_SOCKLEN_TYPE	sockbuflen;

	dsocketptr = socketptr->dev;
	ai_ptr = (struct addrinfo*)(&socketptr->local.ai);
	assert(NULL != dsocketptr);
	dsocketptr->iod->dollar.key[0] = '\0';
	if (FD_INVALID != socketptr->temp_sd)
	{
		socketptr->sd = socketptr->temp_sd;
		socketptr->temp_sd = FD_INVALID;
	}
	if (timepar != NO_M_TIMEOUT)
	{
		msec_timeout = timeout2msec(timepar);
		sys_get_curr_time(&cur_time);
		add_int_to_abs_time(&cur_time, msec_timeout, &end_time);
	}

	do
	{
		temp_1 = 1;
		if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				SOL_SOCKET, SO_REUSEADDR, &temp_1, SIZEOF(temp_1)))
		{
		        real_errno = errno;
			errptr = (char *)STRERROR(real_errno);
			errlen = STRLEN(errptr);
			SOCKET_FREE(socketptr);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("SO_REUSEADDR"), real_errno, errlen, errptr);
			return FALSE;
		}
#ifdef TCP_NODELAY
		temp_1 = socketptr->nodelay ? 1 : 0;
		if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				IPPROTO_TCP, TCP_NODELAY, &temp_1, SIZEOF(temp_1)))
		{
		        real_errno = errno;
			errptr = (char *)STRERROR(real_errno);
			errlen = STRLEN(errptr);
			SOCKET_FREE(socketptr);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("TCP_NODELAY"), real_errno, errlen, errptr);
			return FALSE;
		}
#endif
		if (update_bufsiz)
		{
			if (-1 == tcp_routines.aa_setsockopt(socketptr->sd,
				SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, SIZEOF(socketptr->bufsiz)))
			{
			        real_errno = errno;
				errptr = (char *)STRERROR(real_errno);
				errlen = STRLEN(errptr);
				SOCKET_FREE(socketptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5,
						RTS_ERROR_LITERAL("SO_RCVBUF"), real_errno, errlen, errptr);
				return FALSE;
			}
		} else
		{
			sockbuflen = SIZEOF(socketptr->bufsiz);
			if (-1 == tcp_routines.aa_getsockopt(socketptr->sd,
				SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, &sockbuflen))
			{
			        real_errno = errno;
				errptr = (char *)STRERROR(real_errno);
				errlen = STRLEN(errptr);
				SOCKET_FREE(socketptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_GETSOCKOPTERR, 5,
					RTS_ERROR_LITERAL("SO_RCVBUF"), real_errno, errlen, errptr);
				return FALSE;
			}
		}
		temp_1 = tcp_routines.aa_bind(socketptr->sd, SOCKET_LOCAL_ADDR(socketptr), ai_ptr->ai_addrlen);
		if (temp_1 < 0)
		{
			real_errno = errno;
			no_time_left = TRUE;
			switch (real_errno)
			{
				case EADDRINUSE:
					if (NO_M_TIMEOUT != timepar)
					{
						sys_get_curr_time(&cur_time);
						cur_time = sub_abs_time(&end_time, &cur_time);
						if (cur_time.at_sec > 0)
							no_time_left = FALSE;
					}
					break;
				case EINTR:
					break;
				default:
					SOCKET_FREE(socketptr);
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKBIND, 0, real_errno, 0);
					break;
			}
			if (no_time_left)
				return FALSE;
			hiber_start(100);
			tcp_routines.aa_close(socketptr->sd);
			if (-1 == (socketptr->sd = tcp_routines.aa_socket(ai_ptr->ai_family,ai_ptr->ai_socktype,
									  ai_ptr->ai_protocol)))
			{
				real_errno = errno;
				errptr = (char *)STRERROR(real_errno);
				errlen = STRLEN(errptr);
				SOCKET_FREE(socketptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, real_errno, errlen, errptr);
				return FALSE;
			}
		}
	} while (temp_1 < 0);

	/* obtain actual port from the bound address if port 0 was specified */
	addrlen = SOCKET_ADDRLEN(socketptr, ai_ptr, local);
	if (-1 == tcp_routines.aa_getsockname(socketptr->sd, SOCKET_LOCAL_ADDR(socketptr), &addrlen))
	{
		real_errno = errno;
		errptr = (char *)STRERROR(real_errno);
		errlen = STRLEN(errptr);
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, real_errno, errlen, errptr);
	        return FALSE;
	}
	assert(ai_ptr->ai_addrlen == addrlen);
	GETNAMEINFO(SOCKET_LOCAL_ADDR(socketptr), addrlen, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV, errcode);
	if (0 != errcode)
	{
		SOCKET_FREE(socketptr);
		RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode);
		return FALSE;
	}
	actual_port = ATOI(port_buffer);
	if (0 == socketptr->local.port)
		socketptr->local.port = actual_port;
	assert(socketptr->local.port == actual_port);
	socketptr->state = socket_bound;
	len = SIZEOF(BOUND) - 1;
        memcpy(&dsocketptr->iod->dollar.key[0], BOUND, len);
        dsocketptr->iod->dollar.key[len++] = '|';
        memcpy(&dsocketptr->iod->dollar.key[len], socketptr->handle, socketptr->handle_len);
        len += socketptr->handle_len;
        dsocketptr->iod->dollar.key[len++] = '|';
        SPRINTF(&dsocketptr->iod->dollar.key[len], "%d", socketptr->local.port);
	return TRUE;
}
Beispiel #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;
	}
socket_struct *iosocket_create(char *sockaddr, uint4 bfsize, int file_des, boolean_t listen_specified)
{
	socket_struct		*socketptr;
	socket_struct		*prev_socketptr;
	socket_struct		*socklist_head;
	boolean_t		passive = FALSE;
	unsigned short		port;
	int			ii, save_errno, tmplen, errlen, sockaddrlen;
	char 			temp_addr[SA_MAXLITLEN], protocolstr[6], *adptr;
	const char		*errptr;
	struct addrinfo		*ai_ptr;
	struct addrinfo		hints, *addr_info_ptr = NULL;
#ifndef VMS
	struct sockaddr_un	*sa_un_ptr, sa_un_trans;
	mval			localpath;
	mstr			transpath;
	int			trans_status;
#endif
	enum socket_protocol	protocol;
	int			af;
	int			sd;
	int			errcode;
	char			host_buffer[NI_MAXHOST];
	char			port_buffer[NI_MAXSERV];
	int			port_buffer_len;
	int			colon_cnt, protooffset;
	char			*last_2colon = NULL;
	int			addrlen;
	GTM_SOCKLEN_TYPE	tmp_addrlen;

	if (0 > file_des)
	{	/* no socket descriptor yet */
		memset(&hints, 0, SIZEOF(hints));

		protooffset = colon_cnt = 0;
		sockaddrlen = STRLEN(sockaddr);
		for (ii = sockaddrlen - 1; 0 <= ii; ii--)
		{
			if (SEPARATOR == sockaddr[ii])
			{
				colon_cnt++;
				if (1 == colon_cnt)
					protooffset = ii + 1;
				else
				{
					last_2colon = &sockaddr[ii];
					break;
				}
			}
		}
		if (0 == colon_cnt)
		{
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVPORTSPEC);
			return NULL;
		}
		tmplen = sockaddrlen - protooffset;
		if (SIZEOF(protocolstr) <= tmplen)
		{	/* last piece just too big to be valid */
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PROTNOTSUP, 2, tmplen , &sockaddr[protooffset]);
			return NULL;
		}
		lower_to_upper((uchar_ptr_t)protocolstr, (uchar_ptr_t)&sockaddr[protooffset], tmplen);
		if (((SIZEOF("TCP") - 1) == tmplen) && (0 == MEMCMP_LIT(protocolstr, "TCP")))
			protocol = socket_tcpip;
#		ifndef VMS
		else if (((SIZEOF("LOCAL") - 1) == tmplen) && (0 == MEMCMP_LIT(protocolstr, "LOCAL")))
			protocol = socket_local;
#		endif
		else
		{
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PROTNOTSUP, 2, tmplen , &sockaddr[protooffset]);
			return NULL;
		}
		if (socket_tcpip == protocol)
		{
			if (1 == colon_cnt)
			{	/* for listening socket or broadcasting socket */
				if (!listen_specified || (SSCANF(sockaddr, PORT_PROTO_FORMAT, &port, protocolstr) < 2))
				{
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVPORTSPEC);
					return NULL;
				}
				passive = TRUE;
				/* We always first try using IPv6 address, if supported */
				af = ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET);
				if (-1 == (sd = socket(af, SOCK_STREAM, IPPROTO_TCP)))
				{
					/* Try creating IPv4 socket */
					af = AF_INET;
					if (-1 == (sd = socket(af, SOCK_STREAM, IPPROTO_TCP)))
					{
						save_errno = errno;
						errptr = (char *)STRERROR(save_errno);
						errlen = STRLEN(errptr);
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, save_errno,
							errlen, errptr);
						return NULL;
					}
				}
				SERVER_HINTS(hints, af);
				port_buffer_len = 0;
				I2A(port_buffer, port_buffer_len, port);
				port_buffer[port_buffer_len]='\0';
				if (0 != (errcode = getaddrinfo(NULL, port_buffer, &hints, &addr_info_ptr)))
				{
					close(sd);
					RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode);
					return NULL;
				}
				SOCKET_ALLOC(socketptr);
				socketptr->local.port = port;
				socketptr->temp_sd = sd;
				socketptr->sd = FD_INVALID;
				ai_ptr = &(socketptr->local.ai);
				memcpy(ai_ptr, addr_info_ptr, SIZEOF(struct addrinfo));
				SOCKET_AI_TO_LOCAL_ADDR(socketptr, addr_info_ptr);
				ai_ptr->ai_addr = SOCKET_LOCAL_ADDR(socketptr);
				ai_ptr->ai_addrlen = addr_info_ptr->ai_addrlen;
				ai_ptr->ai_next = NULL;
				freeaddrinfo(addr_info_ptr);
			} else
			{	/* connection socket */
				assert(2 == colon_cnt);
				if (listen_specified || (SSCANF(last_2colon + 1, PORT_PROTO_FORMAT, &port, protocolstr) < 2))
				{
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC);
					return NULL;
				}
				/* for connection socket */
				SPRINTF(port_buffer, "%hu", port);
				addrlen = last_2colon - sockaddr;
				if ('[' == sockaddr[0])
				{
					if (NULL == memchr(sockaddr, ']', addrlen))
					{
						rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC);
						return NULL;
					}
					addrlen -= 2;
					memcpy(temp_addr, &sockaddr[1], addrlen);
				} else
					memcpy(temp_addr, sockaddr, addrlen);
				temp_addr[addrlen] = 0;
				CLIENT_HINTS(hints);
				if (0 != (errcode = getaddrinfo(temp_addr, port_buffer, &hints, &addr_info_ptr)))
				{
					RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode);
					return NULL;
				}
				/*  we will test all address families in iosocket_connect() */
				SOCKET_ALLOC(socketptr);
				socketptr->remote.ai_head = addr_info_ptr;
				socketptr->remote.port = port;
				socketptr->sd = socketptr->temp_sd = FD_INVALID; /* don't mess with 0 */
			}
#		ifndef VMS
		} else if (socket_local == protocol)
		{	/* should we get_full_path first */
			/* check protooffset < sizeof sun_path */
			/* protooffset is after colon */
			SOCKET_ALLOC(socketptr);
			socketptr->protocol = socket_local;
			sa_un_ptr = malloc(SIZEOF(struct sockaddr_un));
			sa_un_ptr->sun_family = AF_UNIX;
			MV_INIT_STRING(&localpath, protooffset - 1, sockaddr);
			trans_status = TRANS_LOG_NAME(&localpath.str, &transpath, sa_un_trans.sun_path,
				(int)SIZEOF(sa_un_trans.sun_path), dont_sendmsg_on_log2long);
			if (SS_LOG2LONG == trans_status)
			{	/* if LOG2LONG, returned len not valid so report untranslated length */
				SOCKET_FREE(socketptr);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ADDRTOOLONG, 4, localpath.str.len, localpath.str.addr,
					localpath.str.len, SIZEOF(sa_un_trans.sun_path));
				return NULL;
			}
			memcpy(sa_un_ptr->sun_path, transpath.addr, transpath.len);
			sa_un_ptr->sun_path[transpath.len] = '\0';
			if (listen_specified)
			{
				passive = TRUE;
				socketptr->local.sa = (struct sockaddr *)sa_un_ptr;
				socketptr->local.ai.ai_family = AF_UNIX;
				socketptr->local.ai.ai_socktype = SOCK_STREAM;
				socketptr->local.ai.ai_addrlen = (size_t)((struct sockaddr_un *)0)->sun_path + protooffset;
				if (-1 == (sd = socket(AF_UNIX, SOCK_STREAM, 0)))
				{
					save_errno = errno;
					SOCKET_FREE(socketptr);
					errptr = (char *)STRERROR(save_errno);
					errlen = STRLEN(errptr);
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, save_errno, errlen, errptr);
					return NULL;
				}
				socketptr->temp_sd = sd;
				socketptr->sd = FD_INVALID;
			} else
			{
				socketptr->remote.sa = (struct sockaddr *)sa_un_ptr;
				/* setup remote fields */
				socketptr->remote.ai.ai_family = AF_UNIX;
				socketptr->remote.ai.ai_socktype = SOCK_STREAM;
				socketptr->remote.ai.ai_addrlen = (size_t)((struct sockaddr_un *)0)->sun_path + protooffset;
				socketptr->sd = socketptr->temp_sd = FD_INVALID; /* don't mess with 0 */
			}
#		endif
		} else
void	iosocket_use(io_desc *iod, mval *pp)
{
	unsigned char	ch, len;
	int		handled_len, handlea_len, handles_len, int_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, *free_ozff = NULL;
	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,
		        flush_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;

        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_csa(CSA_ARG(NULL) 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 = (int)(*(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_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_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;
				int_len = (int)(*(pp->str.addr + p_offset));
				if (int_len < USR_SA_MAXLITLEN)
				{
					memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), int_len);
					sockaddr[int_len] = '\0';
				} else
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ADDRTOOLONG,
						  4, int_len, pp->str.addr + p_offset + 1, int_len, USR_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_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) 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;
				int_len = (int)(*(pp->str.addr + p_offset));
				if (int_len < USR_SA_MAXLITLEN)
				{
					memcpy(sockaddr, (char *)(pp->str.addr + p_offset + 1), int_len);
					sockaddr[int_len] = '\0';
				} else
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ADDRTOOLONG,
						  4, int_len, pp->str.addr + p_offset + 1, int_len, USR_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_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG);
				else if (MAX_MOREREAD_TIMEOUT < moreread_timeout)
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_MRTMAXEXCEEDED, 1, MAX_MOREREAD_TIMEOUT);
                                moreread_specified = TRUE;
                                break;
			case iop_flush:
				n_specified++;
				flush_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_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ANCOMPTINC, 4, LEN_AND_LIT("DETACH"), LEN_AND_LIT("USE"));
			return;
		}
		if (NULL == socket_pool)
		{
			iosocket_poolinit();
			memcpy(newdsocket, dsocketptr, d_socket_struct_len);
		}
		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_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ANCOMPTINC, 4, LEN_AND_LIT("ATTACH"), LEN_AND_LIT("USE"));
			return;
		}
		if (NULL == socket_pool)
		{
			rts_error_csa(CSA_ARG(NULL) 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, listen_specified)))
                        return;
		if (gtm_max_sockets <= newdsocket->n_socket)
		{
			if (FD_INVALID != socketptr->temp_sd)
				close(socketptr->temp_sd);
			SOCKET_FREE(socketptr);
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets);
			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 */
#ifndef		VMS
		socketptr->filemode_mask = 0;
		socketptr->uic.mem = (uid_t)-1;
		socketptr->uic.grp = (gid_t)-1;
#endif
	} 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_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKNOTFND, 2, handles_len, handles);
				return;
			}
			newdsocket->current_socket = index;
			socketptr = newdsocket->socket[index];
			if ((1 == n_specified) && (socket_listening == socketptr->state))
			{	/* accept a new connection if there is one */
				socketptr->pendingevent = FALSE;
				iod->dollar.key[0] = '\0';
				save_errno = iosocket_accept(dsocketptr, socketptr, TRUE);
				return;
			}
		} else
		{
			if (0 >= newdsocket->n_socket)
			{
#				ifndef VMS
				if (iod == io_std_device.out)
					ionl_use(iod, pp);
				else
#				endif
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_NOSOCKETINDEV);
				return;
			}
     			if (newdsocket->n_socket <= newdsocket->current_socket)
	     		{
				assert(FALSE);
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CURRSOCKOFR, 2, newdsocket->current_socket,
						newdsocket->n_socket);
     				return;
     			}
			socketptr = newdsocket->socket[newdsocket->current_socket];
		}
		socketptr->temp_sd = FD_INVALID;
	}
	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));
		socketptr->n_delimiter = 0;	/* prevent double frees if error */
	}
	if (iod->wrap && 0 != newsocket.n_delimiter && iod->width < newsocket.delimiter[0].len)
		rts_error_csa(CSA_ARG(NULL) 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 (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.
			*/
			utf8_len_strict(zff_buffer, zff_len);
		}
		if ((NULL != newsocket.ozff.addr) && (socketptr->ozff.addr != socketptr->zff.addr))
			free_ozff = newsocket.ozff.addr;	/* previously converted */
		if (NULL == newsocket.zff.addr) /* we rely on newsocket.zff.addr being set to 0 in iosocket_create() */
		{
			socketptr->zff.addr = newsocket.zff.addr = (char *)malloc(MAX_ZFF_LEN);
			socketptr->zff.len = zff_len;		/* in case error so SOCKET_FREE frees */
		}
		memcpy(newsocket.zff.addr, zff_buffer, zff_len);
		newsocket.ozff = newsocket.zff;
	} else if (0 == zff_len)
	{
		if ((NULL != newsocket.ozff.addr) && (socketptr->ozff.addr != socketptr->zff.addr))
			free_ozff = newsocket.ozff.addr;	/* previously converted */
		newsocket.ozff = newsocket.zff;

	}
	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 (flush_specified)
			iosocket_flush(iod);	/* buffered output if any */
		if (bfsize_specified)
			newsocket.buffer_size = bfsize;
#ifdef TCP_NODELAY
		if (socket_local != newsocket.protocol)
		{
			nodelay = newsocket.nodelay ? 1 : 0;
			if ((socketptr->nodelay != newsocket.nodelay) &&
			    (-1 == setsockopt(newsocket.sd, IPPROTO_TCP,
						      TCP_NODELAY, &nodelay, SIZEOF(nodelay))))
			{
				save_errno = errno;
				errptr = (char *)STRERROR(save_errno);
                		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("TCP_NODELAY"),
					save_errno, LEN_AND_STR(errptr));
				return;
			}
		}
#endif
		if ((socketptr->bufsiz != newsocket.bufsiz) &&
		    (-1 == setsockopt(newsocket.sd, SOL_SOCKET,
						      SO_RCVBUF, &newsocket.bufsiz, SIZEOF(newsocket.bufsiz))))
		{
			save_errno = errno;
			errptr = (char *)STRERROR(save_errno);
                	rts_error_csa(CSA_ARG(NULL) 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_csa(CSA_ARG(NULL) 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, FALSE))
			|| (!iosocket_listen_sock(&newsocket, DEFAULT_LISTEN_DEPTH))))
		|| (connect_specified && (!iosocket_connect(&newsocket, 0, ibfsize_specified))))
        {	/* error message should be printed from bind/connect */
                if (socketptr->sd > 0)
                        (void)close(socketptr->sd);
		SOCKET_FREE(socketptr);
                return;
        }
	/* ------------------------------------ commit changes -------------------------------------- */
	if (create_new_socket)
	{
		/* 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 (NULL != free_ozff)
			free(free_ozff);
		if (socketptr->buffer_size != newsocket.buffer_size)
			free(socketptr->buffer);
	}
	*socketptr = newsocket;
	memcpy(dsocketptr, newdsocket, d_socket_struct_len);
	return;
}
Beispiel #5
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);
        }
    }
}