void dse_dmp(void) { boolean_t dmp_res, glo_present, zwr_present; patch_fdmp_recs = 0; glo_present = (CLI_PRESENT == cli_present("GLO")); zwr_present = (CLI_PRESENT == cli_present("ZWR")); if (glo_present || zwr_present) { if (CLOSED_FMT == dse_dmp_format) { util_out_print("Error: must open an output file before dump.", TRUE); return; } if (gtm_utf8_mode && (GLO_FMT == glo_present)) { util_out_print("Error: GLO format is not supported in UTF-8 mode. Use ZWR format.", TRUE); return; } if (OPEN_FMT == dse_dmp_format) { dse_dmp_format = (glo_present ? GLO_FMT : ZWR_FMT); if (!gtm_utf8_mode) dse_fdmp_output(LIT_AND_LEN("; DSE EXTRACT")); else dse_fdmp_output(LIT_AND_LEN("; DSE EXTRACT UTF-8")); dse_fdmp_output(STR_AND_LEN(format_label[dse_dmp_format])); } else if ((glo_present ? GLO_FMT : ZWR_FMT) != dse_dmp_format) { util_out_print("Error: current output file already contains !AD records.", TRUE, LEN_AND_STR(&format_label[dse_dmp_format][MESS_OFF])); return; } patch_is_fdmp = TRUE; ESTABLISH(dse_dmp_handler); } else patch_is_fdmp = FALSE; if (CLI_PRESENT == cli_present("RECORD") || CLI_PRESENT == cli_present("OFFSET")) dmp_res = dse_r_dmp(); else dmp_res = dse_b_dmp(); if (patch_is_fdmp) { REVERT; if (dmp_res) util_out_print("!UL !AD records written.!/", TRUE, patch_fdmp_recs, LEN_AND_STR(&format_label[dse_dmp_format][MESS_OFF])); } return; }
void dse_f_key(void) { block_id path[MAX_BT_DEPTH + 1], root_path[MAX_BT_DEPTH + 1]; int4 offset[MAX_BT_DEPTH + 1], root_offset[MAX_BT_DEPTH + 1], nocrit_present; char targ_key[256], targ_key_root[256], *key_top, util_buff[MAX_UTIL_LEN]; int size, size_root, root_path_count, count, util_len; bool found, was_crit; if (!dse_getki(&targ_key[0],&size,LIT_AND_LEN("KEY"))) return; patch_path_count = 1; root_path[0] = get_dir_root(); for (key_top = &targ_key[0]; key_top <= &targ_key[256]; ) if (!*key_top++) break; size_root = key_top - &targ_key[0] + 1; memcpy(&targ_key_root[0],&targ_key[0],size_root); targ_key_root[size_root - 1] = targ_key_root[size_root] = 0; patch_find_root_search = TRUE; was_crit = cs_addrs->now_crit; nocrit_present = (CLI_NEGATED == cli_present("CRIT")); if (!was_crit) { if (nocrit_present) cs_addrs->now_crit = TRUE; else grab_crit(gv_cur_region); } if (!dse_ksrch(root_path[0],&root_path[1],&root_offset[0],&targ_key_root[0],size_root)) { util_out_print("!/Key not found, no root present.!/",TRUE); if (!was_crit) { if (nocrit_present) cs_addrs->now_crit = FALSE; else rel_crit(gv_cur_region); } return; } root_path_count = patch_path_count; patch_path_count = 1; path[0] = ksrch_root; patch_find_root_search = FALSE; if (!dse_ksrch(path[0],&path[1],&offset[0],&targ_key[0],size)) { memcpy(util_buff,"!/Key not found, would be in block ",36); util_len = 36; util_len += i2hex_nofill(path[patch_path_count - 2], (uchar_ptr_t)&util_buff[util_len], 8); memcpy(&util_buff[util_len], ".",1); util_len += 1; util_buff[util_len] = 0; util_out_print(util_buff,FALSE); patch_path_count -= 1; }else { memcpy(util_buff,"!/Key found in block ",22); util_len = 22; util_len += i2hex_nofill(path[patch_path_count - 1], (uchar_ptr_t)&util_buff[util_len], 8); memcpy(&util_buff[util_len], ".",1); util_len += 1; util_buff[util_len] = 0; util_out_print(util_buff,FALSE); } util_out_print("!/ Directory path!/ Path--blk:off",TRUE); for (count = 0; count < root_path_count ;count++) { memcpy(util_buff," ",1); util_len = 1; util_len += i2hex_nofill(root_path[count],(uchar_ptr_t)&util_buff[util_len], 8); memcpy(&util_buff[util_len],":",1); util_len += 1; util_len += i2hex_nofill(root_offset[count],(uchar_ptr_t)&util_buff[util_len], 4); memcpy(&util_buff[util_len],",",1); util_len += 1; util_buff[util_len] = 0; util_out_print(util_buff,FALSE); } util_out_print("!/ Global tree path!/ Path--blk:off",TRUE); if (patch_path_count) { for (count = 0; count < patch_path_count ;count++) { memcpy(util_buff," ",1); util_len = 1; util_len += i2hex_nofill(path[count],(uchar_ptr_t)&util_buff[util_len], 8); memcpy(&util_buff[util_len],":",1); util_len += 1; util_len += i2hex_nofill(offset[count],(uchar_ptr_t)&util_buff[util_len], 4); memcpy(&util_buff[util_len],",",1); util_len += 1; util_buff[util_len] = 0; util_out_print(util_buff,FALSE); } util_out_print(0,TRUE); } else { memcpy(util_buff," ",1); util_len = 1; util_len += i2hex_nofill(root_path[count],(uchar_ptr_t)&util_buff[util_len], 8); memcpy(&util_buff[util_len],"!/",2); util_len += 2; util_buff[util_len] = 0; util_out_print(util_buff,TRUE); } if (!was_crit) { if (nocrit_present) cs_addrs->now_crit = FALSE; else rel_crit(gv_cur_region); } return; }
void goq_load(uint4 begin, uint4 end, struct FAB *infab) { int status; msgtype msg; unsigned char *in_buff, *b; unsigned int n; bool is_begin; uint4 rec_count; unsigned short goq_blk_size; short iosb[4]; error_def(ERR_INVMVXSZ); error_def(ERR_MUPIPINFO); error_def(ERR_PREMATEOF); error_def(ERR_LDGOQFMT); error_def(ERR_BEGINST); rec_count = 0; if (begin > 0) is_begin = TRUE; else is_begin = FALSE; goq_blk_size = MVX_BLK_SIZE; infab->fab$w_mrs = goq_blk_size; in_buff = malloc(goq_blk_size + 8); if (is_begin) { status = sys$qio(efn_bg_qio_read, infab->fab$l_stv, IO$_READVBLK, &iosb[0], 0, 0, in_buff, goq_blk_size, (rec_count * goq_blk_size / 512) + 1, 0, 0, 0); if (SS$_NORMAL != status) /* get header block */ rts_error(VARLSTCNT(1) status); sys$synch(efn_bg_qio_read, &iosb[0]); if (SS$_NORMAL != iosb[0]) rts_error(VARLSTCNT(1) iosb[0]); if (iosb[1] != goq_blk_size) { if (M11_BLK_SIZE != iosb[1]) rts_error(VARLSTCNT(1) ERR_INVMVXSZ); goq_blk_size = M11_BLK_SIZE; } while ((SS$_ENDOFFILE != iosb[0]) && (rec_count < begin)) { rec_count++; status = sys$qio(efn_bg_qio_read, infab->fab$l_stv, IO$_READVBLK, &iosb[0], 0, 0, in_buff, goq_blk_size, (rec_count * goq_blk_size / 512) + 1, 0, 0, 0); if (SS$_NORMAL != status) rts_error(VARLSTCNT(1) status); sys$synch(efn_bg_qio_read, &iosb[0]); if ((SS$_NORMAL != iosb[0]) && (SS$_ENDOFFILE != iosb[0])) { rts_error(VARLSTCNT(1) iosb[0]); mupip_exit(iosb[0]); } } for (;rec_count < begin;) { status = sys$qio(efn_bg_qio_read, infab->fab$l_stv, IO$_READVBLK, &iosb[0], 0, 0, in_buff, goq_blk_size, (rec_count * goq_blk_size / 512) + 1, 0, 0, 0); if (SS$_NORMAL != status) rts_error(VARLSTCNT(1) status); sys$synch(efn_bg_qio_read, &iosb[0]); if (SS$_ENDOFFILE == iosb[0]) rts_error(VARLSTCNT(1) ERR_PREMATEOF); if (SS$_NORMAL != iosb[0]) rts_error(VARLSTCNT(1) iosb[0]); rec_count++; } msg.msg_number = ERR_BEGINST; msg.arg_cnt = 3; msg.new_opts = msg.def_opts = 1; msg.fp_cnt = 1; msg.fp[0].n = rec_count; sys$putmsg(&msg, 0, 0, 0); } else { status = sys$qio(efn_bg_qio_read, infab->fab$l_stv, IO$_READVBLK, &iosb[0], 0, 0, in_buff, goq_blk_size, (rec_count * goq_blk_size / 512) + 1, 0, 0, 0); if (SS$_NORMAL != status) rts_error(VARLSTCNT(1) status); sys$synch(efn_bg_qio_read, &iosb[0]); if (SS$_NORMAL != iosb[0]) { rts_error(VARLSTCNT(1) iosb[0]); mupip_exit(iosb[0]); } if (iosb[1] != goq_blk_size) { if (M11_BLK_SIZE != iosb[1]) rts_error(VARLSTCNT(1) ERR_INVMVXSZ); goq_blk_size = M11_BLK_SIZE; } b = in_buff; while ((13 != *b++) && (b - in_buff < goq_blk_size - 28)) ; if (memcmp(b - SIZEOF("~%GOQ"), LIT_AND_LEN("~%GOQ")) || (10 != *b)) { rts_error(VARLSTCNT(1) ERR_LDGOQFMT); mupip_exit(ERR_LDGOQFMT); } for (n = 0; n < 3; n++) { while ((13 != *b++) && b - in_buff < goq_blk_size) ; if (10 != *b++) { rts_error(VARLSTCNT(1) ERR_LDGOQFMT); mupip_exit(ERR_LDGOQFMT); } } msg.msg_number = ERR_MUPIPINFO; msg.arg_cnt = 4; msg.new_opts = msg.def_opts = 1; msg.fp_cnt = 2; msg.fp[0].n = b - in_buff - 1; msg.fp[1].cp = in_buff; sys$putmsg(&msg, 0, 0, 0); while (SS$_ENDOFFILE != iosb[0]) { rec_count++; status = sys$qio(efn_bg_qio_read, infab->fab$l_stv, IO$_READVBLK, &iosb[0], 0, 0, in_buff, goq_blk_size, (rec_count * goq_blk_size / 512) + 1, 0, 0, 0); if (SS$_NORMAL != status) { rts_error(VARLSTCNT(1) status); mupip_exit(status); } sys$synch(efn_bg_qio_read, &iosb[0]); if ((SS$_NORMAL != iosb[0]) && (SS$_ENDOFFILE != iosb[0])) { rts_error(VARLSTCNT(1) iosb[0]); mupip_exit(iosb[0]); } } } if (MVX_BLK_SIZE == goq_blk_size) goq_mvx_load(infab, in_buff, rec_count, end); else goq_m11_load(infab, in_buff, rec_count, end); /***********************************************************************************************/ /* Shut Down */ /***********************************************************************************************/ CLOSE: free(in_buff); gv_cur_region = NULL; status = sys$dassgn(infab->fab$l_stv); if (SS$_NORMAL != status) { rts_error(VARLSTCNT(1) status); mupip_exit(status); } return; }
void dse_range(void) { char lower[256], targ_key[256], upper[256], util_buff[MAX_UTIL_LEN]; block_id from, to, blk, blk_child; sm_uc_ptr_t bp, b_top, key_bot, key_top, key_top1, rp, r_top; char level; int4 dummy_int, nocrit_present; cache_rec_ptr_t dummy_cr; short int rsize, size, size1; int cnt, dummy, lower_len, util_len, upper_len; boolean_t busy_matters, free, got_lonely_star, index, low, lost, star, up, was_crit, was_hold_onto_crit; if (cli_present("FROM") == CLI_PRESENT) { if (!cli_get_hex("FROM", (uint4 *)&from)) return; if (from < 0 || from > cs_addrs->ti->total_blks || !(from % cs_addrs->hdr->bplmap)) { util_out_print("Error: invalid block number.", TRUE); return; } } else from = 1; if (cli_present("TO") == CLI_PRESENT) { if(!cli_get_hex("TO", (uint4 *)&to)) return; if (to < 0 || to > cs_addrs->ti->total_blks || !(to % cs_addrs->hdr->bplmap)) { util_out_print("Error: invalid block number.", TRUE); return; } } else to = cs_addrs->ti->total_blks - 1; if (low = (cli_present("LOWER") == CLI_PRESENT)) { if (!dse_getki(&lower[0], &lower_len, LIT_AND_LEN("LOWER"))) return; } if (up = (cli_present("UPPER") == CLI_PRESENT)) { if (!dse_getki(&upper[0], &upper_len, LIT_AND_LEN("UPPER"))) return; } star = (cli_present("STAR") == CLI_PRESENT); if (!low && !up && !star) { util_out_print("Must specify star, or a lower or upper key limit.", TRUE); return; } index = (cli_present("INDEX") == CLI_PRESENT); lost = (cli_present("LOST") == CLI_PRESENT); dummy = cli_present("BUSY"); if (dummy == CLI_PRESENT) { busy_matters = TRUE; free = FALSE; } else if (dummy == CLI_NEGATED) busy_matters = free = TRUE; else busy_matters = free = FALSE; patch_path[0] = get_dir_root(); cnt = 0; was_crit = cs_addrs->now_crit; nocrit_present = (CLI_NEGATED == cli_present("CRIT")); DSE_GRAB_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region); for (blk = from; blk <= to ;blk++) { if (util_interrupt) { DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region); rts_error(VARLSTCNT(1) ERR_CTRLC); break; } if (!(blk % cs_addrs->hdr->bplmap)) continue; if (!(bp = t_qread(blk, &dummy_int, &dummy_cr))) rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL); level = ((blk_hdr_ptr_t)bp)->levl; if (index && (level == 0)) continue; if (busy_matters && (free != dse_is_blk_free(blk, &dummy_int, &dummy_cr))) continue; if (((blk_hdr_ptr_t) bp)->bsiz > cs_addrs->hdr->blk_size) b_top = bp + cs_addrs->hdr->blk_size; else if (((blk_hdr_ptr_t) bp)->bsiz < SIZEOF(blk_hdr)) b_top = bp + SIZEOF(blk_hdr); else b_top = bp + ((blk_hdr_ptr_t) bp)->bsiz; rp = bp + SIZEOF(blk_hdr); GET_SHORT(rsize, &((rec_hdr_ptr_t) rp)->rsiz); if (rsize < SIZEOF(rec_hdr)) r_top = rp + SIZEOF(rec_hdr); else r_top = rp + rsize; if (r_top >= b_top) r_top = b_top; got_lonely_star = FALSE; if (((blk_hdr_ptr_t) bp)->levl) { key_top = r_top - SIZEOF(block_id); if (star && (r_top == b_top)) got_lonely_star = TRUE; } else { if (!up && !low) continue; for (key_top = rp + SIZEOF(rec_hdr); key_top < r_top ; ) if (!*key_top++ && !*key_top++) break; } if (!got_lonely_star) { key_bot = rp + SIZEOF(rec_hdr); size = key_top - key_bot; if (size <= 0) continue; if (size > SIZEOF(targ_key)) size = SIZEOF(targ_key); if (lost) { for (key_top1 = rp + SIZEOF(rec_hdr); key_top1 < r_top ; ) if (!*key_top1++) break; size1 = key_top1 - rp - SIZEOF(rec_hdr); if (size1 > SIZEOF(targ_key)) size1 = SIZEOF(targ_key); patch_find_root_search = TRUE; patch_path_count = 1; patch_find_blk = blk; if (dse_is_blk_in(rp, r_top, size1)) continue; } if (low && memcmp(lower, key_bot, MIN(lower_len, size)) > 0) continue; if (up && memcmp(upper, key_bot, MIN(upper_len, size)) < 0) continue; } else { got_lonely_star = FALSE; if (lost) { blk_child = *(block_id_ptr_t)key_top; if (!(bp = t_qread(blk_child, &dummy_int, &dummy_cr))) rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL); if (((blk_hdr_ptr_t) bp)->bsiz > cs_addrs->hdr->blk_size) b_top = bp + cs_addrs->hdr->blk_size; else if (((blk_hdr_ptr_t) bp)->bsiz < SIZEOF(blk_hdr)) b_top = bp + SIZEOF(blk_hdr); else b_top = bp + ((blk_hdr_ptr_t) bp)->bsiz; rp = bp + SIZEOF(blk_hdr); GET_SHORT(rsize, &((rec_hdr_ptr_t) rp)->rsiz); if (rsize < SIZEOF(rec_hdr)) r_top = rp + SIZEOF(rec_hdr); else r_top = rp + rsize; if (r_top >= b_top) r_top = b_top; if (((blk_hdr_ptr_t) bp)->levl) key_top = r_top - SIZEOF(block_id); for (key_top1 = rp + SIZEOF(rec_hdr); key_top1 < r_top ; ) if (!*key_top1++) break; size1 = key_top1 - rp - SIZEOF(rec_hdr); if (size1 > 0) { if (size1 > SIZEOF(targ_key)) size1 = SIZEOF(targ_key); patch_find_root_search = TRUE; patch_path_count = 1; patch_find_blk = blk; if (dse_is_blk_in(rp, r_top, size1)) continue; } } } if (!cnt++) util_out_print("!/Blocks in the specified key range:", TRUE); util_out_print("Block: !8XL Level: !2UL", TRUE, blk, level); } DSE_REL_CRIT_AS_APPROPRIATE(was_crit, was_hold_onto_crit, nocrit_present, cs_addrs, gv_cur_region); if (cnt) util_out_print("Found !UL blocks", TRUE, cnt); else util_out_print("None found.", TRUE); return; }
callin_entry_list* citab_parse (void) { int parameter_count, i, fclose_res; uint4 inp_mask, out_mask, mask; mstr labref, callnam; enum gtm_types ret_tok, parameter_types[MAX_ACTUALS], pr; char str_buffer[MAX_TABLINE_LEN], *tbp, *end; FILE *ext_table_file_handle; callin_entry_list *entry_ptr = NULL, *save_entry_ptr = NULL; ext_table_file_name = GETENV(CALLIN_ENV_NAME); if (!ext_table_file_name) /* environment variable not set */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CITABENV, 2, LEN_AND_STR(CALLIN_ENV_NAME)); ext_table_file_handle = Fopen(ext_table_file_name, "r"); if (!ext_table_file_handle) /* call-in table not found */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(11) ERR_CITABOPN, 2, LEN_AND_STR(ext_table_file_name), ERR_SYSCALL, 5, LEN_AND_LIT("fopen"), CALLFROM, errno); ext_source_line_num = 0; while (read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle)) { if (!*(tbp = exttab_scan_space(str_buffer))) continue; if (!(end = scan_ident(tbp))) ext_stx_error(ERR_CIRCALLNAME, ext_table_file_name); callnam.addr = tbp; callnam.len = INTCAST(end - tbp); tbp = exttab_scan_space(end); if (':' != *tbp++) ext_stx_error(ERR_COLON, ext_table_file_name); ret_tok = scan_keyword(&tbp); /* return type */ switch (ret_tok) /* return type valid ? */ { case gtm_void: case gtm_char_star: case gtm_int_star: case gtm_uint_star: case gtm_long_star: case gtm_ulong_star: case gtm_float_star: case gtm_double_star: case gtm_string_star: case gtm_jboolean: case gtm_jint: case gtm_jlong: case gtm_jfloat: case gtm_jdouble: case gtm_jstring: case gtm_jbyte_array: case gtm_jbig_decimal: break; default: ext_stx_error(ERR_CIRTNTYP, ext_table_file_name); } labref.addr = tbp; if ((end = scan_labelref(tbp))) labref.len = INTCAST(end - tbp); else ext_stx_error(ERR_CIENTNAME, ext_table_file_name); tbp = exttab_scan_space(end); inp_mask = out_mask = 0; for (parameter_count = 0; (*tbp && ')' != *tbp); parameter_count++) { if (MAX_ACTUALS <= parameter_count) ext_stx_error(ERR_CIMAXPARAM, ext_table_file_name); /* must have comma if this is not the first parameter, otherwise '(' */ if (((0 == parameter_count)?'(':',') != *tbp++) ext_stx_error(ERR_CIRPARMNAME, ext_table_file_name); tbp = exttab_scan_space(tbp); if ((0 == parameter_count) && (*tbp == ')')) /* special case () */ break; /* looking for an I, a O or an IO */ mask = (1 << parameter_count); inp_mask |= ('I' == *tbp) ? (tbp++, mask) : 0; out_mask |= ('O' == *tbp) ? (tbp++, mask) : 0; if ((!(inp_mask & mask) && !(out_mask & mask)) || (':' != *tbp++)) ext_stx_error(ERR_CIDIRECTIVE, ext_table_file_name); switch ((pr = scan_keyword(&tbp))) /* valid param type? */ { case gtm_int: case gtm_uint: case gtm_long: case gtm_ulong: case gtm_float: case gtm_double: if (out_mask & mask) ext_stx_error(ERR_CIPARTYPE, ext_table_file_name); /* fall-thru */ case gtm_char_star: case gtm_int_star: case gtm_uint_star: case gtm_long_star: case gtm_ulong_star: case gtm_float_star: case gtm_double_star: case gtm_string_star: case gtm_jboolean: case gtm_jint: case gtm_jlong: case gtm_jfloat: case gtm_jdouble: case gtm_jstring: case gtm_jbyte_array: case gtm_jbig_decimal: break; default: ext_stx_error(ERR_CIUNTYPE, ext_table_file_name); } parameter_types[parameter_count] = pr; tbp = exttab_scan_space(tbp); } if (!*tbp) ext_stx_error(ERR_CIRPARMNAME, ext_table_file_name); entry_ptr = get_memory(SIZEOF(callin_entry_list)); entry_ptr->next_entry = save_entry_ptr; save_entry_ptr = entry_ptr; entry_ptr->return_type = ret_tok; entry_ptr->argcnt = parameter_count; entry_ptr->input_mask = inp_mask; entry_ptr->output_mask = out_mask; entry_ptr->parms = get_memory(parameter_count * SIZEOF(entry_ptr->parms[0])); for (i = 0 ; i < parameter_count; i++) entry_ptr->parms[i] = parameter_types[i]; put_mstr(&labref, &entry_ptr->label_ref); put_mstr(&callnam, &entry_ptr->call_name); } FCLOSE(ext_table_file_handle, fclose_res); return entry_ptr; }
/* Note: Need condition handler to clean-up allocated structures and close intput file in the event of an error */ struct extcall_package_list *exttab_parse(mval *package) { int parameter_alloc_values[MAX_ACTUALS], parameter_count, ret_pre_alloc_val, i, fclose_res; int len, keywordlen; boolean_t is_input[MAX_ACTUALS], is_output[MAX_ACTUALS], got_status; mstr callnam, rtnnam, clnuprtn; mstr val, trans; void_ptr_t pakhandle; enum gtm_types ret_tok, parameter_types[MAX_ACTUALS], pr; char str_buffer[MAX_TABLINE_LEN], *tbp, *end; char str_temp_buffer[MAX_TABLINE_LEN]; FILE *ext_table_file_handle; struct extcall_package_list *pak; struct extcall_entry_list *entry_ptr; /* First, construct package name environment variable */ memcpy(str_buffer, PACKAGE_ENV_PREFIX, SIZEOF(PACKAGE_ENV_PREFIX)); tbp = &str_buffer[SIZEOF(PACKAGE_ENV_PREFIX) - 1]; if (package->str.len) { /* guaranteed by compiler */ assert(package->str.len < MAX_NAME_LENGTH - SIZEOF(PACKAGE_ENV_PREFIX) - 1); *tbp++ = '_'; memcpy(tbp, package->str.addr, package->str.len); tbp += package->str.len; } *tbp = 0; /* Now we have the environment name, lookup file name */ ext_table_file_name = GETENV(str_buffer); if (NULL == ext_table_file_name) { /* Environment variable for the package not found */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZCCTENV, 2, LEN_AND_STR(str_buffer)); } ext_table_file_handle = Fopen(ext_table_file_name, "r"); if (NULL == ext_table_file_handle) { /* Package's external call table could not be found */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZCCTOPN, 2, LEN_AND_STR(ext_table_file_name)); } ext_source_line_num = 0; /* Pick-up name of shareable library */ tbp = read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle); if (NULL == tbp) { /* External call table is a null file */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZCCTNULLF, 2, package->str.len, package->str.addr); } STRNCPY_STR(str_temp_buffer, str_buffer, MAX_TABLINE_LEN); val.addr = str_temp_buffer; val.len = STRLEN(str_temp_buffer); /* Need to copy the str_buffer into another temp variable since * TRANS_LOG_NAME requires input and output buffers to be different. * If there is an env variable present in the pathname, TRANS_LOG_NAME * expands it and return SS_NORMAL. Else it returns SS_NOLOGNAM. * Instead of checking 2 return values, better to check against SS_LOG2LONG * which occurs if the pathname is too long after any kind of expansion. */ if (SS_LOG2LONG == TRANS_LOG_NAME(&val, &trans, str_buffer, SIZEOF(str_buffer), dont_sendmsg_on_log2long)) { /* Env variable expansion in the pathname caused buffer overflow */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.len, val.addr, SIZEOF(str_buffer) - 1); } pakhandle = fgn_getpak(str_buffer, INFO); if (NULL == pakhandle) { /* Unable to obtain handle to the shared library */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ZCUNAVAIL, 2, package->str.len, package->str.addr); } pak = get_memory(SIZEOF(*pak)); pak->first_entry = 0; put_mstr(&package->str, &pak->package_name); pak->package_handle = pakhandle; pak->package_clnup_rtn = NULL; len = STRLEN("GTMSHLIBEXIT"); /* At this point, we have a valid package, pointed to by pak */ # ifdef DEBUG_EXTCALL FPRINTF(stderr, "GT.M external call opened package name: %s\n", pak->package_name.addr); # endif for (;;) { star_found = FALSE; tbp = read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle); if (NULL == tbp) break; tbp = exttab_scan_space(str_buffer); /* Empty line? */ if (!*tbp) continue; /* No, must be entryref or keyword */ end = scan_ident(tbp); if (!end) ext_stx_error(ERR_ZCENTNAME, ext_table_file_name); keywordlen = end - tbp; end = exttab_scan_space(end); if ('=' == *end) { /* Keyword before '=' has a string of size == STRLEN("GTMSHLIBEXIT") */ if (keywordlen == len) { if (0 == MEMCMP_LIT(tbp, "GTMSHLIBEXIT")) { /* Skip past the '=' char */ tbp = exttab_scan_space(end + 1); if (*tbp) { /* We have a cleanup routine name */ clnuprtn.addr = tbp; clnuprtn.len = scan_ident(tbp) - tbp; clnuprtn.addr[clnuprtn.len] = 0; pak->package_clnup_rtn = (clnupfptr)fgn_getrtn(pak->package_handle, &clnuprtn, ERROR); } else ext_stx_error(ERR_ZCCLNUPRTNMISNG, ext_table_file_name); continue; } } ext_stx_error(ERR_ZCINVALIDKEYWORD, ext_table_file_name); continue; } if ('^' == *end) { end++; end = scan_ident(end); if (!end) ext_stx_error(ERR_ZCENTNAME, ext_table_file_name); } rtnnam.addr = tbp; rtnnam.len = INTCAST(end - tbp); tbp = exttab_scan_space(end); if (':' != *tbp++) ext_stx_error(ERR_ZCCOLON, ext_table_file_name); /* Get return type */ ret_tok = scan_keyword(&tbp); /* Check for legal return type */ switch (ret_tok) { case gtm_status: case gtm_void: case gtm_int: case gtm_uint: case gtm_long: case gtm_ulong: case gtm_char_star: case gtm_float_star: case gtm_string_star: case gtm_int_star: case gtm_uint_star: case gtm_long_star: case gtm_ulong_star: case gtm_double_star: case gtm_char_starstar: case gtm_pointertofunc: case gtm_pointertofunc_star: case gtm_jboolean: case gtm_jint: case gtm_jlong: case gtm_jfloat: case gtm_jdouble: case gtm_jstring: case gtm_jbyte_array: case gtm_jbig_decimal: break; default: ext_stx_error(ERR_ZCRTNTYP, ext_table_file_name); } got_status = (ret_tok == gtm_status); /* Get call name */ if ('[' == *tbp) { if (star_found) ret_pre_alloc_val = scan_array_bound(&tbp,ret_tok); else ext_stx_error(ERR_ZCPREALLVALPAR, ext_table_file_name); /* We should allow the pre-allocated value upto to the maximum string size (MAX_STRLEN) plus 1 for the * extra terminating NULL. Negative values would have been caught by scan_array_bound() above. */ if (ret_pre_alloc_val > MAX_STRLEN + 1) ext_stx_error(ERR_ZCPREALLVALINV, ext_table_file_name); } else ret_pre_alloc_val = -1; /* Fix C9E12-002681 */ if ('%' == *tbp) *tbp = '_'; end = scan_ident(tbp); if (!end) ext_stx_error(ERR_ZCRCALLNAME, ext_table_file_name); callnam.addr = tbp; callnam.len = INTCAST(end - tbp); tbp = exttab_scan_space(end); tbp = exttab_scan_space(tbp); for (parameter_count = 0;(MAX_ACTUALS > parameter_count) && (')' != *tbp); parameter_count++) { star_found = FALSE; /* Must have comma if this is not the first parameter, otherwise '(' */ if (((0 == parameter_count)?'(':',') != *tbp++) ext_stx_error(ERR_ZCRPARMNAME, ext_table_file_name); tbp = exttab_scan_space(tbp); /* Special case: () is ok */ if ((0 == parameter_count) && (*tbp == ')')) break; /* Looking for an I, an O or an IO */ is_input[parameter_count] = is_output[parameter_count] = FALSE; if ('I' == *tbp) { is_input[parameter_count] = TRUE; tbp++; } if ('O' == *tbp) { is_output[parameter_count] = TRUE; tbp++; } if (((FALSE == is_input[parameter_count]) && (FALSE == is_output[parameter_count])) ||(':' != *tbp++)) ext_stx_error(ERR_ZCRCALLNAME, ext_table_file_name); /* Scanned colon--now get type */ pr = scan_keyword(&tbp); if (gtm_notfound == pr) ext_stx_error(ERR_ZCUNTYPE, ext_table_file_name); if (gtm_status == pr) { /* Only one type "status" allowed per call */ if (got_status) ext_stx_error(ERR_ZCMLTSTATUS, ext_table_file_name); else got_status = TRUE; } parameter_types[parameter_count] = pr; if ('[' == *tbp) { if (star_found && !is_input[parameter_count]) parameter_alloc_values[parameter_count] = scan_array_bound(&tbp, pr); else ext_stx_error(ERR_ZCPREALLVALPAR, ext_table_file_name); /* We should allow the pre-allocated value upto to the maximum string size (MAX_STRLEN) plus 1 for * the extra terminating NULL. Negative values would have been caught by scan_array_bound() above. */ if (parameter_alloc_values[parameter_count] > MAX_STRLEN + 1) ext_stx_error(ERR_ZCPREALLVALINV, ext_table_file_name); } else parameter_alloc_values[parameter_count] = -1; tbp = exttab_scan_space(tbp); } entry_ptr = get_memory(SIZEOF(*entry_ptr)); entry_ptr->next_entry = pak->first_entry; pak->first_entry = entry_ptr; entry_ptr->return_type = ret_tok; entry_ptr->ret_pre_alloc_val = ret_pre_alloc_val; entry_ptr->argcnt = parameter_count; entry_ptr->input_mask = array_to_mask(is_input, parameter_count); entry_ptr->output_mask = array_to_mask(is_output, parameter_count); entry_ptr->parms = get_memory(parameter_count * SIZEOF(entry_ptr->parms[0])); entry_ptr->param_pre_alloc_size = get_memory(parameter_count * SIZEOF(intszofptr_t)); entry_ptr->parmblk_size = (SIZEOF(void *) * parameter_count) + SIZEOF(intszofptr_t); for (i = 0 ; i < parameter_count; i++) { entry_ptr->parms[i] = parameter_types[i]; assert(gtm_void != parameter_types[i]); entry_ptr->parmblk_size += parm_space_needed[parameter_types[i]]; entry_ptr->param_pre_alloc_size[i] = parameter_alloc_values[i]; } put_mstr(&rtnnam, &entry_ptr->entry_name); put_mstr(&callnam, &entry_ptr->call_name); /* The reason for passing INFO severity is that PROFILE has several routines listed in * the external call table that are not in the shared library. PROFILE folks would * rather see info/warning messages for such routines at shared library open time, * than error out. These unimplemented routines, they say were not being called from * the application and wouldn't cause any application failures. If we fail to open * the shared libary, or we fail to locate a routine that is called from the * application, we issue rts_error message (in extab_parse.c). */ entry_ptr->fcn = fgn_getrtn(pak->package_handle, &entry_ptr->call_name, INFO); # ifdef DEBUG_EXTCALL FPRINTF(stderr, " package entry point: %s, address: %x\n", entry_ptr->entry_name.addr, entry_ptr->fcn); # endif } FCLOSE(ext_table_file_handle, fclose_res); return pak; }
/* Note: need condition handler to clean-up allocated structures and close intput file in the event of an error */ struct extcall_package_list *exttab_parse(mval *package) { int parameter_alloc_values[MAXIMUM_PARAMETERS], parameter_count, ret_pre_alloc_val, i, fclose_res; boolean_t is_input[MAXIMUM_PARAMETERS], is_output[MAXIMUM_PARAMETERS], got_status; mstr callnam, rtnnam; void_ptr_t pakhandle; enum xc_types ret_tok, parameter_types[MAXIMUM_PARAMETERS], pr; char str_buffer[MAX_TABLINE_LEN], *tbp, *end; FILE *ext_table_file_handle; struct extcall_package_list *pak; struct extcall_entry_list *entry_ptr; error_def(ERR_ZCRTENOTF); error_def(ERR_ZCALLTABLE); error_def(ERR_ZCUSRRTN); error_def(ERR_ZCCTENV); error_def(ERR_ZCCTOPN); error_def(ERR_ZCCTNULLF); error_def(ERR_ZCUNAVAIL); error_def(ERR_ZCENTNAME); error_def(ERR_ZCCOLON); error_def(ERR_ZCRTNTYP); error_def(ERR_ZCRCALLNAME); error_def(ERR_ZCUNTYPE); error_def(ERR_ZCMLTSTATUS); error_def(ERR_ZCRPARMNAME); error_def(ERR_ZCPREALLVALPAR); error_def(ERR_ZCPREALLVALINV); /* First, construct package name environment variable */ memcpy(str_buffer, PACKAGE_ENV_PREFIX, sizeof(PACKAGE_ENV_PREFIX)); tbp = &str_buffer[sizeof(PACKAGE_ENV_PREFIX) - 1]; if (package->str.len) { /* guaranteed by compiler */ assert(package->str.len < MAX_NAME_LENGTH - sizeof(PACKAGE_ENV_PREFIX) - 1); *tbp++ = '_'; memcpy(tbp, package->str.addr, package->str.len); tbp += package->str.len; } *tbp = 0; /* Now we have the environment name, lookup file name */ ext_table_file_name = GETENV(str_buffer); if (NULL == ext_table_file_name) { /* Environment variable for the package not found */ rts_error(VARLSTCNT(4) ERR_ZCCTENV, 2, LEN_AND_STR(str_buffer)); } ext_table_file_handle = Fopen(ext_table_file_name, "r"); if (NULL == ext_table_file_handle) { /* Package's external call table could not be found */ rts_error(VARLSTCNT(4) ERR_ZCCTOPN, 2, LEN_AND_STR(ext_table_file_name)); } ext_source_line_num = 0; /* pick-up name of shareable library */ tbp = read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle); if (NULL == tbp) { /* External call table is a null file */ rts_error(VARLSTCNT(4) ERR_ZCCTNULLF, 2, package->str.len, package->str.addr); } pakhandle = fgn_getpak(str_buffer, INFO); if (NULL == pakhandle) { /* Unable to obtain handle to the shared library */ rts_error(VARLSTCNT(4) ERR_ZCUNAVAIL, 2, package->str.len, package->str.addr); } pak = get_memory(sizeof(*pak)); pak->first_entry = 0; put_mstr(&package->str, &pak->package_name); pak->package_handle = pakhandle; /* At this point, we have a valid package, pointed to by pak */ #ifdef DEBUG_EXTCALL FPRINTF(stderr, "GT.M external call opened package name: %s\n", pak->package_name.addr); #endif for (;;) { star_found = FALSE; tbp = read_table(LIT_AND_LEN(str_buffer), ext_table_file_handle); if (NULL == tbp) break; tbp = scan_space(str_buffer); /* empty line? */ if (!*tbp) continue; /* No, must be entryref */ end = scan_ident(tbp); if (!end) ext_stx_error(ERR_ZCENTNAME, ext_table_file_name); if ('^' == *end) { end++; end = scan_ident(end); if (!end) ext_stx_error(ERR_ZCENTNAME, ext_table_file_name); } rtnnam.addr = tbp; rtnnam.len = INTCAST(end - tbp); tbp = scan_space(end); if (':' != *tbp++) ext_stx_error(ERR_ZCCOLON, ext_table_file_name); /* get return type */ ret_tok = scan_keyword(&tbp); /* check for legal return type */ switch (ret_tok) { case xc_status: case xc_void: case xc_int: case xc_uint: case xc_long: case xc_ulong: case xc_char_star: case xc_float_star: case xc_string_star: case xc_int_star: case xc_uint_star: case xc_long_star: case xc_ulong_star: case xc_double_star: case xc_char_starstar: case xc_pointertofunc: case xc_pointertofunc_star: break; default: ext_stx_error(ERR_ZCRTNTYP, ext_table_file_name); } got_status = (ret_tok == xc_status); /* get call name */ if ('[' == *tbp) { if (star_found) ret_pre_alloc_val = scan_array_bound(&tbp,ret_tok); else ext_stx_error(ERR_ZCPREALLVALPAR, ext_table_file_name); /* We should allow the pre-allocated value upto to the maximum string size (MAX_STRLEN) plus 1 for the * extra terminating NULL. Negative values would have been caught by scan_array_bound() above */ if (ret_pre_alloc_val > MAX_STRLEN + 1) ext_stx_error(ERR_ZCPREALLVALINV, ext_table_file_name); } else ret_pre_alloc_val = -1; end = scan_ident(tbp); if (!end) ext_stx_error(ERR_ZCRCALLNAME, ext_table_file_name); callnam.addr = tbp; callnam.len = INTCAST(end - tbp); tbp = scan_space(end); tbp = scan_space(tbp); for (parameter_count = 0;(MAXIMUM_PARAMETERS > parameter_count) && (')' != *tbp); parameter_count++) { star_found = FALSE; /* must have comma if this is not the first parameter, otherwise '(' */ if (((0 == parameter_count)?'(':',') != *tbp++) ext_stx_error(ERR_ZCRPARMNAME, ext_table_file_name); tbp = scan_space(tbp); /* special case: () is ok */ if ((0 == parameter_count) && (*tbp == ')')) break; /* looking for an I, an O or an IO */ is_input[parameter_count] = is_output[parameter_count] = FALSE; if ('I' == *tbp) { is_input[parameter_count] = TRUE; tbp++; } if ('O' == *tbp) { is_output[parameter_count] = TRUE; tbp++; } if (((FALSE == is_input[parameter_count]) && (FALSE == is_output[parameter_count])) ||(':' != *tbp++)) ext_stx_error(ERR_ZCRCALLNAME, ext_table_file_name); /* scanned colon--now get type */ pr = scan_keyword(&tbp); if (xc_notfound == pr) ext_stx_error(ERR_ZCUNTYPE, ext_table_file_name); if (xc_status == pr) { /* Only one type "status" allowed per call */ if (got_status) ext_stx_error(ERR_ZCMLTSTATUS, ext_table_file_name); else got_status = TRUE; } parameter_types[parameter_count] = pr; if ('[' == *tbp) { if (star_found && !is_input[parameter_count]) parameter_alloc_values[parameter_count] = scan_array_bound(&tbp, pr); else ext_stx_error(ERR_ZCPREALLVALPAR, ext_table_file_name); /* We should allow the pre-allocated value upto to the maximum string size (MAX_STRLEN) plus 1 for * the extra terminating NULL. Negative values would have been caught by scan_array_bound() above */ if (parameter_alloc_values[parameter_count] > MAX_STRLEN + 1) ext_stx_error(ERR_ZCPREALLVALINV, ext_table_file_name); } else parameter_alloc_values[parameter_count] = -1; tbp = scan_space(tbp); } entry_ptr = get_memory(sizeof(*entry_ptr)); entry_ptr->next_entry = pak->first_entry; pak->first_entry = entry_ptr; entry_ptr->return_type = ret_tok; entry_ptr->ret_pre_alloc_val = ret_pre_alloc_val; entry_ptr->argcnt = parameter_count; entry_ptr->input_mask = array_to_mask(is_input, parameter_count); entry_ptr->output_mask = array_to_mask(is_output, parameter_count); entry_ptr->parms = get_memory(parameter_count * sizeof(entry_ptr->parms[0])); entry_ptr->param_pre_alloc_size = get_memory(parameter_count * sizeof(intszofptr_t)); entry_ptr->parmblk_size = (SIZEOF(void *) * parameter_count) + SIZEOF(intszofptr_t); for (i = 0 ; i < parameter_count ; i++) { entry_ptr->parms[i] = parameter_types[i]; entry_ptr->parmblk_size += parm_space_needed[parameter_types[i]]; entry_ptr->param_pre_alloc_size[i] = parameter_alloc_values[i]; } put_mstr(&rtnnam, &entry_ptr->entry_name); put_mstr(&callnam, &entry_ptr->call_name); /* the reason for passing INFO severity is that PROFILE has several routines listed in * the external call table that are not in the shared library. PROFILE folks would * rather see info/warning messages for such routines at shared library open time, * than error out. These unimplemented routines, they say were not being called from * the application and wouldn't cause any application failures. If we fail to open * the shared libary, or we fail to locate a routine that is called from the * application, we issue rts_error message (in extab_parse.c) */ entry_ptr->fcn = fgn_getrtn(pak->package_handle, &entry_ptr->call_name, INFO); #ifdef DEBUG_EXTCALL FPRINTF(stderr, " package entry point: %s, address: %x\n", entry_ptr->entry_name.addr, entry_ptr->fcn); #endif } FCLOSE(ext_table_file_handle, fclose_res); return pak; }
* * ****************************************************************/ #include "mdef.h" #include "gtm_ctype.h" #include "gtm_string.h" #include "cmidef.h" #include "hashtab_mname.h" /* needed for cmmdef.h */ #include "cmmdef.h" #include "gtcm_protocol.h" static char *encode_cpu(void); static char *encode_os(void); LITDEF gtcm_proto_cpu_info_t gtcm_proto_cpu_info[] = { {LIT_AND_LEN("IA64"), "IA64"}, {LIT_AND_LEN("RS6000"), "PPC"}, {LIT_AND_LEN("AXP"), "AXP"}, {LIT_AND_LEN("HP-PA"), "PAR"}, {LIT_AND_LEN("x86"), "X86"}, {LIT_AND_LEN("x86_64"), "X86_64"}, {LIT_AND_LEN("S390"), "390"}, {LIT_AND_LEN("S390X"), "390"}, {LIT_AND_LEN("SPARC"), "SPA"}, {LIT_AND_LEN("VAX"), "VAX"}, {LIT_AND_LEN(GTCM_PROTO_BAD_CPU), GTCM_PROTO_BAD_CPU} }; LITDEF gtcm_proto_os_info_t gtcm_proto_os_info[] = { {LIT_AND_LEN("AIX"), "AIX"},
bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mval *mspace) { char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */ char dev_type[MAX_DEV_TYPE_LEN]; int n; mstr tn; /* translated name */ uint4 stat; /* status */ int p_offset; unsigned char ch; ABS_TIME cur_time, end_time; bool out_of_time = FALSE; 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; p_offset = 0; while (iop_eol != *(pp->str.addr + p_offset)) { if ((iop_tmpmbx == (ch = *(pp->str.addr + p_offset++))) || (iop_prmmbx == ch)) tl->iod->type = mb; else if (iop_nl == ch) tl->iod->type = nl; p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]); } if (!tl->iod->type && mspace && mspace->str.len) { lower_to_upper(dev_type, mspace->str.addr, mspace->str.len); if (((SIZEOF("SOCKET") - 1) == mspace->str.len) && (0 == memcmp(dev_type, LIT_AND_LEN("SOCKET")))) tl->iod->type = gtmsocket; else tl->iod->type = us; } if (!tl->iod->type) { tn.len = tl->len; tn.addr = &tl->dollar_io; tl->iod->type = io_type(&tn); } } naml->iod = tl->iod; } tl->iod->disp_ptr = &io_dev_dispatch[tl->iod->type]; assert(0 != naml->iod); 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 = write_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; naml->iod->dollar.zeof = FALSE; } if (0 == timeout) stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout); /* ZY: add a parameter timeout */ else if (NO_M_TIMEOUT == timeout) { while (FALSE == (stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout))) /* ZY: add timeout */ { hiber_start(1000); /* 1 second */ if (outofband) outofband_action(FALSE); } } else { sys_get_curr_time(&cur_time); add_int_to_abs_time(&cur_time, timeout * 1000, &end_time); while (FALSE == (stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout)) /* ZY: add timeout */ && (!out_of_time)) { hiber_start(1000); /* 1 second */ if (outofband) outofband_action(FALSE); sys_get_curr_time(&cur_time); if (abs_time_comp(&end_time, &cur_time) <= 0) out_of_time = TRUE; } } if (TRUE == stat) { naml->iod->state = dev_open; if (27 == naml->iod->trans_name->dollar_io[0]) { tn.addr = &naml->iod->trans_name->dollar_io[4]; n = naml->iod->trans_name->len - 4; if (n < 0) n = 0; tn.len = n; naml->iod->trans_name = get_log_name(&tn, INSERT); naml->iod->trans_name->iod = naml->iod; } } else { if (dev_open == naml->iod->state && (gtmsocket != naml->iod->type)) naml->iod->state = dev_closed; else if ((gtmsocket == naml->iod->type) && naml->iod->newly_created) { assert(naml->iod->state != dev_open); iosocket_destroy(naml->iod); } } active_device = 0; if ((NO_M_TIMEOUT != timeout) && IS_MCODE_RUNNING) return (stat); return FALSE; }
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 int helper_init(upd_helper_entry_ptr_t helper, recvpool_user helper_type) { int save_errno, save_shutdown; char helper_cmd[UPDHELPER_CMD_MAXLEN]; int status; int4 i4status; mstr helper_log_cmd, helper_trans_cmd; upd_helper_ctl_ptr_t upd_helper_ctl; #ifdef UNIX pid_t helper_pid, waitpid_res; #elif defined(VMS) uint4 helper_pid, cmd_channel; char mbx_suffix[2 + 1]; /* hex representation of numbers 0 through MAX_UPD_HELPERS-1, +1 for '\0' */ $DESCRIPTOR(cmd_desc_reader, UPDHELPER_READER_CMD_STR); $DESCRIPTOR(cmd_desc_writer, UPDHELPER_WRITER_CMD_STR); #endif upd_helper_ctl = recvpool.upd_helper_ctl; save_shutdown = helper->helper_shutdown; helper->helper_shutdown = NO_SHUTDOWN; #ifdef UNIX if (0 > (helper_pid = fork())) /* BYPASSOK: we exec immediately, no FORK_CLEAN needed */ { save_errno = errno; helper->helper_shutdown = save_shutdown; gtm_putmsg(VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, LEN_AND_LIT("Could not fork update process"), save_errno); repl_errno = EREPL_UPDSTART_FORK; return UPDPROC_START_ERR; } if (0 == helper_pid) { /* helper */ getjobnum(); helper->helper_pid_prev = process_id; /* identify owner of slot */ helper_log_cmd.len = STR_LIT_LEN(UPDHELPER_CMD); helper_log_cmd.addr = UPDHELPER_CMD; if (SS_NORMAL != (i4status = TRANS_LOG_NAME(&helper_log_cmd, &helper_trans_cmd, helper_cmd, SIZEOF(helper_cmd), dont_sendmsg_on_log2long))) { helper->helper_shutdown = save_shutdown; gtm_putmsg(VARLSTCNT(6) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, LEN_AND_LIT("Could not find path of Helper Process. Check value of $gtm_dist")); if (SS_LOG2LONG == i4status) gtm_putmsg(VARLSTCNT(5) ERR_LOGTOOLONG, 3, LEN_AND_LIT(UPDHELPER_CMD), SIZEOF(helper_cmd) - 1); repl_errno = EREPL_UPDSTART_BADPATH; return UPDPROC_START_ERR; } helper_cmd[helper_trans_cmd.len] = '\0'; if (-1 == EXECL(helper_cmd, helper_cmd, UPDHELPER_CMD_ARG1, UPDHELPER_CMD_ARG2, (UPD_HELPER_READER == helper_type) ? UPDHELPER_READER_CMD_ARG3 : UPDHELPER_WRITER_CMD_ARG3, NULL)) { save_errno = errno; helper->helper_shutdown = save_shutdown; gtm_putmsg(VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, LEN_AND_LIT("Could not exec Helper Process"), save_errno); repl_errno = EREPL_UPDSTART_EXEC; return UPDPROC_START_ERR; } } #elif defined(VMS) /* Create detached server and write startup commands to it */ i2hex(helper - upd_helper_ctl->helper_list, LIT_AND_LEN(mbx_suffix)); mbx_suffix[SIZEOF(mbx_suffix) - 1] = '\0'; /* A mailbox is created per helper, and the mailbox name is assigned to a logical. This logical will persist until the * helper terminates. So, we need to assign a unique logical per helper. Hence the suffix. */ if (SS_NORMAL != (status = repl_create_server((UPD_HELPER_READER == helper_type) ? &cmd_desc_reader : &cmd_desc_writer, UPDHELPER_MBX_PREFIX, mbx_suffix, &cmd_channel, &helper->helper_pid_prev, ERR_RECVPOOLSETUP))) { gtm_putmsg(VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, LEN_AND_LIT("Unable to spawn Helper process"), status); helper->helper_shutdown = save_shutdown; repl_errno = EREPL_UPDSTART_FORK; return UPDPROC_START_ERR; } helper_pid = helper->helper_pid_prev; #endif /* Wait for helper to startup */ while (helper_pid != helper->helper_pid && is_proc_alive(helper_pid, 0)) { SHORT_SLEEP(GTMRECV_WAIT_FOR_SRV_START); UNIX_ONLY(WAITPID(helper_pid, &status, WNOHANG, waitpid_res);) /* Release defunct helper process if dead */ } /* The helper has now gone far enough in the initialization, or died before initialization. Consider startup completed. */ #if defined(VMS) /* Deassign the send-cmd mailbox channel */ if (SS_NORMAL != (status = sys$dassgn(cmd_channel))) { gtm_putmsg(VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Unable to close upd-send-cmd mbox channel"), status); helper->helper_shutdown = save_shutdown; repl_errno = EREPL_UPDSTART_BADPATH; /* Just to make an auto-shutdown */ return UPDPROC_START_ERR; } #endif repl_log(gtmrecv_log_fp, TRUE, TRUE, "Helper %s started. PID %d [0x%X]\n", (UPD_HELPER_READER == helper_type) ? "reader" : "writer", helper_pid, helper_pid); return UPDPROC_STARTED; }