Пример #1
0
static int crt_image_beginenum(imgtool_image *img, imgtool_directory **outenum)
{
	crt_image *image=(crt_image*)img;
	crt_iterator *iter;

	iter=*(crt_iterator**)outenum = (crt_iterator *) malloc(sizeof(crt_iterator));
	if (!iter) return IMGTOOLERR_OUTOFMEMORY;

	iter->base.module = img->module;

	iter->image=image;
	iter->pos = GET_ULONG( HEADER(image)->length );
	iter->number = 0;
	return 0;
}
Пример #2
0
static int crt_image_deletefile(imgtool_image *img, const char *fname)
{
	crt_image *image=(crt_image*)img;
	int size;
	int pos;

	if (!(pos=crt_image_findfile(image, fname)) ) {
		return IMGTOOLERR_MODULENOTFOUND;
	}
	size=GET_ULONG(PACKET(image, pos)->packet_length);
	if (image->size-pos-size>0)
		memmove(image->data+pos, image->data+pos+size, image->size-pos-size);
	image->size-=size;
	image->modified=1;

	return 0;
}
Пример #3
0
static int crt_image_writefile(imgtool_image *img, const char *fname, imgtool_stream *sourcef,
							   const ResolvedOption *_options)
{
	crt_image *image=(crt_image*)img;
	int size;
	int pos;

	size=stream_size(sourcef);
	if (!(pos=crt_image_findfile(image, fname)) ) {
		// appending
		pos=image->size;
		if (!(image->data=realloc(image->data, image->size+size+sizeof(crt_packet))) )
			return IMGTOOLERR_OUTOFMEMORY;
		image->size+=size+sizeof(crt_packet);
	} else {
		int oldsize=GET_ULONG(PACKET(image,pos)->packet_length);
		// overwritting
		if (!(image->data=realloc(image->data, image->size+size+sizeof(crt_packet)-oldsize) ) )
			return IMGTOOLERR_OUTOFMEMORY;
		if (image->size-pos-oldsize!=0) {
			memmove(image->data+pos+size+sizeof(crt_packet), image->data+pos+oldsize,
					image->size-pos-oldsize);
		}
		image->size+=size+sizeof(crt_packet)-oldsize;
	}
	if (stream_read(sourcef, image->data+pos+sizeof(crt_packet), size)!=size) {
		return IMGTOOLERR_READERROR;
	}
	memset(image->data+pos, 0, sizeof(crt_packet));
	memcpy(PACKET(image,pos)->id,"CHIP",4);
	SET_ULONG( PACKET(image, pos)->packet_length, size+sizeof(crt_packet));
	SET_UWORD(PACKET(image, pos)->chip_type, _options[C64CRT_FILEOPTION_FTYPE].i);
	SET_UWORD( PACKET(image, pos)->address, _options[C64CRT_FILEOPTION_FADDR].i);
	SET_UWORD( PACKET(image, pos)->bank, _options[C64CRT_FILEOPTION_FBANK].i);
	SET_UWORD( PACKET(image, pos)->length, size);

	image->modified=1;

	return 0;
}
Пример #4
0
static int crt_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
{
	crt_iterator *iter=(crt_iterator*)enumeration;

	ent->corrupt=0;

	if (!(ent->eof=(iter->pos>=iter->image->size))) {
		sprintf(ent->fname,"%d", iter->number);
		ent->filesize=GET_UWORD( PACKET(iter->image, iter->pos)->length );
		if (ent->attr) {
		    unsigned crc=crc32(0, iter->image->data+iter->pos+sizeof(crt_packet), ent->filesize);
			sprintf(ent->attr,"%-4s %s bank:%-2d addr:%.4x crc:%8x",
					(char*)PACKET(iter->image, iter->pos),
					chip_types[GET_UWORD(PACKET(iter->image,iter->pos)->chip_type)],
					GET_UWORD( PACKET(iter->image,iter->pos)->bank),
					GET_UWORD( PACKET(iter->image,iter->pos)->address),
				crc);
		}
		iter->number++;

		iter->pos+=GET_ULONG( PACKET(iter->image, iter->pos)->packet_length );
	}
	return 0;
}
Пример #5
0
int do_patalt(uint4 *firstalt, unsigned char *strptr, unsigned char *strtop, int4 repmin, int4 repmax, int totchar, int repcnt,
											int4 min_incr, int4 max_incr)
{
	boolean_t	fixed;
	int4		alt_tot_min, alt_tot_max, new_pte_csh_size, tmp_do_patalt_calls;
	uint4		*cur_alt, tempuint;
	uint4		*patptr;
	int		match, alt_size, charlen, bytelen, pat_found;
	mval		alt_pat, alt_str;
	pte_csh		*tmp_pte;
	unsigned char	*strtmp, *strnext;

	if (PTE_MAX_CURALT_DEPTH > curalt_depth)
	{	/* try to find it in the current pattern evaluation cache (cur_pte_csh_array) itself */
		tmp_do_patalt_calls = ++do_patalt_calls[curalt_depth];
		pat_found = pte_csh_present((char *)firstalt, (char *)strptr, totchar, repcnt);
		if (PTE_NOT_FOUND != pat_found)
		{
			do_patalt_hits[curalt_depth]++;
			return pat_found;
		} else if ((tmp_do_patalt_calls > cur_pte_csh_size)
			&& ((tmp_do_patalt_calls - do_patalt_hits[curalt_depth]) > (tmp_do_patalt_calls / PTE_CSH_MISS_FACTOR)))
		{	/* lots of cache miss happening. try to increase pt_csh_array size */
			do_patalt_hits[curalt_depth] = do_patalt_calls[curalt_depth] = 1;
			new_pte_csh_size = cur_pte_csh_size;
			if (cur_pte_csh_size < pte_csh_alloc_size[curalt_depth])
			{
				new_pte_csh_size = (cur_pte_csh_size << 1);
				assert(cur_pte_csh_size <= pte_csh_alloc_size[curalt_depth]);
			} else if (PTE_MAX_ENTRIES > pte_csh_alloc_size[curalt_depth])
			{
				new_pte_csh_size = (cur_pte_csh_size << 1);
				tmp_pte = malloc(SIZEOF(pte_csh) * new_pte_csh_size);
				free(cur_pte_csh_array);
				pte_csh_alloc_size[curalt_depth] = new_pte_csh_size;
				pte_csh_array[curalt_depth] = tmp_pte;
				cur_pte_csh_array = pte_csh_array[curalt_depth];
			} else
				do_patalt_maxed_out[curalt_depth]++;
			if (new_pte_csh_size != cur_pte_csh_size)
			{
				memset(pte_csh_array[curalt_depth], 0, SIZEOF(pte_csh) * new_pte_csh_size);
				pte_csh_cur_size[curalt_depth] *= 2;
				pte_csh_entries_per_len[curalt_depth] *= 2;
				pte_csh_tail_count[curalt_depth] *= 2;
				UPDATE_CUR_PTE_CSH_MINUS_ARRAY(cur_pte_csh_size,
								cur_pte_csh_entries_per_len, cur_pte_csh_tail_count);
			}
		}
	}
	alt_pat.mvtype = MV_STR;
	alt_str.mvtype = MV_STR;
	alt_str.str.addr = (char *)strptr;
	patptr = firstalt;
	GET_LONG(alt_size, patptr);
	patptr++;
	for (match = FALSE; !match && alt_size; patptr++)
	{
		cur_alt = patptr;
		cur_alt++;
		GET_ULONG(tempuint, cur_alt);
		cur_alt++;
		cur_alt += tempuint;
		GET_LONG(alt_tot_min, cur_alt);
		cur_alt++;
		if (alt_tot_min <= totchar)
		{
			GET_LONG(tempuint, cur_alt);
			GET_LONG(fixed, patptr);
			/* Note that some patterns whose minimum and maximum length are the same need not have
			 * "fixed" field 1. This is because alternations which have choices that all evaluate
			 * to the same length (e.g. 5(2l,2e,"ab")) are currently not recognizable by do_patfixed
			 * and hence go through do_pattern.
			 */
			assert(!fixed || (alt_tot_min == tempuint));
			alt_tot_max = (tempuint < totchar) ? tempuint : totchar;
			alt_pat.str.addr = (char *)patptr;
			alt_pat.str.len = alt_size * SIZEOF(uint4);
			/* Note that the below zero min length avoiding code is actually an optimization.
			 * This is because if we start from length 0, we will end up matching the input string and in case
			 * 	the alternation pattern's max count is huge (e.g. PAT_MAX) we will end up recursing
			 * 	in do_patalt() as many times each time matching a length of 0, without realizing we are
			 * 	not progressing anywhere in the match by matching a huge number of empty strings.
			 * This will effectively cause a combinatorial explosion to occur in case there are at least 2 choices
			 * 	in the alternation pattern (which usually will be the case) since the choices that need to be
			 * 	examined are 2 ** PAT_MAX.
			 * Instead, if we start from length 1, every level of recursion we decrease the size of the problem
			 * 	by matching a non-zero length of the input string and hence we can't progress much in the
			 * 	recursion levels before starting to backtrack, thereby avoiding the explosion.
			 * Note that we do have to consider zero length in case we haven't yet exhausted our minimum count of
			 * 	the alternation pattern and we have a null input string remaining to be matched.
			 * Hence the if check below.
			 */
			if (totchar && (0 == alt_tot_min))
				alt_tot_min = 1;	/* avoid zero min length when non-zero string still needs to be matched */
			if (!gtm_utf8_mode)
			{	/* each character is 1 byte so charlen and bytelen is same */
				charlen = alt_tot_min;
				bytelen = alt_tot_min;
			}
			UNICODE_ONLY(
			else
			{	/* skip alt_tot_min characters */
				strtmp = strptr;
				for (charlen = 0; charlen < alt_tot_min; charlen++)
				{
					assert(strtmp < strtop);
					strtmp = UTF8_MBNEXT(strtmp, strtop);
				}
				bytelen = (int)(strtmp - strptr);
			}
			)
			UNICODE_ONLY(
				if (gtm_utf8_mode)
					alt_str.mvtype |= MV_UTF_LEN;	/* avoid recomputing "char_len" in do_pattern/do_patfixed */
			)
			for ( ; !match && (charlen <= alt_tot_max); charlen++)
Пример #6
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;
}