void iomt_use(io_desc *iod, mval *pp) { unsigned char ch, len; int lab_type; int4 length, width; int4 skips; d_mt_struct *mt_ptr, *out_ptr; io_desc *d_in, *d_out; mident tab; int p_offset; error_def(ERR_MTINVLAB); error_def(ERR_DEVPARMNEG); error_def(ERR_UNIMPLOP); p_offset = 0; d_in = iod->pair.in; d_out = iod->pair.out; mt_ptr = (d_mt_struct *)iod->dev_sp; out_ptr = (d_mt_struct *)d_out->dev_sp; while (*(pp->str.addr + p_offset) != iop_eol) { switch (ch = *(pp->str.addr + p_offset++)) { case iop_ebcdic: mt_ptr->ebcdic = TRUE; break; case iop_noebcdic: mt_ptr->ebcdic = FALSE; break; case iop_newversion: mt_ptr->newversion = TRUE; break; case iop_label: memset(tab.c, 0, sizeof(mident)); len = *(pp->str.addr + p_offset); memcpy(tab.c, (pp->str.addr + p_offset + 1), (len < sizeof(mident) ? len : sizeof(mident))); if ((lab_type = namelook(mtlab_index, mtlab_names, tab.c)) < 0) rts_error(VARLSTCNT(1) ERR_MTINVLAB); mt_ptr->labeled = mtlab_type[lab_type]; break; case iop_nolabel: mt_ptr->labeled = FALSE; break; case iop_rdcheckdata: mt_ptr->read_mask |= IO_M_DATACHECK; break; case iop_nordcheckdata: mt_ptr->read_mask &= (~(IO_M_DATACHECK)); break; case iop_wtcheckdata: mt_ptr->write_mask |= IO_M_DATACHECK; break; case iop_nowtcheckdata: mt_ptr->write_mask &= (~(IO_M_DATACHECK)); break; case iop_inhretry: mt_ptr->write_mask |= IO_M_INHRETRY; mt_ptr->read_mask |= IO_M_INHRETRY; break; case iop_retry: mt_ptr->write_mask &= ~IO_M_INHRETRY; mt_ptr->read_mask &= ~IO_M_INHRETRY; break; case iop_inhextgap: mt_ptr->write_mask |= IO_M_INHEXTGAP; break; case iop_extgap: mt_ptr->write_mask &= ~IO_M_INHEXTGAP; 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: GET_LONG(width, (pp->str.addr + p_offset)); if (width < 0) rts_error(VARLSTCNT(1) ERR_DEVPARMNEG); if (width == 0) { iod->wrap = FALSE; iod->width = mt_ptr->record_sz; } else if (width <= mt_ptr->record_sz) { iomt_flush(iod); iod->width = width; iod->wrap = TRUE; } break; case iop_wrap: out_ptr->wrap = TRUE; break; case iop_nowrap: out_ptr->wrap = FALSE; break; case iop_skipfile: GET_LONG(skips, (pp->str.addr + p_offset)); iomt_skipfile(iod, skips); break; case iop_unload: assert(FALSE); break; case iop_rewind: iomt_rewind(iod); break; case iop_erasetape: iomt_erase(iod); break; case iop_space: GET_LONG(skips, (pp->str.addr + p_offset)); iomt_skiprecord(iod, skips); break; case iop_writeof: iomt_eof(iod); break; case iop_writetm: iomt_tm(iod); break; case iop_writelb: memset(&tab, 0, sizeof(mident)); len = *(pp->str.addr + p_offset); memcpy(&tab.c[0], pp->str.addr + p_offset + 1, (len < sizeof(mident) ? len : sizeof(mident))); if ((lab_type = namelook(mtwtlab_index, mtwtlab_names, tab.c)) < 0) rts_error(VARLSTCNT(1) ERR_MTINVLAB); iomt_wtansilab(iod, mtwtlab_type[lab_type]); break; case iop_next: rts_error(VARLSTCNT(1) ERR_UNIMPLOP); break; case iop_exception: iod->error_handler.len = *(pp->str.addr + p_offset); iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1); s2pool(&iod->error_handler); break; case iop_ipchset: { if ( (iconv_t)0 != iod->input_conv_cd ) { ICONV_CLOSE_CD(iod->input_conv_cd); } SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->in_code_set) ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET); break; } case iop_opchset: { if ( (iconv_t) 0 != iod->output_conv_cd ) { ICONV_CLOSE_CD(iod->output_conv_cd); } SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->out_code_set) ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1)); break; } default: break; } p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]); } }
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; }
void iott_use(io_desc *iod, mval *pp) { boolean_t flush_input; char dc1, *ttab; d_tt_struct *temp_ptr, *tt_ptr; int p_offset, fil_type, save_errno, status; int4 length, width; io_desc *d_in, *d_out; io_termmask mask_term; struct sigaction act; struct termios t; uint4 mask_in; unsigned char ch, len; boolean_t ch_set; p_offset = 0; assert(iod->state == dev_open); ESTABLISH_GTMIO_CH(&iod->pair, ch_set); iott_flush(iod); tt_ptr = (d_tt_struct *)iod->dev_sp; if (*(pp->str.addr + p_offset) != iop_eol) { if (tt_ptr->mupintr) if (dollar_zininterrupt) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO); else { /* The interrupted read was not properly resumed so clear it now */ tt_ptr->mupintr = FALSE; tt_ptr->tt_state_save.who_saved = ttwhichinvalid; io_find_mvstent(iod, TRUE); } status = tcgetattr(tt_ptr->fildes, &t); if (0 != status) { save_errno = errno; ISSUE_NOPRINCIO_IF_NEEDED_TT(io_curr_device.out); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TCGETATTR, 1, tt_ptr->fildes, save_errno); } flush_input = FALSE; d_in = iod->pair.in; d_out = iod->pair.out; temp_ptr = (d_tt_struct *)d_in->dev_sp; mask_in = temp_ptr->term_ctrl; mask_term = temp_ptr->mask_term; while (*(pp->str.addr + p_offset) != iop_eol) { switch (ch = *(pp->str.addr + p_offset++)) { case iop_canonical: tt_ptr->canonical = TRUE; t.c_lflag |= ICANON; break; case iop_nocanonical: tt_ptr->canonical = FALSE; t.c_lflag &= ~(ICANON); break; case iop_empterm: tt_ptr->ext_cap |= TT_EMPTERM; break; case iop_noempterm: tt_ptr->ext_cap &= ~TT_EMPTERM; break; case iop_cenable: if (!ctrlc_on) { /* if it's already cenable, no need to change */ temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp; if (tt_ptr->fildes == temp_ptr->fildes) { /* if this is $PRINCIPAL make sure the ctrlc_handler is enabled */ sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = ctrlc_handler_ptr; sigaction(SIGINT, &act, 0); ctrlc_on = TRUE; } } break; case iop_nocenable: if (ctrlc_on) { /* if it's already nocenable, no need to change */ temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp; if (tt_ptr->fildes == temp_ptr->fildes) { /* if this is $PRINCIPAL may disable the ctrlc_handler */ if (0 == (CTRLC_MSK & tt_ptr->enbld_outofbands.mask)) { /* but only if ctrap=$c(3) is not active */ sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = SIG_IGN; sigaction(SIGINT, &act, 0); } ctrlc_on = FALSE; } } break; case iop_clearscreen: if (NULL != CLR_EOS) gtm_tputs(CLR_EOS, 1, outc); break; case iop_convert: mask_in |= TRM_CONVERT; break; case iop_noconvert: mask_in &= ~TRM_CONVERT; break; case iop_ctrap: GET_LONG(tt_ptr->enbld_outofbands.mask, pp->str.addr + p_offset); if (!ctrlc_on) { /* if cenable, ctrlc_handler active anyway, otherwise, depends on ctrap=$c(3) */ sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = (CTRLC_MSK & tt_ptr->enbld_outofbands.mask) ? ctrlc_handler_ptr : SIG_IGN; sigaction(SIGINT, &act, 0); } break; case iop_downscroll: if (d_out->dollar.y > 0) { d_out->dollar.y--; if (NULL != CURSOR_ADDRESS) gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc); } break; case iop_echo: mask_in &= (~TRM_NOECHO); break; case iop_noecho: mask_in |= TRM_NOECHO; break; case iop_editing: if (io_curr_device.in == io_std_device.in) { /* $PRINCIPAL only */ tt_ptr->ext_cap |= TT_EDITING; if (!tt_ptr->recall_buff.addr) { assert(tt_ptr->in_buf_sz); tt_ptr->recall_buff.addr = malloc(tt_ptr->in_buf_sz); tt_ptr->recall_size = tt_ptr->in_buf_sz; tt_ptr->recall_buff.len = 0; /* nothing in buffer */ } } break; case iop_noediting: if (io_curr_device.in == io_std_device.in) tt_ptr->ext_cap &= ~TT_EDITING; /* $PRINCIPAL only */ break; case iop_escape: mask_in |= TRM_ESCAPE; break; case iop_noescape: mask_in &= (~TRM_ESCAPE); default: break; case iop_eraseline: if (NULL != CLR_EOL) gtm_tputs(CLR_EOL, 1, outc); break; case iop_exception: iod->error_handler.len = *(pp->str.addr + p_offset); iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1); s2pool(&iod->error_handler); break; case iop_filter: len = *(pp->str.addr + p_offset); ttab = pp->str.addr + p_offset + 1; if ((fil_type = namelook(filter_index, filter_names, ttab, len)) < 0) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TTINVFILTER); return; } switch (fil_type) { case 0: iod->write_filter |= CHAR_FILTER; break; case 1: iod->write_filter |= ESC1; break; case 2: iod->write_filter &= ~CHAR_FILTER; break; case 3: iod->write_filter &= ~ESC1; break; } break; case iop_nofilter: iod->write_filter = 0; break; case iop_flush: flush_input = TRUE; break; case iop_hostsync: t.c_iflag |= IXOFF; break; case iop_nohostsync: t.c_iflag &= ~IXOFF; break; case iop_insert: if (io_curr_device.in == io_std_device.in) tt_ptr->ext_cap &= ~TT_NOINSERT; /* $PRINCIPAL only */ break; case iop_noinsert: if (io_curr_device.in == io_std_device.in) tt_ptr->ext_cap |= TT_NOINSERT; /* $PRINCIPAL only */ break; case iop_length: GET_LONG(length, pp->str.addr + p_offset); if (0 > length) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG); d_out->length = length; break; case iop_pasthru: mask_in |= TRM_PASTHRU; break; case iop_nopasthru: mask_in &= (~TRM_PASTHRU); break; case iop_readsync: mask_in |= TRM_READSYNC; break; case iop_noreadsync: dc1 = (char)17; temp_ptr = (d_tt_struct *)io_std_device.in->dev_sp; DOWRITERC(temp_ptr->fildes, &dc1, 1, status); if (0 != status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status); mask_in &= (~TRM_READSYNC); break; case iop_terminator: memcpy(&mask_term.mask[0], (pp->str.addr + p_offset), SIZEOF(io_termmask)); temp_ptr = (d_tt_struct *)d_in->dev_sp; if (mask_term.mask[0] == NUL && mask_term.mask[1] == NUL && mask_term.mask[2] == NUL && mask_term.mask[3] == NUL && mask_term.mask[4] == NUL && mask_term.mask[5] == NUL && mask_term.mask[6] == NUL && mask_term.mask[7] == NUL) { temp_ptr->default_mask_term = TRUE; if (CHSET_UTF8 == d_in->ichset) { mask_term.mask[0] = TERM_MSK_UTF8_0; mask_term.mask[4] = TERM_MSK_UTF8_4; } else mask_term.mask[0] = TERM_MSK; } else temp_ptr->default_mask_term = FALSE; break; case iop_noterminator: temp_ptr = (d_tt_struct *)d_in->dev_sp; temp_ptr->default_mask_term = FALSE; memset(&mask_term.mask[0], 0, SIZEOF(io_termmask)); break; case iop_ttsync: t.c_iflag |= IXON; break; case iop_nottsync: t.c_iflag &= ~IXON; break; case iop_typeahead: mask_in &= (~TRM_NOTYPEAHD); break; case iop_notypeahead: mask_in |= TRM_NOTYPEAHD; break; case iop_upscroll: d_out->dollar.y++; if (d_out->length) d_out->dollar.y %= d_out->length; if (NULL != CURSOR_ADDRESS) gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc); break; case iop_width: GET_LONG(width, pp->str.addr + p_offset); if (0 > width) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_DEVPARMNEG); /* Do not allow a WIDTH of 1 if UTF mode (ICHSET or OCHSET is not M) */ if ((1 == width) && ((CHSET_M != d_in->ochset) || (CHSET_M != d_in->ichset))) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_WIDTHTOOSMALL); if (0 == width) { d_out->wrap = FALSE; d_out->width = TTDEF_PG_WIDTH; } else { d_out->width = width; d_out->wrap = TRUE; } break; case iop_wrap: d_out->wrap = TRUE; break; case iop_nowrap: d_out->wrap = FALSE; break; case iop_x: GET_LONG(d_out->dollar.x, pp->str.addr + p_offset); if (0 > (int4)d_out->dollar.x) d_out->dollar.x = 0; if (d_out->dollar.x > d_out->width && d_out->wrap) { d_out->dollar.y += (d_out->dollar.x / d_out->width); if (d_out->length) d_out->dollar.y %= d_out->length; d_out->dollar.x %= d_out->width; } if (NULL != CURSOR_ADDRESS) gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc); break; case iop_y: GET_LONG(d_out->dollar.y, pp->str.addr + p_offset); if (0 > (int4)d_out->dollar.y) d_out->dollar.y = 0; if (d_out->length) d_out->dollar.y %= d_out->length; if (NULL != CURSOR_ADDRESS) gtm_tputs(gtm_tparm(CURSOR_ADDRESS, d_out->dollar.y, d_out->dollar.x), 1, outc); break; case iop_ipchset: { # ifdef KEEP_zOS_EBCDIC if ( (iconv_t)0 != iod->input_conv_cd ) { ICONV_CLOSE_CD(iod->input_conv_cd); } SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->in_code_set) ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET); # endif break; } case iop_opchset: { # ifdef KEEP_zOS_EBCDIC if ( (iconv_t)0 != iod->output_conv_cd) { ICONV_CLOSE_CD(iod->output_conv_cd); } SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->out_code_set) ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1)); # endif break; } } p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]); } temp_ptr = (d_tt_struct *)d_in->dev_sp; Tcsetattr(tt_ptr->fildes, TCSANOW, &t, status, save_errno); if (0 != status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TCSETATTR, 1, tt_ptr->fildes, save_errno); temp_ptr->term_ctrl = mask_in; memcpy(&temp_ptr->mask_term, &mask_term, SIZEOF(io_termmask)); if (flush_input) { TCFLUSH(tt_ptr->fildes, TCIFLUSH, status); if (0 != status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LIT_AND_LEN("tcflush input"), CALLFROM, errno); } } else if (tt_ptr->mupintr && !dollar_zininterrupt) { /* The interrupted read was not properly resumed so clear it now */ tt_ptr->mupintr = FALSE; tt_ptr->tt_state_save.who_saved = ttwhichinvalid; io_find_mvstent(iod, TRUE); /* clear mv stack entry */ } REVERT_GTMIO_CH(&iod->pair, ch_set); return; }
static bool mu_open_try(io_log_name *naml, io_log_name *tl, mval *pp, mval *mspace) { int4 status; int4 size; mstr tn; /* translated name */ mstr chset_mstr; int oflag; unsigned char ch; int file_des; struct stat outbuf; char *buf, namebuf[LOGNAME_LEN + 1]; d_mt_struct *mt_ptr; int umask_orig, umask_creat; int char_or_block_special; int fstat_res; int save_errno; int p_offset; boolean_t ichset_specified, ochset_specified; error_def(ERR_SYSCALL); mt_ptr = NULL; char_or_block_special = FALSE; file_des = -2; oflag = 0; tn.len = tl->len; if (tn.len > LOGNAME_LEN) tn.len = LOGNAME_LEN; tn.addr = tl->dollar_io; memcpy(namebuf, tn.addr, tn.len); namebuf[tn.len] = '\0'; buf = namebuf; if (0 == naml->iod) { if (0 == tl->iod) { tl->iod = (io_desc *)malloc(sizeof(io_desc)); memset((char*)tl->iod, 0, sizeof(io_desc)); tl->iod->pair.in = tl->iod; tl->iod->pair.out = tl->iod; tl->iod->trans_name = tl; tl->iod->type = n_io_dev_types; p_offset = 0; while(iop_eol != *(pp->str.addr + p_offset)) { ch = *(pp->str.addr + p_offset++); if (iop_sequential == ch) tl->iod->type = rm; if (IOP_VAR_SIZE == io_params_size[ch]) p_offset += *(pp->str.addr + p_offset) + 1; else p_offset += io_params_size[ch]; } } if ((n_io_dev_types == tl->iod->type) && mspace && mspace->str.len) tl->iod->type = us; if (n_io_dev_types == tl->iod->type) { if (0 == memvcmp(tn.addr, tn.len, sys_input.addr, sys_input.len)) { file_des = 0; FSTAT_FILE(file_des, &outbuf, fstat_res); if (-1 == fstat_res) { save_errno = errno; rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat()"), CALLFROM, save_errno); } } else { if (0 == memvcmp(tn.addr, tn.len, sys_output.addr, sys_output.len)) { file_des = 1; FSTAT_FILE(file_des, &outbuf, fstat_res); if (-1 == fstat_res) { save_errno = errno; rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat()"), CALLFROM, save_errno); } } else if (0 == memvcmp(tn.addr, tn.len, "/dev/null", 9)) tl->iod->type = nl; else if ((-1 == Stat(buf, &outbuf)) && (n_io_dev_types == tl->iod->type)) { if (ENOENT == errno) tl->iod->type = rm; else { save_errno = errno; rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat()"), CALLFROM, save_errno); } } } } if (n_io_dev_types == tl->iod->type) { switch(outbuf.st_mode & S_IFMT) { case S_IFCHR: case S_IFBLK: char_or_block_special = TRUE; break; case S_IFIFO: tl->iod->type = ff; break; case S_IFREG: case S_IFDIR: tl->iod->type = rm; break; case S_IFSOCK: case 0: tl->iod->type = ff; break; default: break; } } naml->iod = tl->iod; } active_device = naml->iod; if ((-2 == file_des) && (dev_open != naml->iod->state) && (us != naml->iod->type) && (tcp != naml->iod->type)) { oflag |= (O_RDWR | O_CREAT | O_NOCTTY); size = 0; p_offset = 0; ichset_specified = ochset_specified = FALSE; while(iop_eol != *(pp->str.addr + p_offset)) { assert((params) *(pp->str.addr + p_offset) < (params)n_iops); switch ((ch = *(pp->str.addr + p_offset++))) { case iop_allocation: if (rm == naml->iod->type) { GET_LONG(size, pp->str.addr + p_offset); size *= 512; } break; case iop_append: if (rm == naml->iod->type) oflag |= O_APPEND; break; case iop_contiguous: break; case iop_newversion: if ((dev_open != naml->iod->state) && (rm == naml->iod->type)) oflag |= O_TRUNC; break; case iop_readonly: oflag &= ~(O_RDWR | O_CREAT | O_WRONLY); oflag |= O_RDONLY; break; case iop_writeonly: oflag &= ~(O_RDWR | O_RDONLY); oflag |= O_WRONLY | O_CREAT; break; case iop_ipchset: #ifdef KEEP_zOS_EBCDIC if ( (iconv_t)0 != naml->iod->input_conv_cd ) { ICONV_CLOSE_CD(naml->iod->input_conv_cd); } SET_CODE_SET(naml->iod->in_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != naml->iod->in_code_set) ICONV_OPEN_CD(naml->iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET); break; #endif if (gtm_utf8_mode) { chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1); chset_mstr.len = *(pp->str.addr + p_offset); SET_ENCODING(naml->iod->ichset, &chset_mstr); ichset_specified = TRUE; } break; case iop_opchset: #ifdef KEEP_zOS_EBCDIC if ( (iconv_t)0 != naml->iod->output_conv_cd) { ICONV_CLOSE_CD(naml->iod->output_conv_cd); } SET_CODE_SET(naml->iod->out_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != naml->iod->out_code_set) ICONV_OPEN_CD(naml->iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1)); break; #endif if (gtm_utf8_mode) { chset_mstr.addr = (char *)(pp->str.addr + p_offset + 1); chset_mstr.len = *(pp->str.addr + p_offset); SET_ENCODING(naml->iod->ochset, &chset_mstr); ochset_specified = TRUE; } break; case iop_m: case iop_utf8: case iop_utf16: case iop_utf16be: case iop_utf16le: if (gtm_utf8_mode) { naml->iod->ichset = naml->iod->ochset = (iop_m == ch) ? CHSET_M : (iop_utf8 == ch) ? CHSET_UTF8 : (iop_utf16 == ch) ? CHSET_UTF16 : (iop_utf16be == ch) ? CHSET_UTF16BE : CHSET_UTF16LE; ichset_specified = ochset_specified = TRUE; } break; default: break; } if (IOP_VAR_SIZE == io_params_size[ch]) p_offset += *(pp->str.addr + p_offset) + 1; else p_offset += io_params_size[ch]; } if (!ichset_specified) naml->iod->ichset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M; if (!ochset_specified) naml->iod->ochset = (gtm_utf8_mode) ? CHSET_UTF8 : CHSET_M; if (CHSET_M != naml->iod->ichset && CHSET_UTF16 != naml->iod->ichset) get_chset_desc(&chset_names[naml->iod->ichset]); if (CHSET_M != naml->iod->ochset && CHSET_UTF16 != naml->iod->ochset) get_chset_desc(&chset_names[naml->iod->ochset]); /* RW permissions for owner and others as determined by umask. */ umask_orig = umask(000); /* determine umask (destructive) */ (void)umask(umask_orig); /* reset umask */ umask_creat = 0666 & ~umask_orig; /* * the check for EINTR below is valid and should not be converte d to an EINTR * wrapper macro, due to the other errno values being checked. */ while ((-1 == (file_des = OPEN4(buf, oflag, umask_creat, size)))) { if ( EINTR == errno || ETXTBSY == errno || ENFILE == errno || EBUSY == errno || ((mb == naml->iod->type) && (ENXIO == errno))) continue; else break; } if (-1 == file_des) return FALSE; } assert (tcp != naml->iod->type); #ifdef KEEP_zOS_EBCDIC SET_CODE_SET(naml->iod->in_code_set, OUTSIDE_CH_SET); if (DEFAULT_CODE_SET != naml->iod->in_code_set) ICONV_OPEN_CD(naml->iod->input_conv_cd, OUTSIDE_CH_SET, INSIDE_CH_SET); SET_CODE_SET(naml->iod->out_code_set, OUTSIDE_CH_SET); if (DEFAULT_CODE_SET != naml->iod->out_code_set) ICONV_OPEN_CD(naml->iod->output_conv_cd, INSIDE_CH_SET, OUTSIDE_CH_SET); #endif /* smw 99/12/18 not possible to be -1 here */ if (-1 == file_des) { rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("open()"), CALLFROM, save_errno); } if (n_io_dev_types == naml->iod->type) { if (isatty(file_des)) naml->iod->type = tt; else if (char_or_block_special && file_des > 2) /* assume mag tape */ naml->iod->type = mt; else naml->iod->type = rm; } assert(naml->iod->type < n_io_dev_types); naml->iod->disp_ptr = &io_dev_dispatch_mupip[naml->iod->type]; active_device = naml->iod; if (dev_never_opened == naml->iod->state) { naml->iod->wrap = DEFAULT_IOD_WRAP; naml->iod->width = DEFAULT_IOD_WIDTH; naml->iod->length = DEFAULT_IOD_LENGTH; naml->iod->write_filter = 0; /* MUPIP should not use FILTER */ } if (dev_open != naml->iod->state) { naml->iod->dollar.x = 0; naml->iod->dollar.y = 0; naml->iod->dollar.za = 0; naml->iod->dollar.zb[0] = 0; } status = (naml->iod->disp_ptr->open)(naml, pp, file_des, mspace, NO_M_TIMEOUT); if (TRUE == status) naml->iod->state = dev_open; else if (dev_open == naml->iod->state) naml->iod->state = dev_closed; if (1 == file_des) naml->iod->dollar.zeof = TRUE; active_device = 0; if (run_time) return (status); return TRUE; }
void iorm_use(io_desc *iod, mval *pp) { boolean_t fstat_done; unsigned char c; short mode, mode1; int4 length, width; long size; int fstat_res, save_errno; d_rm_struct *rm_ptr; struct stat statbuf; int p_offset; error_def(ERR_DEVPARMNEG); error_def(ERR_RMWIDTHPOS); error_def(ERR_RMWIDTHTOOBIG); error_def(ERR_SYSCALL); p_offset = 0; rm_ptr = (d_rm_struct *)iod->dev_sp; fstat_done = FALSE; while (*(pp->str.addr + p_offset) != iop_eol) { assert((params) *(pp->str.addr + p_offset) < (params)n_iops); switch (c = *(pp->str.addr + p_offset++)) { 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_fixed: if (iod->state != dev_open) rm_ptr->fixed = TRUE; break; case iop_nofixed: if (iod->state != dev_open) rm_ptr->fixed = FALSE; 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_w_protection: FSTAT_CHECK; mode &= ~(0x07); mode |= *(pp->str.addr + p_offset); break; case iop_g_protection: FSTAT_CHECK; mode &= ~(0x07 << 3); mode |= *(pp->str.addr + p_offset) << 3; break; case iop_s_protection: case iop_o_protection: FSTAT_CHECK; mode &= ~(0x07 << 6); mode |= *(pp->str.addr + p_offset) << 6; break; case iop_readonly: rm_ptr->noread = TRUE; break; case iop_noreadonly: rm_ptr->noread = FALSE; break; case iop_recordsize: GET_LONG(width, (pp->str.addr + p_offset)); if (width <= 0) rts_error(VARLSTCNT(1) ERR_RMWIDTHPOS); else if (MAX_STRLEN < width) rts_error(VARLSTCNT(1) ERR_RMWIDTHTOOBIG); iod->width = width; break; case iop_rewind: if (iod->state == dev_open && !rm_ptr->fifo) { iorm_flush(iod); if (lseek(rm_ptr->fildes, (off_t)0, SEEK_SET) == -1) rts_error(VARLSTCNT(1) errno); if (fseek(rm_ptr->filstr, (long)0, SEEK_SET) == -1) /* Rewind the input stream */ rts_error(VARLSTCNT(1) errno); iod->dollar.zeof = FALSE; iod->dollar.y = 0; iod->dollar.x = 0; rm_ptr->lastop = RM_NOOP; } break; case iop_stream: rm_ptr->stream = TRUE; break; case iop_truncate: if (!rm_ptr->fifo) { /* Warning! ftell() returns a long and fseek only accepts a long * as its second argument. this may cause problems for files longer * the 2Gb. */ if ((size = ftell(rm_ptr->filstr)) != -1) { int ftruncate_res; if (lseek(rm_ptr->fildes, (off_t)size, SEEK_SET) == -1) rts_error(VARLSTCNT(1) errno); FTRUNCATE(rm_ptr->fildes, (off_t)size, ftruncate_res); if (fseek(rm_ptr->filstr, size, SEEK_SET) == -1) rts_error(VARLSTCNT(1) errno); iod->dollar.zeof = TRUE; } } break; case iop_uic: { unsigned char *ch, ct, *end; int chown_res; uic_struct uic; ch = (unsigned char *)pp->str.addr + p_offset; ct = *ch++; end = ch + ct; uic.grp = uic.mem = 0; while ((*ch != ',') && (ch < end)) uic.mem = (10 * uic.mem) + (*ch++ - '0'); if (*ch == ',') { while (++ch < end) uic.grp = (10 * uic.grp) + (*ch - '0'); } CHG_OWNER(iod->trans_name->dollar_io, uic.mem, uic.grp, chown_res); if (-1 == chown_res) rts_error(VARLSTCNT(1) errno); break; } case iop_width: assert(iod->state == dev_open); GET_LONG(width, (pp->str.addr + p_offset)); if (width <= 0) rts_error(VARLSTCNT(1) ERR_RMWIDTHPOS); else if (MAX_STRLEN < width) rts_error(VARLSTCNT(1) ERR_RMWIDTHTOOBIG); iod->width = width; iod->wrap = TRUE; break; case iop_wrap: iod->wrap = TRUE; break; case iop_nowrap: iod->wrap = FALSE; break; case iop_ipchset: { if ( (iconv_t)0 != iod->input_conv_cd ) { ICONV_CLOSE_CD(iod->input_conv_cd); } SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->in_code_set) ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET); break; } case iop_opchset: { if ( (iconv_t) 0 != iod->output_conv_cd ) { ICONV_CLOSE_CD(iod->output_conv_cd); } SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->out_code_set) ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1)); break; } default: break; } p_offset += ((IOP_VAR_SIZE == io_params_size[c]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[c]); } if (fstat_done && mode != mode1) { /* if the mode has been changed by the qualifiers, reset it */ if (-1 == CHMOD(iod->trans_name->dollar_io, mode)) rts_error(VARLSTCNT(1) errno); } return; }
void ionl_use(io_desc *iod, mval *pp) { unsigned char ch, len; int fil_type; int4 width, length; io_desc *d_in, *d_out; mident tab; int p_offset; error_def(ERR_TTINVFILTER); error_def(ERR_DEVPARMNEG); p_offset = 0; d_in = iod->pair.in; d_out = iod->pair.out; assert(iod->state == dev_open); while (*(pp->str.addr + p_offset) != iop_eol) { switch (ch = *(pp->str.addr + p_offset++)) { 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: memset(&tab, 0, sizeof(mident)); len = *(pp->str.addr + p_offset); memcpy(&tab.c[0], pp->str.addr + p_offset + 1, (len < sizeof(mident) ? len : sizeof(mident))); if ((fil_type = namelook(filter_index, filter_names, tab.c)) < 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_length: GET_LONG(length, pp->str.addr + p_offset); if (length < 0) rts_error(VARLSTCNT(1) ERR_DEVPARMNEG); d_out->length = length; break; case iop_width: GET_LONG(width, pp->str.addr + p_offset); if (width < 0) rts_error(VARLSTCNT(1) ERR_DEVPARMNEG); if (width == 0) { d_out->wrap = FALSE; d_out->width = TTDEF_PG_WIDTH; } else { d_out->width = width; d_out->wrap = TRUE; } break; case iop_wrap: d_out->wrap = TRUE; break; case iop_nowrap: d_out->wrap = FALSE; break; case iop_x: { int4 col; GET_LONG(col, pp->str.addr + p_offset); d_out->dollar.x = col; if ((d_out->dollar.x) < 0) d_out->dollar.x = 0; if (d_out->dollar.x > d_out->width && d_out->wrap) d_out->dollar.x %= d_out->width; break; } case iop_y: { int4 row; GET_LONG(row, (pp->str.addr + p_offset)); d_out->dollar.y = row; if ((d_out->dollar.y) < 0) d_out->dollar.y = 0; if (d_out->length) d_out->dollar.y %= d_out->length; break; } case iop_ipchset: { if ( (iconv_t)0 != iod->input_conv_cd ) { ICONV_CLOSE_CD(iod->input_conv_cd); } SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->in_code_set) ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET); break; } case iop_opchset: { if ( (iconv_t) 0 != iod->output_conv_cd ) { ICONV_CLOSE_CD(iod->output_conv_cd); } SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->out_code_set) ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1)); break; } } p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]); } return; }
void iotcp_use(io_desc *iod, mval *pp) { unsigned char c; int4 length, width; d_tcp_struct *tcpptr, newtcp; int p_offset; error_def(ERR_DEVPARMNEG); error_def(ERR_RMWIDTHPOS); #ifdef DEBUG_TCP PRINTF("%s >>>\n", __FILE__); #endif p_offset = 0; tcpptr = (d_tcp_struct *)iod->dev_sp; /* copy existing parameters */ memcpy(&newtcp, tcpptr, sizeof(d_tcp_struct)); while (*(pp->str.addr + p_offset) != iop_eol) { assert((params) *(pp->str.addr + p_offset) < (params) n_iops); switch (c = *(pp->str.addr + p_offset++)) { case iop_width: GET_LONG(width, pp->str.addr + p_offset); if (width == 0) newtcp.width = TCPDEF_WIDTH; else if (width > 0) newtcp.width = width; else rts_error(VARLSTCNT(1) ERR_DEVPARMNEG); break; case iop_length: GET_LONG(length, pp->str.addr + p_offset); if (length == 0) newtcp.length = TCPDEF_LENGTH; else if (length > 0) newtcp.length = length; else rts_error(VARLSTCNT(1) ERR_DEVPARMNEG); break; case iop_urgent: newtcp.urgent = TRUE; break; case iop_nourgent: newtcp.urgent = FALSE; break; case iop_exception: iod->error_handler.len = *(pp->str.addr + p_offset); iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1); s2pool(&iod->error_handler); break; case iop_ipchset: { 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)); break; } case iop_opchset: { 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); break; } default: break; } p_offset += ((IOP_VAR_SIZE == io_params_size[c]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[c]); } /* commit changes */ memcpy(tcpptr, &newtcp, sizeof(d_tcp_struct)); #ifdef DEBUG_TCP PRINTF("%s <<<\n", __FILE__); #endif return; }
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); } } }
void iomb_use(io_desc *iod, mval *pp) { char *path; uint4 status; d_mb_struct *mb_ptr; params ch; int p_offset; p_offset = 0; iomb_flush(iod); mb_ptr = (d_mb_struct *)iod->dev_sp; while ( (ch = *(pp->str.addr + p_offset++)) != iop_eol) { switch (ch) { case iop_delete: if (mb_ptr->prmflg && mb_ptr->del_on_close) { close(mb_ptr->channel); path = iod->trans_name->dollar_io; if ((status = UNLINK(path)) == -1) rts_error(VARLSTCNT(1) errno); } break; case iop_exception: iod->error_handler.len = *(pp->str.addr + p_offset); iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1); s2pool(&iod->error_handler); break; case iop_wait: mb_ptr->write_mask = 1; break; case iop_nowait: mb_ptr->write_mask = 0; break; case iop_ipchset: { if ( (iconv_t)0 != iod->input_conv_cd ) { ICONV_CLOSE_CD(iod->input_conv_cd); } SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->in_code_set) ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET); break; } case iop_opchset: { if ( (iconv_t) 0 != iod->output_conv_cd ) { ICONV_CLOSE_CD(iod->output_conv_cd); } SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->out_code_set) ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1)); break; } default: break; } p_offset += ((IOP_VAR_SIZE == io_params_size[*(pp->str.addr + p_offset)]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[*(pp->str.addr + p_offset)]); } }