/* returns the truth value based on the sense indicated by 'negate'. * If negate is FALSE (i.e. in regular mode), * returns TRUE if the env variable/logical log is defined and evaluates to "TRUE" (or part thereof), * or "YES" (or part thereof), or a non zero integer * returns FALSE otherwise * If negate is TRUE(i.e. in negative mode), * returns TRUE if the env variable/logical log is defined and evaluates to "FALSE" (or part thereof), * or "NO" (or part thereof), or a zero integer * returns FALSE otherwise */ boolean_t logical_truth_value(mstr *log, boolean_t negate, boolean_t *is_defined) { int4 status; mstr tn; char buf[1024]; boolean_t zero, is_num; int index; error_def(ERR_LOGTOOLONG); error_def(ERR_TRNLOGFAIL); tn.addr = buf; if (NULL != is_defined) *is_defined = FALSE; if (SS_NORMAL == (status = TRANS_LOG_NAME(log, &tn, buf, SIZEOF(buf), dont_sendmsg_on_log2long))) { if (NULL != is_defined) *is_defined = TRUE; if (tn.len <= 0) return FALSE; for (is_num = TRUE, zero = TRUE, index = 0; index < tn.len; index++) { if (!ISDIGIT_ASCII(buf[index])) { is_num = FALSE; break; } zero = (zero && ('0' == buf[index])); } if (!negate) { /* regular mode */ return (!is_num ? (0 == STRNCASECMP(buf, LOGICAL_TRUE, MIN(STR_LIT_LEN(LOGICAL_TRUE), tn.len)) || 0 == STRNCASECMP(buf, LOGICAL_YES, MIN(STR_LIT_LEN(LOGICAL_YES), tn.len))) : !zero); } else { /* negative mode */ return (!is_num ? (0 == STRNCASECMP(buf, LOGICAL_FALSE, MIN(STR_LIT_LEN(LOGICAL_FALSE), tn.len)) || 0 == STRNCASECMP(buf, LOGICAL_NO, MIN(STR_LIT_LEN(LOGICAL_NO), tn.len))) : zero); } } else if (SS_NOLOGNAM == status) return (FALSE); # ifdef UNIX else if (SS_LOG2LONG == status) { rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, log->len, log->addr, SIZEOF(buf) - 1); return (FALSE); } # endif else { rts_error(VARLSTCNT(5) ERR_TRNLOGFAIL, 2, log->len, log->addr, status); return (FALSE); } }
/* The third parameter is dummy to keep the inteface same as op_open */ int mu_op_open(mval *v, mval *p, int t, mval *mspace) { char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */ io_log_name *naml; /* logical record for passed name */ io_log_name *tl; /* logical record for translated name */ int4 stat; /* status */ mstr tn; /* translated name */ error_def(LP_NOTACQ); /* bad license */ error_def(ERR_LOGTOOLONG); MV_FORCE_STR(v); MV_FORCE_STR(p); if (mspace) MV_FORCE_STR(mspace); if (t < 0) t = 0; assert((unsigned char)*p->str.addr < n_iops); naml = get_log_name(&v->str, INSERT); if (naml->iod != 0) tl = naml; else { # ifdef NOLICENSE licensed= TRUE ; # else CRYPT_CHKSYSTEM; if (!licensed || LP_CONFIRM(lid,lkid)==LP_NOTACQ) { licensed= FALSE ; } # endif switch(stat = TRANS_LOG_NAME(&v->str, &tn, &buf1[0], sizeof(buf1), dont_sendmsg_on_log2long)) { case SS_NORMAL: tl = get_log_name(&tn, INSERT); break; case SS_NOLOGNAM: tl = naml; break; case SS_LOG2LONG: rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, v->str.len, v->str.addr, sizeof(buf1) - 1); break; default: rts_error(VARLSTCNT(1) stat); } } stat = mu_open_try(naml, tl, p, mspace); return (stat); }
uint4 trans_numeric(mstr *log, boolean_t *is_defined, boolean_t ignore_errors) { /* return * - 0 on error if ignore_errors is set (otherwise error is raised and no return is made) or * if logical/envvar is undefined. * - an unsigned int containing the numeric value (or as much as could be determined) from * the logical/envvar string value (up to the first non-numeric digit. Characters accepted * are those read by the strtoul() function. */ int4 status; uint4 value; mstr tn; char buf[MAX_TRANS_NAME_LEN], *endptr; error_def(ERR_LOGTOOLONG); error_def(ERR_TRNLOGFAIL); *is_defined = FALSE; if (SS_NORMAL == (status = TRANS_LOG_NAME(log, &tn, buf, SIZEOF(buf), ignore_errors ? do_sendmsg_on_log2long : dont_sendmsg_on_log2long))) { /* Translation was successful */ *is_defined = TRUE; assert(tn.len < SIZEOF(buf)); endptr = tn.addr + tn.len; *endptr = '\0'; value = (uint4)STRTOUL(buf, &endptr, 0); /* Base 0 allows base 10, 0x or octal input */ /* At this point, if '\0' == *endptr, the entire string was successfully consumed as a numeric string. If not, endptr has been updated to point to the errant chars. We currently have no clients who care about this so there is no expansion on this but this could be added at this point. For now we just return whatever numeric value (if any) was gleened.. */ return value; } else if (SS_NOLOGNAM == status) /* Not defined */ return 0; if (!ignore_errors) { /* Only give errors if we can handle them */ # ifdef UNIX if (SS_LOG2LONG == status) rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, log->len, log->addr, SIZEOF(buf) - 1); else # endif rts_error(VARLSTCNT(5) ERR_TRNLOGFAIL, 2, log->len, log->addr, status); } return 0; }
void gtcm_open_cmerrlog(void) { int len; mstr lfn1, lfn2; char lfn_path[MAX_TRANS_NAME_LEN + 1]; char new_lfn_path[MAX_TRANS_NAME_LEN + 1]; int new_len; uint4 ustatus; int4 rval; FILE *new_file; error_def(ERR_TEXT); if (0 != (len = STRLEN(gtcm_gnp_server_log))) { lfn1.addr = gtcm_gnp_server_log; lfn1.len = len; } else { lfn1.addr = GTCM_GNP_CMERR_FN; lfn1.len = sizeof(GTCM_GNP_CMERR_FN) - 1; } rval = TRANS_LOG_NAME(&lfn1, &lfn2, lfn_path, sizeof(lfn_path), do_sendmsg_on_log2long); if (rval == SS_NORMAL || rval == SS_NOLOGNAM) { lfn_path[lfn2.len] = 0; rename_file_if_exists(lfn_path, lfn2.len, new_lfn_path, &new_len, &ustatus); new_file = Fopen(lfn_path, "a"); if (NULL != new_file) { gtcm_errfile = TRUE; if (gtcm_errfs) fclose(gtcm_errfs); gtcm_errfs = new_file; if (dup2(fileno(gtcm_errfs), 1) < 0) { rts_error(VARLSTCNT(5) ERR_TEXT, 2, LEN_AND_LIT("Error on dup2 of stdout"), errno); } if (dup2(fileno(gtcm_errfs), 2) < 0) { rts_error(VARLSTCNT(5) ERR_TEXT, 2, LEN_AND_LIT("Error on dup2 of stderr"), errno); } } else fprintf(stderr, "Unable to open %s : %s\n", lfn_path, STRERROR(errno)); } else fprintf(stderr, "Unable to resolve %s : return value = %d\n", GTCM_GNP_CMERR_FN, rval); gtcm_firsterr = FALSE; }
uint4 gtmcrypt_entry() { void_ptr_t handle, fptr; char_ptr_t err_str, env_ptr, libname_ptr, libpath_ptr; char *gtmcryptlib_fname[] = { GTMCRYPT_INIT_FNAME, GTMCRYPT_CLOSE_FNAME, GTMCRYPT_HASH_GEN_FNAME, GTMCRYPT_ENCRYPT_FNAME, GTMCRYPT_DECRYPT_FNAME, GTMCRYPT_GETKEY_BY_NAME, GTMCRYPT_GETKEY_BY_HASH, GTMCRYPT_STRERROR }; void **gtmcryptlib_fptr[] = { (void **)>mcrypt_init_fnptr, (void **)>mcrypt_close_fnptr, (void **)>mcrypt_hash_gen_fnptr, (void **)>mcrypt_encrypt_fnptr, (void **)>mcrypt_decrypt_fnptr, (void **)>mcrypt_getkey_by_name_fnptr, (void **)>mcrypt_getkey_by_hash_fnptr, (void **)>mcrypt_strerror_fnptr }; int findx, num_dlsyms, plugin_dir_len, save_errno; char libpath[GTM_PATH_MAX], buf[MAX_GTMCRYPT_PLUGIN_STR_LEN], plugin_dir_path[GTM_PATH_MAX]; char resolved_libpath[GTM_PATH_MAX], resolved_gtmdist[GTM_PATH_MAX]; mstr trans, env_var = {0, SIZEOF(GTM_CRYPT_PLUGIN) - 1, GTM_CRYPT_PLUGIN}; if (NULL == (env_ptr = getenv(GTM_DIST))) rts_error(VARLSTCNT(1) ERR_GTMDISTUNDEF); if (NULL == realpath(env_ptr, &resolved_gtmdist[0])) { save_errno = errno; SNPRINTF(dl_err, MAX_ERRSTR_LEN, "Failed to find symbolic link for %s. %s", env_ptr, STRERROR(save_errno)); return ERR_CRYPTDLNOOPEN; } SNPRINTF(plugin_dir_path, GTM_PATH_MAX, "%s/%s", resolved_gtmdist, PLUGIN_DIR_NAME); plugin_dir_len = STRLEN(plugin_dir_path); if ((SS_NORMAL != TRANS_LOG_NAME(&env_var, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long)) || (0 >= trans.len)) { /* Either $gtm_crypt_plugin is not defined in the environment variable OR it is set to null-string. Fall-back to * using libgtmcrypt.so */ libname_ptr = GTMCRYPT_LIBNAME; } else libname_ptr = &buf[0]; /* value of $gtm_crypt_plugin */ SNPRINTF(libpath, GTM_PATH_MAX, "%s/%s", plugin_dir_path, libname_ptr); if (NULL == realpath(&libpath[0], &resolved_libpath[0])) { save_errno = errno; SNPRINTF(dl_err, MAX_ERRSTR_LEN, "Failed to find symbolic link for %s. %s", libpath, STRERROR(save_errno)); return ERR_CRYPTDLNOOPEN; } /* Symbolic link found. dlopen resolved_libpath */ if (0 != memcmp(&resolved_libpath[0], plugin_dir_path, plugin_dir_len)) { /* resolved_path doesn't contain $gtm_dist/plugin as the prefix */ SNPRINTF(dl_err, MAX_ERRSTR_LEN, "Symbolic link for %s must be relative to %s", libpath, plugin_dir_path); return ERR_CRYPTDLNOOPEN; } handle = dlopen(&resolved_libpath[0], GTMCRYPT_LIBFLAGS); if (NULL == handle) { COPY_DLLERR_MSG(err_str, dl_err); return ERR_CRYPTDLNOOPEN; } num_dlsyms = ARRAYSIZE(gtmcryptlib_fptr); /* number of functions to be dlsym'ed */ for(findx = 0; findx < num_dlsyms; ++findx) { fptr = (void *)dlsym(handle, gtmcryptlib_fname[findx]); if (NULL == fptr) { COPY_DLLERR_MSG(err_str, dl_err); return ERR_CRYPTDLNOOPEN; } *gtmcryptlib_fptr[findx] = fptr; } return 0; }
/* 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; }
void gtm_env_init(void) { mstr val, trans; boolean_t ret, is_defined; uint4 tdbglvl, tmsock, reservesize, memsize, cachent, trctblsize, trctblbytes; int4 status; char buf[MAX_TRANS_NAME_LEN]; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; if (!TREF(gtm_env_init_done)) { /* See if a debug level has been specified. Do this first since gtmDebugLevel needs * to be initialized before any mallocs are done in the system. */ gtmDebugLevel = INITIAL_DEBUG_LEVEL; val.addr = GTM_DEBUG_LEVEL_ENVLOG; val.len = SIZEOF(GTM_DEBUG_LEVEL_ENVLOG) - 1; if (tdbglvl = trans_numeric(&val, &is_defined, TRUE)) /* Note assignment!! */ { /* Some kind of debugging was asked for.. */ tdbglvl |= GDL_Simple; /* Make sure simple debugging turned on if any is */ if ((GDL_SmChkFreeBackfill | GDL_SmChkAllocBackfill) & tdbglvl) tdbglvl |= GDL_SmBackfill; /* Can't check it unless it's filled in */ if (GDL_SmStorHog & tdbglvl) tdbglvl |= GDL_SmBackfill | GDL_SmChkAllocBackfill; gtmDebugLevel |= tdbglvl; } /* gtm_boolean environment/logical */ val.addr = GTM_BOOLEAN; val.len = SIZEOF(GTM_BOOLEAN) - 1; TREF(gtm_fullbool) = trans_numeric(&val, &is_defined, TRUE); /* NOUNDEF environment/logical */ val.addr = GTM_NOUNDEF; val.len = SIZEOF(GTM_NOUNDEF) - 1; assert(FALSE == undef_inhibit); /* should have been set to FALSE at global variable definition time */ ret = logical_truth_value(&val, FALSE, &is_defined); if (is_defined) undef_inhibit = ret; /* if the logical is not defined, we want undef_inhibit to take its default value */ /* gtm_trace_gbl_name environment; it controls implicit MPROF testing */ val.addr = GTM_MPROF_TESTING; val.len = SIZEOF(GTM_MPROF_TESTING) - 1; if (SS_NORMAL == (status = TRANS_LOG_NAME(&val, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long))) { /* Note assignment above */ if (SIZEOF(buf) >= trans.len) { if (('0' == (char)(*trans.addr)) || (0 == trans.len)) { (TREF(mprof_env_gbl_name)).str.len = 0; /* this malloc is just so that mprof_env_gbl_name.str.addr is not NULL for subsequent * checks in gtm_startup.c and gtm$startup.c */ (TREF(mprof_env_gbl_name)).str.addr = malloc(1); } else { (TREF(mprof_env_gbl_name)).str.len = trans.len; (TREF(mprof_env_gbl_name)).str.addr = malloc(trans.len); memcpy((TREF(mprof_env_gbl_name)).str.addr, trans.addr, trans.len); } (TREF(mprof_env_gbl_name)).mvtype = MV_STR; } } else (TREF(mprof_env_gbl_name)).str.addr = NULL; # ifdef DEBUG /* GTM_GVUNDEF_FATAL environment/logical */ val.addr = GTM_GVUNDEF_FATAL; val.len = SIZEOF(GTM_GVUNDEF_FATAL) - 1; assert(FALSE == TREF(gtm_gvundef_fatal)); /* should have been set to FALSE by gtm_threadgbl_defs */ ret = logical_truth_value(&val, FALSE, &is_defined); if (is_defined) TREF(gtm_gvundef_fatal) = ret; /* if logical is not defined, gtm_gvundef_fatal takes the default value */ # endif /* Initialize variable that controls TP allocation clue (for created blocks) */ val.addr = GTM_TP_ALLOCATION_CLUE; val.len = SIZEOF(GTM_TP_ALLOCATION_CLUE) - 1; gtm_tp_allocation_clue = (block_id)trans_numeric(&val, &is_defined, TRUE); if (!is_defined) gtm_tp_allocation_clue = (block_id)MAXTOTALBLKS_MAX; /* Full Database-block Write mode */ val.addr = GTM_FULLBLOCKWRITES; val.len = SIZEOF(GTM_FULLBLOCKWRITES) - 1; gtm_fullblockwrites = logical_truth_value(&val, FALSE, &is_defined); if (!is_defined) gtm_fullblockwrites = DEFAULT_FBW_FLAG; /* GDS Block certification */ val.addr = GTM_GDSCERT; val.len = SIZEOF(GTM_GDSCERT) - 1; ret = logical_truth_value(&val, FALSE, &is_defined); if (is_defined) certify_all_blocks = ret; /* if the logical is not defined, we want to take default value */ /* Initialize null subscript's collation order */ val.addr = LCT_STDNULL; val.len = SIZEOF(LCT_STDNULL) - 1; ret = logical_truth_value(&val, FALSE, &is_defined); if (is_defined) TREF(local_collseq_stdnull) = ret; /* Initialize eXclusive Kill variety (GTM vs M Standard) */ val.addr = GTM_STDXKILL; val.len = SIZEOF(GTM_STDXKILL) - 1; ret = logical_truth_value(&val, FALSE, &is_defined); if (is_defined) gtm_stdxkill = ret; /* Initialize variables for white box testing. Even though these white-box test variables only control the * flow of the DBG builds, the PRO builds check on these variables (for example, in tp_restart.c to decide * whether to fork_n_core or not) so need to do this initialization for PRO builds as well. */ wbox_test_init(); /* Initialize variable that controls dynamic GT.M block upgrade */ val.addr = GTM_BLKUPGRADE_FLAG; val.len = SIZEOF(GTM_BLKUPGRADE_FLAG) - 1; gtm_blkupgrade_flag = trans_numeric(&val, &is_defined, TRUE); /* Initialize whether database file extensions need to be logged in the operator log */ val.addr = GTM_DBFILEXT_SYSLOG_DISABLE; val.len = SIZEOF(GTM_DBFILEXT_SYSLOG_DISABLE) - 1; ret = logical_truth_value(&val, FALSE, &is_defined); if (is_defined) gtm_dbfilext_syslog_disable = ret; /* if the logical is not defined, we want to take default value */ /* Initialize maximum sockets in a single socket device createable by this process */ gtm_max_sockets = MAX_N_SOCKET; val.addr = GTM_MAX_SOCKETS; val.len = SIZEOF(GTM_MAX_SOCKETS) - 1; if ((tmsock = trans_numeric(&val, &is_defined, TRUE)) && MAX_MAX_N_SOCKET > tmsock) /* Note assignment!! */ gtm_max_sockets = tmsock; /* Initialize storage to allocate and keep in our back pocket in case run out of memory */ outOfMemoryMitigateSize = GTM_MEMORY_RESERVE_DEFAULT; val.addr = GTM_MEMORY_RESERVE; val.len = SIZEOF(GTM_MEMORY_RESERVE) - 1; if (reservesize = trans_numeric(&val, &is_defined, TRUE)) /* Note assignment!! */ outOfMemoryMitigateSize = reservesize; /* Initialize indirect cache limits (max memory, max entries) */ max_cache_memsize = MAX_CACHE_MEMSIZE * 1024; val.addr = GTM_MAX_INDRCACHE_MEMORY; val.len = SIZEOF(GTM_MAX_INDRCACHE_MEMORY) - 1; if (memsize = trans_numeric(&val, &is_defined, TRUE)) /* Note assignment!! */ max_cache_memsize = memsize * 1024; max_cache_entries = MAX_CACHE_ENTRIES; val.addr = GTM_MAX_INDRCACHE_COUNT; val.len = SIZEOF(GTM_MAX_INDRCACHE_COUNT) - 1; if (cachent = trans_numeric(&val, &is_defined, TRUE)) /* Note assignment!! */ max_cache_entries = cachent; /* Initialize ZQUIT to control funky QUIT compilation */ val.addr = GTM_ZQUIT_ANYWAY; val.len = SIZEOF(GTM_ZQUIT_ANYWAY) - 1; ret = logical_truth_value(&val, FALSE, &is_defined); if (is_defined) dollar_zquit_anyway = ret; /* Initialize ZPROMPT to desired GTM prompt or default */ val.addr = GTM_PROMPT; val.len = SIZEOF(GTM_PROMPT) - 1; if (SS_NORMAL == (status = TRANS_LOG_NAME(&val, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long))) { /* Non-standard prompt requested */ assert(SIZEOF(buf) > trans.len); if (SIZEOF_prombuf >= trans.len) { (TREF(gtmprompt)).len = trans.len; memcpy((TREF(gtmprompt)).addr, trans.addr, trans.len); } } /* Initialize tpnotacidtime */ TREF(tpnotacidtime) = TPNOTACID_DEFAULT_TIME; val.addr = GTM_TPNOTACIDTIME; val.len = SIZEOF(GTM_TPNOTACIDTIME) - 1; if ((status = trans_numeric(&val, &is_defined, TRUE)) && (0 <= status) && (TPNOTACID_MAX_TIME >= status) && is_defined) TREF(tpnotacidtime) = status; /* NOTE assignment above */ /* Initialize $gtm_tprestart_log_first */ val.addr = GTM_TPRESTART_LOG_LIMIT; val.len = STR_LIT_LEN(GTM_TPRESTART_LOG_LIMIT); TREF(tprestart_syslog_limit) = trans_numeric(&val, &is_defined, TRUE); if (0 > TREF(tprestart_syslog_limit)) TREF(tprestart_syslog_limit) = 0; /* Initialize $gtm_tprestart_log_delta */ val.addr = GTM_TPRESTART_LOG_DELTA; val.len = STR_LIT_LEN(GTM_TPRESTART_LOG_DELTA); TREF(tprestart_syslog_delta) = trans_numeric(&val, &is_defined, TRUE); if (0 > TREF(tprestart_syslog_delta)) TREF(tprestart_syslog_delta) = 0; /* See if this is a GT.M Development environment, not a production environment */ if (GETENV("gtm_environment_init")) TREF(gtm_environment_init) = TRUE; /* in-house */ /* See if a trace table is desired. If we have been asked to trace one or more groups, we also * see if a specific size has been specified. A default size is provided. */ val.addr = GTM_TRACE_GROUPS; val.len = SIZEOF(GTM_TRACE_GROUPS) - 1; if (SS_NORMAL == (status = TRANS_LOG_NAME(&val, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long))) { /* Trace-group(s) have been declared - figure out which ones */ assert(SIZEOF(buf) > trans.len); parse_trctbl_groups(&trans); if (0 != TREF(gtm_trctbl_groups)) { /* At least one valid group was specified */ val.addr = GTM_TRACE_TABLE_SIZE; val.len = SIZEOF(GTM_TRACE_TABLE_SIZE) - 1; trctblsize = trans_numeric(&val, &is_defined, TRUE); if (0 < (trctblsize = (0 < trctblsize) ? trctblsize : TRACE_TABLE_SIZE_DEFAULT)) /* assignment! */ { trctblbytes = trctblsize * SIZEOF(trctbl_entry); TREF(gtm_trctbl_start) = malloc(trctblbytes); TREF(gtm_trctbl_end) = TREF(gtm_trctbl_start) + trctblsize; TREF(gtm_trctbl_cur) = TREF(gtm_trctbl_start) - 1; /* So doesn't skip 1st entry */ memset(TREF(gtm_trctbl_start), 0, trctblbytes); } } } /* Initialize dollar_zmaxtptime */ val.addr = GTM_ZMAXTPTIME; val.len = SIZEOF(GTM_ZMAXTPTIME) - 1; if ((status = trans_numeric(&val, &is_defined, TRUE)) && (0 <= status) && (TPTIMEOUT_MAX_TIME >= status)) TREF(dollar_zmaxtptime) = status; /* NOTE assignment above */ /* Platform specific initializations */ gtm_env_init_sp(); TREF(gtm_env_init_done) = TRUE; } }
int gtmsource_get_opt(void) { char *connect_parm_token_str, *connect_parm; char *connect_parms_str, tmp_connect_parms_str[GTMSOURCE_CONN_PARMS_LEN + 1]; char secondary_sys[MAX_SECONDARY_LEN], *c, inst_name[MAX_FN_LEN + 1]; char statslog_val[SIZEOF("OFF")]; /* "ON" or "OFF" */ char update_val[SIZEOF("DISABLE")]; /* "ENABLE" or "DISABLE" */ char freeze_val[SIZEOF("OFF")]; /* "ON" or "OFF" */ char freeze_comment[SIZEOF(gtmsource_options.freeze_comment)]; int tries, index = 0, timeout_status, connect_parms_index, status, renegotiate_interval; struct hostent *sec_hostentry; unsigned short log_file_len, filter_cmd_len; unsigned short secondary_len, inst_name_len, statslog_val_len, update_val_len, connect_parms_str_len; unsigned short freeze_val_len, freeze_comment_len, tlsid_len; int errcode; int port_len; char *ip_end; mstr log_nam, trans_name; boolean_t secondary, dotted_notation, log, log_interval_specified, connect_parms_badval, plaintext_fallback; memset((char *)>msource_options, 0, SIZEOF(gtmsource_options)); gtmsource_options.start = (CLI_PRESENT == cli_present("START")); gtmsource_options.shut_down = (CLI_PRESENT == cli_present("SHUTDOWN")); gtmsource_options.activate = (CLI_PRESENT == cli_present("ACTIVATE")); gtmsource_options.deactivate = (CLI_PRESENT == cli_present("DEACTIVATE")); gtmsource_options.checkhealth = (CLI_PRESENT == cli_present("CHECKHEALTH")); gtmsource_options.statslog = (CLI_PRESENT == cli_present("STATSLOG")); gtmsource_options.showbacklog = (CLI_PRESENT == cli_present("SHOWBACKLOG")); gtmsource_options.changelog = (CLI_PRESENT == cli_present("CHANGELOG")); gtmsource_options.stopsourcefilter = (CLI_PRESENT == cli_present("STOPSOURCEFILTER")); gtmsource_options.needrestart = (CLI_PRESENT == cli_present("NEEDRESTART")); gtmsource_options.losttncomplete = (CLI_PRESENT == cli_present("LOSTTNCOMPLETE")); gtmsource_options.jnlpool = (CLI_PRESENT == cli_present("JNLPOOL")); secondary = (CLI_PRESENT == cli_present("SECONDARY")); gtmsource_options.rootprimary = ROOTPRIMARY_UNSPECIFIED; /* to indicate unspecified state */ if ((CLI_PRESENT == cli_present("ROOTPRIMARY")) || (CLI_PRESENT == cli_present("UPDOK"))) gtmsource_options.rootprimary = ROOTPRIMARY_SPECIFIED; else if ((CLI_PRESENT == cli_present("PROPAGATEPRIMARY")) || (CLI_PRESENT == cli_present("UPDNOTOK"))) gtmsource_options.rootprimary = PROPAGATEPRIMARY_SPECIFIED; else { /* Neither ROOTPRIMARY (or UPDOK) nor PROPAGATEPRIMARY (or UPDNOTOK) specified. Assume default values. * Assume ROOTPRIMARY for -START -SECONDARY (active source server start) and -ACTIVATE commands. * Assume PROPAGATEPRIMARY for -START -PASSIVE (passive source server start) and -DEACTIVATE commands. */ if ((gtmsource_options.start && secondary) || gtmsource_options.activate) gtmsource_options.rootprimary = ROOTPRIMARY_SPECIFIED; if ((gtmsource_options.start && !secondary) || gtmsource_options.deactivate) gtmsource_options.rootprimary = PROPAGATEPRIMARY_SPECIFIED; } gtmsource_options.instsecondary = (CLI_PRESENT == cli_present("INSTSECONDARY")); if (gtmsource_options.instsecondary) { /* -INSTSECONDARY is specified in the command line. */ inst_name_len = SIZEOF(inst_name);; if (!cli_get_str("INSTSECONDARY", &inst_name[0], &inst_name_len)) { util_out_print("Error parsing INSTSECONDARY qualifier", TRUE); return(-1); } } else { /* Check if environment variable "gtm_repl_instsecondary" is defined. * Do that only if any of the following qualifiers is present as these are the only ones that honour it. * Mandatory : START, ACTIVATE, DEACTIVATE, STOPSOURCEFILTER, CHANGELOG, STATSLOG, NEEDRESTART, * Optional : CHECKHEALTH, SHOWBACKLOG or SHUTDOWN */ if (gtmsource_options.start || gtmsource_options.activate || gtmsource_options.deactivate || gtmsource_options.stopsourcefilter || gtmsource_options.changelog || gtmsource_options.statslog || gtmsource_options.needrestart || gtmsource_options.checkhealth || gtmsource_options.showbacklog || gtmsource_options.shut_down) { log_nam.addr = GTM_REPL_INSTSECONDARY; log_nam.len = SIZEOF(GTM_REPL_INSTSECONDARY) - 1; trans_name.addr = &inst_name[0]; if (SS_NORMAL == (status = TRANS_LOG_NAME(&log_nam, &trans_name, inst_name, SIZEOF(inst_name), do_sendmsg_on_log2long))) { gtmsource_options.instsecondary = TRUE; inst_name_len = trans_name.len; } else if (!gtmsource_options.checkhealth && !gtmsource_options.showbacklog && !gtmsource_options.shut_down) { if (SS_LOG2LONG == status) gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3, log_nam.len, log_nam.addr, SIZEOF(inst_name) - 1); gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_REPLINSTSECUNDF); return (-1); } } } if (gtmsource_options.instsecondary) { /* Secondary instance name specified either through -INSTSECONDARY or "gtm_repl_instsecondary" */ inst_name[inst_name_len] = '\0'; if ((MAX_INSTNAME_LEN <= inst_name_len) || (0 == inst_name_len)) { gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_REPLINSTSECLEN, 2, inst_name_len, inst_name); return (-1); } assert((inst_name_len + 1) <= MAX_INSTNAME_LEN); memcpy(gtmsource_options.secondary_instname, inst_name, inst_name_len + 1); /* copy terminating '\0' as well */ } if (gtmsource_options.start || gtmsource_options.activate) { if (secondary) { secondary_len = MAX_SECONDARY_LEN; if (!cli_get_str("SECONDARY", secondary_sys, &secondary_len)) { util_out_print("Error parsing SECONDARY qualifier", TRUE); return(-1); } /* Parse secondary_sys into secondary_host * and secondary_port */ c = secondary_sys; dotted_notation = TRUE; if ('[' == *c) { ip_end = strchr(++c, ']'); if (NULL == ip_end || 0 == (index = ip_end - c)) { util_out_print("Invalid IP address !AD", TRUE, LEN_AND_STR(secondary_sys)); return(-1); } memcpy(gtmsource_options.secondary_host, c, index); gtmsource_options.secondary_host[index] = '\0'; c = ip_end + 1; } else { while(*c && (':' != *c)) gtmsource_options.secondary_host[index++] = *c++; gtmsource_options.secondary_host[index] = '\0'; } if (':' != *c) { util_out_print("Secondary port number should be specified", TRUE); return(-1); } port_len = strlen(++c); errno = 0; if (((0 == (gtmsource_options.secondary_port = ATOI(c))) && (0 != errno)) || (0 >= gtmsource_options.secondary_port)) { util_out_print("Error parsing secondary port number !AD", TRUE, LEN_AND_STR(c)); return(-1); } } if (CLI_PRESENT == cli_present("CONNECTPARAMS")) { connect_parms_str_len = GTMSOURCE_CONN_PARMS_LEN + 1; if (!cli_get_str("CONNECTPARAMS", tmp_connect_parms_str, &connect_parms_str_len)) { util_out_print("Error parsing CONNECTPARAMS qualifier", TRUE); return(-1); } #ifdef VMS /* strip the quotes around the string. (DCL doesn't do it) */ assert('"' == tmp_connect_parms_str[0]); assert('"' == tmp_connect_parms_str[connect_parms_str_len - 1]); connect_parms_str = &tmp_connect_parms_str[1]; tmp_connect_parms_str[connect_parms_str_len - 1] = '\0'; #else connect_parms_str = &tmp_connect_parms_str[0]; #endif for (connect_parms_index = GTMSOURCE_CONN_HARD_TRIES_COUNT, connect_parms_badval = FALSE, connect_parm_token_str = connect_parms_str; !connect_parms_badval && connect_parms_index < GTMSOURCE_CONN_PARMS_COUNT && (connect_parm = strtok(connect_parm_token_str, GTMSOURCE_CONN_PARMS_DELIM)) != NULL; connect_parms_index++, connect_parm_token_str = NULL) { errno = 0; if ((0 == (gtmsource_options.connect_parms[connect_parms_index] = ATOI(connect_parm)) && 0 != errno) || 0 >= gtmsource_options.connect_parms[connect_parms_index]) connect_parms_badval = TRUE; } if (connect_parms_badval) { util_out_print("Error parsing or invalid value parameter in CONNECTPARAMS", TRUE); return(-1); } if (GTMSOURCE_CONN_PARMS_COUNT != connect_parms_index) { util_out_print( "All CONNECTPARAMS - HARD TRIES, HARD TRIES PERIOD, " "SOFT TRIES PERIOD, " "ALERT TIME, HEARTBEAT INTERVAL, " "MAX HEARBEAT WAIT should be specified", TRUE); return(-1); } } else { gtmsource_options.connect_parms[GTMSOURCE_CONN_HARD_TRIES_COUNT] = REPL_CONN_HARD_TRIES_COUNT; gtmsource_options.connect_parms[GTMSOURCE_CONN_HARD_TRIES_PERIOD] = REPL_CONN_HARD_TRIES_PERIOD; gtmsource_options.connect_parms[GTMSOURCE_CONN_SOFT_TRIES_PERIOD] = REPL_CONN_SOFT_TRIES_PERIOD; gtmsource_options.connect_parms[GTMSOURCE_CONN_ALERT_PERIOD] = REPL_CONN_ALERT_ALERT_PERIOD; gtmsource_options.connect_parms[GTMSOURCE_CONN_HEARTBEAT_PERIOD] = REPL_CONN_HEARTBEAT_PERIOD; gtmsource_options.connect_parms[GTMSOURCE_CONN_HEARTBEAT_MAX_WAIT] = REPL_CONN_HEARTBEAT_MAX_WAIT; } if (gtmsource_options.connect_parms[GTMSOURCE_CONN_ALERT_PERIOD]< gtmsource_options.connect_parms[GTMSOURCE_CONN_SOFT_TRIES_PERIOD]) gtmsource_options.connect_parms[GTMSOURCE_CONN_ALERT_PERIOD] = gtmsource_options.connect_parms[GTMSOURCE_CONN_SOFT_TRIES_PERIOD]; if (gtmsource_options.connect_parms[GTMSOURCE_CONN_HEARTBEAT_MAX_WAIT] < gtmsource_options.connect_parms[GTMSOURCE_CONN_HEARTBEAT_PERIOD]) gtmsource_options.connect_parms[GTMSOURCE_CONN_HEARTBEAT_MAX_WAIT] = gtmsource_options.connect_parms[GTMSOURCE_CONN_HEARTBEAT_PERIOD]; } if (gtmsource_options.start || gtmsource_options.statslog || gtmsource_options.changelog || gtmsource_options.activate) { log = (cli_present("LOG") == CLI_PRESENT); log_interval_specified = (CLI_PRESENT == cli_present("LOG_INTERVAL")); if (log) { log_file_len = MAX_FN_LEN + 1; if (!cli_get_str("LOG", gtmsource_options.log_file, &log_file_len)) { util_out_print("Error parsing LOG qualifier", TRUE); return(-1); } } else gtmsource_options.log_file[0] = '\0'; gtmsource_options.src_log_interval = 0; if (log_interval_specified) { if (!cli_get_num("LOG_INTERVAL", (int4 *)>msource_options.src_log_interval)) { util_out_print("Error parsing LOG_INTERVAL qualifier", TRUE); return (-1); } } if (gtmsource_options.start && 0 == gtmsource_options.src_log_interval) gtmsource_options.src_log_interval = LOGTRNUM_INTERVAL; /* For changelog/activate, interval == 0 implies don't change log interval already established */ /* We ignore interval specification for statslog, Vinaya 2005/02/07 */ } if (gtmsource_options.start) { assert(secondary || CLI_PRESENT == cli_present("PASSIVE")); gtmsource_options.mode = ((secondary) ? GTMSOURCE_MODE_ACTIVE : GTMSOURCE_MODE_PASSIVE); if (CLI_PRESENT == cli_present("BUFFSIZE")) { if (!cli_get_int("BUFFSIZE", >msource_options.buffsize)) { util_out_print("Error parsing BUFFSIZE qualifier", TRUE); return(-1); } if (MIN_JNLPOOL_SIZE > gtmsource_options.buffsize) gtmsource_options.buffsize = MIN_JNLPOOL_SIZE; } else gtmsource_options.buffsize = DEFAULT_JNLPOOL_SIZE; /* Round up buffsize to the nearest (~JNL_WRT_END_MASK + 1) multiple */ gtmsource_options.buffsize = ((gtmsource_options.buffsize + ~JNL_WRT_END_MASK) & JNL_WRT_END_MASK); if (CLI_PRESENT == cli_present("FILTER")) { filter_cmd_len = MAX_FILTER_CMD_LEN; if (!cli_get_str("FILTER", gtmsource_options.filter_cmd, &filter_cmd_len)) { util_out_print("Error parsing FILTER qualifier", TRUE); return(-1); } } else gtmsource_options.filter_cmd[0] = '\0'; /* Check if compression level is specified */ if (CLI_PRESENT == cli_present("CMPLVL")) { if (!cli_get_int("CMPLVL", >msource_options.cmplvl)) { util_out_print("Error parsing CMPLVL qualifier", TRUE); return(-1); } if (GTM_CMPLVL_OUT_OF_RANGE(gtmsource_options.cmplvl)) gtmsource_options.cmplvl = ZLIB_CMPLVL_MIN; /* no compression in this case */ /* CMPLVL qualifier should override any value specified in the environment variable gtm_zlib_cmp_level */ gtm_zlib_cmp_level = gtmsource_options.cmplvl; } else gtmsource_options.cmplvl = ZLIB_CMPLVL_MIN; /* no compression in this case */ /* Check if SSL/TLS secure communication is requested. */ # ifdef GTM_TLS if (CLI_PRESENT == cli_present("TLSID")) { tlsid_len = MAX_TLSID_LEN; if (!cli_get_str("TLSID", repl_tls.id, &tlsid_len)) { util_out_print("Error parsing TLSID qualifier", TRUE); return -1; } assert(0 < tlsid_len); if (CLI_PRESENT == cli_present("RENEGOTIATE_INTERVAL")) { if (!cli_get_int("RENEGOTIATE_INTERVAL", &renegotiate_interval)) { util_out_print("Error parsing RENEGOTIATE_INTERVAL qualifier", TRUE); return -1; } if (0 > renegotiate_interval) { util_out_print("Negative values are not allowed for RENEGOTIATE_INTERVAL qualifier", TRUE); return -1; } else if ((0 < renegotiate_interval) && (renegotiate_interval < MIN_RENEGOTIATE_TIMEOUT)) renegotiate_interval = MIN_RENEGOTIATE_TIMEOUT; renegotiate_interval = renegotiate_interval * 60; /* Convert to seconds. */ } else renegotiate_interval = DEFAULT_RENEGOTIATE_TIMEOUT * 60; /* Convert to seconds. */ /* Convert renegotiate_interval to heartbeat units (# of 8 second intervals). */ renegotiate_interval = DIVIDE_ROUND_UP(renegotiate_interval, HEARTBEAT_INTERVAL_IN_SECS); gtmsource_options.renegotiate_interval = renegotiate_interval; /* Check if plaintext-fallback mode is specified. Default option is NOPLAINTEXTFALLBACK. */ if (CLI_PRESENT == (plaintext_fallback = cli_present("PLAINTEXTFALLBACK"))) repl_tls.plaintext_fallback = (plaintext_fallback != CLI_NEGATED); else repl_tls.plaintext_fallback = FALSE; } # endif } if (gtmsource_options.shut_down) { if ((timeout_status = cli_present("TIMEOUT")) == CLI_PRESENT) { if (!cli_get_int("TIMEOUT", >msource_options.shutdown_time)) { util_out_print("Error parsing TIMEOUT qualifier", TRUE); return(-1); } if (DEFAULT_SHUTDOWN_TIMEOUT < gtmsource_options.shutdown_time || 0 > gtmsource_options.shutdown_time) { gtmsource_options.shutdown_time = DEFAULT_SHUTDOWN_TIMEOUT; util_out_print("shutdown TIMEOUT changed to !UL", TRUE, gtmsource_options.shutdown_time); } } else if (CLI_NEGATED == timeout_status) gtmsource_options.shutdown_time = -1; else /* TIMEOUT not specified */ gtmsource_options.shutdown_time = DEFAULT_SHUTDOWN_TIMEOUT; } if (gtmsource_options.statslog) { statslog_val_len = 4; /* max(strlen("ON"), strlen("OFF")) + 1 */ if (!cli_get_str("STATSLOG", statslog_val, &statslog_val_len)) { util_out_print("Error parsing STATSLOG qualifier", TRUE); return(-1); } UNIX_ONLY(cli_strupper(statslog_val);) if (0 == STRCMP(statslog_val, "ON"))
int gtmrecv_upd_proc_init(boolean_t fresh_start) { /* Update Process initialization */ mstr upd_proc_log_cmd, upd_proc_trans_cmd; char upd_proc_cmd[UPDPROC_CMD_MAXLEN]; int status; int upd_status, save_upd_status; #ifdef UNIX pid_t upd_pid, waitpid_res; #elif defined(VMS) uint4 upd_pid; uint4 cmd_channel; $DESCRIPTOR(cmd_desc, UPDPROC_CMD_STR); #endif /* Check if the update process is alive */ if ((upd_status = is_updproc_alive()) == SRV_ERR) { gtm_putmsg(VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Receive pool semctl failure"), REPL_SEM_ERRNO); repl_errno = EREPL_UPDSTART_SEMCTL; return(UPDPROC_START_ERR); } else if (upd_status == SRV_ALIVE && !fresh_start) { gtm_putmsg(VARLSTCNT(4) ERR_TEXT, 2, RTS_ERROR_LITERAL("Update process already exists. Not starting it")); return(UPDPROC_EXISTS); } else if (upd_status == SRV_ALIVE) { gtm_putmsg(VARLSTCNT(6) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Update process already exists. Please kill it before a fresh start")); return(UPDPROC_EXISTS); } save_upd_status = recvpool.upd_proc_local->upd_proc_shutdown; recvpool.upd_proc_local->upd_proc_shutdown = NO_SHUTDOWN; #ifdef UNIX if (0 > (upd_pid = fork())) /* BYPASSOK: we exec immediately, no FORK_CLEAN needed */ { recvpool.upd_proc_local->upd_proc_shutdown = save_upd_status; gtm_putmsg(VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Could not fork update process"), errno); repl_errno = EREPL_UPDSTART_FORK; return(UPDPROC_START_ERR); } if (0 == upd_pid) { /* Update Process */ upd_proc_log_cmd.len = SIZEOF(UPDPROC_CMD) - 1; upd_proc_log_cmd.addr = UPDPROC_CMD; status = TRANS_LOG_NAME(&upd_proc_log_cmd, &upd_proc_trans_cmd, upd_proc_cmd, SIZEOF(upd_proc_cmd), dont_sendmsg_on_log2long); if (status != SS_NORMAL) { gtm_putmsg(VARLSTCNT(6) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Could not find path of Update Process. Check value of $gtm_dist")); if (SS_LOG2LONG == status) gtm_putmsg(VARLSTCNT(5) ERR_LOGTOOLONG, 3, LEN_AND_LIT(UPDPROC_CMD), SIZEOF(upd_proc_cmd) - 1); repl_errno = EREPL_UPDSTART_BADPATH; return(UPDPROC_START_ERR); } upd_proc_cmd[upd_proc_trans_cmd.len] = '\0'; if (EXECL(upd_proc_cmd, upd_proc_cmd, UPDPROC_CMD_ARG1, UPDPROC_CMD_ARG2, NULL) < 0) { gtm_putmsg(VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Could not exec Update Process"), errno); repl_errno = EREPL_UPDSTART_EXEC; return(UPDPROC_START_ERR); } } #elif defined(VMS) /* Create detached server and write startup commands to it */ status = repl_create_server(&cmd_desc, "GTMU", "", &cmd_channel, &upd_pid, ERR_RECVPOOLSETUP); if (SS_NORMAL != status) { gtm_putmsg(VARLSTCNT(7) ERR_RECVPOOLSETUP, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Unable to spawn Update process"), status); recvpool.upd_proc_local->upd_proc_shutdown = save_upd_status; repl_errno = EREPL_UPDSTART_FORK; return(UPDPROC_START_ERR); } #endif if (recvpool.upd_proc_local->upd_proc_pid) recvpool.upd_proc_local->upd_proc_pid_prev = recvpool.upd_proc_local->upd_proc_pid; else recvpool.upd_proc_local->upd_proc_pid_prev = upd_pid; recvpool.upd_proc_local->upd_proc_pid = upd_pid; /* Receiver Server; wait for the update process to startup */ REPL_DPRINT2("Waiting for update process %d to startup\n", upd_pid); while (get_sem_info(RECV, UPD_PROC_COUNT_SEM, SEM_INFO_VAL) == 0 && is_proc_alive(upd_pid, 0)) { /* To take care of reassignment of PIDs, the while condition should be && with the * condition (PPID of pid == process_id) */ REPL_DPRINT2("Waiting for update process %d to startup\n", upd_pid); UNIX_ONLY(WAITPID(upd_pid, &status, WNOHANG, waitpid_res);) /* Release defunct update process if dead */ SHORT_SLEEP(GTMRECV_WAIT_FOR_SRV_START); }
int op_open(mval *device, mval *devparms, int timeout, mval *mspace) { char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */ io_log_name *naml; /* logical record for passed name */ io_log_name *tl; /* logical record for translated name */ io_log_name *prev; /* logical record for removal search */ int4 stat; /* status */ mstr tn; /* translated name */ DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; MV_FORCE_STR(device); MV_FORCE_STR(devparms); if (mspace) MV_FORCE_STR(mspace); if (timeout < 0) timeout = 0; else if (TREF(tpnotacidtime) < timeout) TPNOTACID_CHECK(OPENTIMESTR); assert((unsigned char)*devparms->str.addr < n_iops); naml = get_log_name(&device->str, INSERT); if (naml->iod != 0) tl = naml; else { # ifdef NOLICENSE licensed= TRUE; # else CRYPT_CHKSYSTEM; if (!licensed || LP_CONFIRM(lid, lkid)==LP_NOTACQ) licensed= FALSE; # endif switch(stat = TRANS_LOG_NAME(&device->str, &tn, &buf1[0], SIZEOF(buf1), dont_sendmsg_on_log2long)) { case SS_NORMAL: tl = get_log_name(&tn, INSERT); break; case SS_NOLOGNAM: tl = naml; break; default: for (prev = io_root_log_name, tl = prev->next; tl != 0; prev = tl, tl = tl->next) { if (naml == tl) { prev->next = tl->next; free(tl); break; } } # ifdef UNIX if (SS_LOG2LONG == stat) rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, device->str.len, device->str.addr, SIZEOF(buf1) - 1); else # endif rts_error(VARLSTCNT(1) stat); } } stat = io_open_try(naml, tl, devparms, timeout, mspace); return (stat); }
socket_struct *iosocket_create(char *sockaddr, uint4 bfsize, int file_des, boolean_t listen_specified) { socket_struct *socketptr; socket_struct *prev_socketptr; socket_struct *socklist_head; boolean_t passive = FALSE; unsigned short port; int ii, save_errno, tmplen, errlen, sockaddrlen; char temp_addr[SA_MAXLITLEN], protocolstr[6], *adptr; const char *errptr; struct addrinfo *ai_ptr; struct addrinfo hints, *addr_info_ptr = NULL; #ifndef VMS struct sockaddr_un *sa_un_ptr, sa_un_trans; mval localpath; mstr transpath; int trans_status; #endif enum socket_protocol protocol; int af; int sd; int errcode; char host_buffer[NI_MAXHOST]; char port_buffer[NI_MAXSERV]; int port_buffer_len; int colon_cnt, protooffset; char *last_2colon = NULL; int addrlen; GTM_SOCKLEN_TYPE tmp_addrlen; if (0 > file_des) { /* no socket descriptor yet */ memset(&hints, 0, SIZEOF(hints)); protooffset = colon_cnt = 0; sockaddrlen = STRLEN(sockaddr); for (ii = sockaddrlen - 1; 0 <= ii; ii--) { if (SEPARATOR == sockaddr[ii]) { colon_cnt++; if (1 == colon_cnt) protooffset = ii + 1; else { last_2colon = &sockaddr[ii]; break; } } } if (0 == colon_cnt) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVPORTSPEC); return NULL; } tmplen = sockaddrlen - protooffset; if (SIZEOF(protocolstr) <= tmplen) { /* last piece just too big to be valid */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PROTNOTSUP, 2, tmplen , &sockaddr[protooffset]); return NULL; } lower_to_upper((uchar_ptr_t)protocolstr, (uchar_ptr_t)&sockaddr[protooffset], tmplen); if (((SIZEOF("TCP") - 1) == tmplen) && (0 == MEMCMP_LIT(protocolstr, "TCP"))) protocol = socket_tcpip; # ifndef VMS else if (((SIZEOF("LOCAL") - 1) == tmplen) && (0 == MEMCMP_LIT(protocolstr, "LOCAL"))) protocol = socket_local; # endif else { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PROTNOTSUP, 2, tmplen , &sockaddr[protooffset]); return NULL; } if (socket_tcpip == protocol) { if (1 == colon_cnt) { /* for listening socket or broadcasting socket */ if (!listen_specified || (SSCANF(sockaddr, PORT_PROTO_FORMAT, &port, protocolstr) < 2)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVPORTSPEC); return NULL; } passive = TRUE; /* We always first try using IPv6 address, if supported */ af = ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET); if (-1 == (sd = socket(af, SOCK_STREAM, IPPROTO_TCP))) { /* Try creating IPv4 socket */ af = AF_INET; if (-1 == (sd = socket(af, SOCK_STREAM, IPPROTO_TCP))) { save_errno = errno; errptr = (char *)STRERROR(save_errno); errlen = STRLEN(errptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, save_errno, errlen, errptr); return NULL; } } SERVER_HINTS(hints, af); port_buffer_len = 0; I2A(port_buffer, port_buffer_len, port); port_buffer[port_buffer_len]='\0'; if (0 != (errcode = getaddrinfo(NULL, port_buffer, &hints, &addr_info_ptr))) { close(sd); RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return NULL; } SOCKET_ALLOC(socketptr); socketptr->local.port = port; socketptr->temp_sd = sd; socketptr->sd = FD_INVALID; ai_ptr = &(socketptr->local.ai); memcpy(ai_ptr, addr_info_ptr, SIZEOF(struct addrinfo)); SOCKET_AI_TO_LOCAL_ADDR(socketptr, addr_info_ptr); ai_ptr->ai_addr = SOCKET_LOCAL_ADDR(socketptr); ai_ptr->ai_addrlen = addr_info_ptr->ai_addrlen; ai_ptr->ai_next = NULL; freeaddrinfo(addr_info_ptr); } else { /* connection socket */ assert(2 == colon_cnt); if (listen_specified || (SSCANF(last_2colon + 1, PORT_PROTO_FORMAT, &port, protocolstr) < 2)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC); return NULL; } /* for connection socket */ SPRINTF(port_buffer, "%hu", port); addrlen = last_2colon - sockaddr; if ('[' == sockaddr[0]) { if (NULL == memchr(sockaddr, ']', addrlen)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC); return NULL; } addrlen -= 2; memcpy(temp_addr, &sockaddr[1], addrlen); } else memcpy(temp_addr, sockaddr, addrlen); temp_addr[addrlen] = 0; CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(temp_addr, port_buffer, &hints, &addr_info_ptr))) { RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return NULL; } /* we will test all address families in iosocket_connect() */ SOCKET_ALLOC(socketptr); socketptr->remote.ai_head = addr_info_ptr; socketptr->remote.port = port; socketptr->sd = socketptr->temp_sd = FD_INVALID; /* don't mess with 0 */ } # ifndef VMS } else if (socket_local == protocol) { /* should we get_full_path first */ /* check protooffset < sizeof sun_path */ /* protooffset is after colon */ SOCKET_ALLOC(socketptr); socketptr->protocol = socket_local; sa_un_ptr = malloc(SIZEOF(struct sockaddr_un)); sa_un_ptr->sun_family = AF_UNIX; MV_INIT_STRING(&localpath, protooffset - 1, sockaddr); trans_status = TRANS_LOG_NAME(&localpath.str, &transpath, sa_un_trans.sun_path, (int)SIZEOF(sa_un_trans.sun_path), dont_sendmsg_on_log2long); if (SS_LOG2LONG == trans_status) { /* if LOG2LONG, returned len not valid so report untranslated length */ SOCKET_FREE(socketptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ADDRTOOLONG, 4, localpath.str.len, localpath.str.addr, localpath.str.len, SIZEOF(sa_un_trans.sun_path)); return NULL; } memcpy(sa_un_ptr->sun_path, transpath.addr, transpath.len); sa_un_ptr->sun_path[transpath.len] = '\0'; if (listen_specified) { passive = TRUE; socketptr->local.sa = (struct sockaddr *)sa_un_ptr; socketptr->local.ai.ai_family = AF_UNIX; socketptr->local.ai.ai_socktype = SOCK_STREAM; socketptr->local.ai.ai_addrlen = (size_t)((struct sockaddr_un *)0)->sun_path + protooffset; if (-1 == (sd = socket(AF_UNIX, SOCK_STREAM, 0))) { save_errno = errno; SOCKET_FREE(socketptr); errptr = (char *)STRERROR(save_errno); errlen = STRLEN(errptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, save_errno, errlen, errptr); return NULL; } socketptr->temp_sd = sd; socketptr->sd = FD_INVALID; } else { socketptr->remote.sa = (struct sockaddr *)sa_un_ptr; /* setup remote fields */ socketptr->remote.ai.ai_family = AF_UNIX; socketptr->remote.ai.ai_socktype = SOCK_STREAM; socketptr->remote.ai.ai_addrlen = (size_t)((struct sockaddr_un *)0)->sun_path + protooffset; socketptr->sd = socketptr->temp_sd = FD_INVALID; /* don't mess with 0 */ } # endif } else
int4 parse_file(mstr *file, parse_blk *pblk) { struct stat statbuf; struct addrinfo *ai_ptr, *localhost_ai_ptr, *temp_ai_ptr, hints; mstr trans, tmp; int status, diff, local_node_len, query_node_len, node_name_len; parse_blk def; char local_node_name[MAX_HOST_NAME_LEN + 1], query_node_name[MAX_HOST_NAME_LEN + 1]; char *base, *ptr, *top, *del, *node, *name, *ext, ch; char **hostaddrlist; char def_string[MAX_FBUFF + 1]; boolean_t hasnode, hasdir, hasname, hasext, wilddir, wildname; enum parse_state state; struct sockaddr_storage query_sas; struct sockaddr localhost_sa, *localhost_sa_ptr; mval def_trans; int errcode; pblk->fnb = 0; ai_ptr = localhost_ai_ptr = temp_ai_ptr = NULL; assert(((unsigned int)pblk->buff_size + 1) <= (MAX_FBUFF + 1)); /* All callers of parse_blk set buff_size to 1 less than the allocated buffer. This is because buff_size is a char * type (for historical reasons) and so cannot go more than 255 whereas we support a max of 255 characters. So we * allocate buffers that contain one more byte (for the terminating '\0') but dont set that in buff_size. Use * that extra byte for the trans_log_name call. */ status = TRANS_LOG_NAME(file, &trans, pblk->buffer, pblk->buff_size + 1, dont_sendmsg_on_log2long); if (SS_LOG2LONG == status) return ERR_PARBUFSM; assert(trans.addr == pblk->buffer); memset(&def, 0, SIZEOF(def)); /* Initial the defaults to zero */ if (pblk->def1_size > 0) { /* Parse default filespec if supplied */ def.fop = F_SYNTAXO; def.buffer = def_string; def.buff_size = MAX_FBUFF; def.def1_size = pblk->def2_size; def.def1_buf = pblk->def2_buf; tmp.len = pblk->def1_size; tmp.addr = pblk->def1_buf; if ((status = parse_file(&tmp, &def)) != ERR_PARNORMAL) return status; assert(!def.b_node); if (def.b_dir) def.fnb |= F_HAS_DIR; if (def.b_name) def.fnb |= F_HAS_NAME; if (def.b_ext) def.fnb |= F_HAS_EXT; } wildname = wilddir = hasnode = hasdir = hasname = hasext = FALSE; node = base = ptr = trans.addr; top = ptr + trans.len; if ((0 == trans.len) || ('/' != *ptr)) { /* No file given, no full path given, or a nodename was specified */ setzdir(NULL, &def_trans); /* Default current directory if none given */ assert((0 == dollar_zdir.str.len) /* dollar_zdir not initialized yet, possible thru main() -> gtm_chk_dist() */ || ((def_trans.str.len == dollar_zdir.str.len) /* Check if cwd and cached value are the same */ && (0 == memcmp(def_trans.str.addr, dollar_zdir.str.addr, def_trans.str.len)))); if (pblk->fop & F_PARNODE) { /* What we have could be a nodename */ assert(pblk->fop & F_SYNTAXO); while (node < top) { ch = *node++; if (':' == ch) /* We have nodeness */ break; if ('/' == ch) { /* Not a node - bypass node checking */ node = top; break; } } if (node < top) { hasnode = TRUE; ptr = base = node; /* Update pointers past node name */ /* See if the desired (query) node is the local node */ node_name_len = (int)(node - trans.addr); /* Scanned node including ':' */ query_node_len = node_name_len - 1; /* Pure name length, no ':' on end */ assert(MAX_HOST_NAME_LEN >= query_node_len); assert(0 < query_node_len); assert(':' == *(trans.addr + query_node_len)); memcpy(query_node_name, trans.addr, query_node_len); query_node_name[query_node_len] = 0; localhost_sa_ptr = NULL; /* Null value needed if not find query node (remote default) */ CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(query_node_name, NULL, &hints, &ai_ptr))) /* Assignment! */ ai_ptr = NULL; /* Skip additional lookups */ else memcpy((sockaddr_ptr)&query_sas, ai_ptr->ai_addr, ai_ptr->ai_addrlen); CLIENT_HINTS(hints); if (0 == (errcode = getaddrinfo(LOCALHOSTNAME, NULL, &hints, &localhost_ai_ptr)) && (0 == memcmp(localhost_ai_ptr->ai_addr, (sockaddr_ptr)&query_sas, localhost_ai_ptr->ai_addrlen))) { localhost_sa_ptr = localhost_ai_ptr->ai_addr; } FREEADDRINFO(localhost_ai_ptr); if (ai_ptr && !localhost_sa_ptr) { /* Have not yet established this is not a local node -- check further */ GETHOSTNAME(local_node_name, MAX_HOST_NAME_LEN, status); if (-1 == status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("gethostname"), CALLFROM, errno); CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(local_node_name, NULL, &hints, &localhost_ai_ptr))) localhost_ai_ptr = NULL; /* Empty address list */ for (temp_ai_ptr = localhost_ai_ptr; temp_ai_ptr!= NULL; temp_ai_ptr = temp_ai_ptr->ai_next) { if (0 == memcmp((sockaddr_ptr)&query_sas, temp_ai_ptr->ai_addr, temp_ai_ptr->ai_addrlen)) { localhost_sa_ptr = temp_ai_ptr->ai_addr; break; /* Tiz truly a local node */ } } FREEADDRINFO(localhost_ai_ptr); } if (ai_ptr && !localhost_sa_ptr) { CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(LOCALHOSTNAME6, NULL, &hints, &localhost_ai_ptr))) localhost_ai_ptr = NULL; /* Empty address list */ for (temp_ai_ptr = localhost_ai_ptr; temp_ai_ptr!= NULL; temp_ai_ptr = temp_ai_ptr->ai_next) { if (0 == memcmp((sockaddr_ptr)&query_sas, temp_ai_ptr->ai_addr, temp_ai_ptr->ai_addrlen)) { localhost_sa_ptr = temp_ai_ptr->ai_addr; break; /* Tiz truly a local node */ } } FREEADDRINFO(localhost_ai_ptr); } if (!localhost_sa_ptr) /* Not local (or an unknown) host given */ { /* Remote node specified -- don't apply any defaults */ FREEADDRINFO(ai_ptr); pblk->l_node = trans.addr; pblk->b_node = node_name_len; pblk->l_dir = base; pblk->b_dir = top - base; pblk->l_name = pblk->l_ext = base + pblk->b_dir; pblk->b_esl = pblk->b_node + pblk->b_dir; pblk->b_name = pblk->b_ext = 0; pblk->fnb |= (hasnode << V_HAS_NODE); return ERR_PARNORMAL; } FREEADDRINFO(ai_ptr); /* Remove local node name from filename buffer */ assert(0 < trans.len - node_name_len); memmove(trans.addr, node, trans.len - node_name_len); ptr = base = node -= node_name_len; top -= node_name_len; trans.len -= node_name_len; if ('/' == *base) /* No default directory if full path given */ def_trans.str.len = 0; } else { /* Supplied text was not a node -- reset pointer back to beginning for rescan */ node = trans.addr; } } /* If parse buffer is not large enough, return error */ if (def_trans.str.len + trans.len > pblk->buff_size) return ERR_PARBUFSM; /* Construct full filename to parse prefixing given filename with default path prefix */ if (0 < def_trans.str.len) { memmove(ptr + def_trans.str.len, ptr, trans.len); memcpy(ptr, def_trans.str.addr, def_trans.str.len); assert('/' == ptr[def_trans.str.len - 1]); ptr += def_trans.str.len; top += def_trans.str.len; } } name = ptr; state = NOSTATE; for (; ptr < top;) { ch = *ptr; if ('.' == ch) { /* Could be /./ or /../ or name.name */ ptr++; state = (DOT1 == state) ? ((DOT2 == state) ? NAME : DOT2) : DOT1; } else if (ch == '/') { /* We must still be doing the path */ ptr++; hasdir = TRUE; hasname = FALSE; hasext = FALSE; wilddir |= wildname; wildname = FALSE; if ((DOT1 != state) && (DOT2 != state) && (SLASH != state)) { /* No dots seen recently so scan as if this is start of filename */ state = SLASH; name = ptr; continue; } if (DOT1 == state) { /* Just remove "./" chars from path */ del = ptr - 2; } else if (DOT2 == state) { /* Have xx/../ construct. Remove /../ and previous level directory from path */ del = ptr - 4; /* /../ characters being removed */ assert ('/' == *del); if (del > base) { del--; while ('/' != *del) del--; } assert((del >= base) && ('/' == *del)); del++; } else if (SLASH == state) { /* Remove duplicate slash from path */ del = ptr - 1; while ((ptr < top) && ('/' == *ptr)) ptr++; } memmove(del, ptr, top - ptr); diff = (int)(ptr - del); ptr -= diff; top -= diff; state = SLASH; name = ptr; } else { /* Hopeful of filename */ hasname = TRUE; while (ptr < top) /* Do small scan looking for filename end */ { ch = *ptr; if ('/' == ch) break; /* Ooops, still doing path */ if ('.' == ch) {/* Filename has an extension */ hasext = TRUE; ext = ptr; } else if (('?' == ch) || ('*' == ch)) wildname = TRUE; ptr++; } state = NAME; } } /* Handle scan end with non-normal state */ if ((SLASH == state) || (DOT1 == state) || (DOT2 == state)) { assert(!hasname && !hasext); hasdir = TRUE; if (state == DOT1) { /* Ignore ./ */ top--; ptr--; } if (DOT2 == state) { /* Ignore ../ plus last directory level specified */ del = ptr - 3; /* on the end */ assert ('/' == *del); if (del > base) { del--; while ('/' != *del) del--; } assert((del >= base) && ('/' == *del)); del++; ptr = top = del; name = ptr; } } if (!hasname) { assert(!hasext); name = ptr; if (def.fnb & F_HAS_NAME) { /* Use default filename if we didn't find one */ diff = (int)(name - node); if (def.b_name + diff > pblk->buff_size) return ERR_PARBUFSM; memcpy(name, def.l_name, def.b_name); ptr += def.b_name; } ext = ptr; } if (!hasext) { ext = ptr; if (def.fnb & F_HAS_EXT) { /* Use default file extension if we didn't find one */ diff = (int)((ext - node)); if (def.b_ext + diff > pblk->buff_size) return ERR_PARBUFSM; memcpy(ext, def.l_ext, def.b_ext); ptr += def.b_ext; } } pblk->b_name = ext - name; pblk->b_ext = ptr - ext; if (!hasdir && (def.fnb & F_HAS_DIR)) { diff = (int)(name - base); diff = def.b_dir - diff; if (def.b_dir + pblk->b_name + pblk->b_ext > pblk->buff_size) return ERR_PARBUFSM; if (diff > 0) memmove(name + diff, name, pblk->b_name + pblk->b_ext); else if (diff < 0) memcpy(name + diff, name, pblk->b_name + pblk->b_ext); memcpy(base, def.l_dir, def.b_dir); ptr += diff; name += diff; } pblk->b_dir = name - base; pblk->b_esl = ptr - base; pblk->l_dir = base; pblk->l_name = base + pblk->b_dir; pblk->l_ext = pblk->l_name + pblk->b_name; pblk->fnb |= (hasdir << V_HAS_DIR); pblk->fnb |= (hasname << V_HAS_NAME); pblk->fnb |= (hasext << V_HAS_EXT); pblk->fnb |= (wildname << V_WILD_NAME); pblk->fnb |= (wilddir << V_WILD_DIR); if (!(pblk->fop & F_SYNTAXO) && !wilddir) { assert('/' == pblk->l_dir[pblk->b_dir - 1]); if (pblk->b_dir > 1) { pblk->l_dir[pblk->b_dir - 1] = 0; STAT_FILE(pblk->l_dir, &statbuf, status); pblk->l_dir[pblk->b_dir - 1] = '/'; if ((-1 == status) || !(statbuf.st_mode & S_IFDIR)) return ERR_FILENOTFND; } } return ERR_PARNORMAL; }
short rc_fnd_file(rc_xdsid *xdsid) { gv_namehead *g; short dsid, node; gd_binding *map; char buff[1024], *cp, *cp1; mstr fpath1, fpath2; mval v; int i, keysize; int len, node2; GET_SHORT(dsid, &xdsid->dsid.value); GET_SHORT(node, &xdsid->node.value); if (!dsid_list) { /* open special database, set up entry */ dsid_list = (rc_dsid_list *)malloc(SIZEOF(rc_dsid_list)); dsid_list->dsid = RC_NSPACE_DSID; dsid_list->next = NULL; fpath1.addr = RC_NSPACE_PATH; fpath1.len = SIZEOF(RC_NSPACE_PATH); if (SS_NORMAL != TRANS_LOG_NAME(&fpath1, &fpath2, buff, SIZEOF(buff), do_sendmsg_on_log2long)) { char msg[256]; SPRINTF(msg, "Invalid DB filename, \"%s\"", fpath1.addr); gtcm_rep_err(msg, errno); return RC_BADFILESPEC; } if (fpath2.len > MAX_FN_LEN) return RC_BADFILESPEC; dsid_list->fname = (char *)malloc(fpath2.len + 1); memcpy(dsid_list->fname, fpath2.addr, fpath2.len); *((char*)(dsid_list->fname + fpath2.len)) = 0; gv_cur_region = (gd_region *)malloc(SIZEOF(gd_region)); memset(gv_cur_region, 0, SIZEOF(gd_region)); gv_cur_region->dyn.addr = (gd_segment *)malloc(SIZEOF(gd_segment)); memset(gv_cur_region->dyn.addr, 0, SIZEOF(gd_segment)); memcpy(gv_cur_region->dyn.addr->fname, fpath2.addr, fpath2.len); gv_cur_region->dyn.addr->fname_len = fpath2.len; gv_cur_region->dyn.addr->acc_meth = dba_bg; ESTABLISH_RET(rc_fnd_file_ch1, RC_SUCCESS); gvcst_init(gv_cur_region); REVERT; change_reg(); /* check to see if this DB has the reserved bytes field set * correctly. Global pages must always have some extra unused * space left in them (RC_RESERVED bytes) so that the page * will fit into the client buffer when unpacked by the * client. */ if (cs_data->reserved_bytes < RC_RESERVED) { OMI_DBG((omi_debug, "Unable to access database file: \"%s\"\nReserved_bytes field in the file header is too small for GT.CM\n", fpath2.addr)); free(dsid_list->fname); dsid_list->fname = NULL; free(dsid_list); dsid_list = NULL; free(gv_cur_region->dyn.addr); gv_cur_region->dyn.addr = NULL; free(gv_cur_region); gv_cur_region = NULL; return RC_FILEACCESS; } gv_keysize = DBKEYSIZE(gv_cur_region->max_key_size); GVKEY_INIT(gv_currkey, gv_keysize); GVKEY_INIT(gv_altkey, gv_keysize); cs_addrs->dir_tree = (gv_namehead *)malloc(SIZEOF(gv_namehead) + 2 * SIZEOF(gv_key) + 3 * (gv_keysize - 1)); g = cs_addrs->dir_tree; g->first_rec = (gv_key*)(g->clue.base + gv_keysize); g->last_rec = (gv_key*)(g->first_rec->base + gv_keysize); g->clue.top = g->last_rec->top = g->first_rec->top = gv_keysize; g->clue.prev = g->clue.end = 0; g->root = DIR_ROOT; dsid_list->gda = (gd_addr*)malloc(SIZEOF(gd_addr) + 3 * SIZEOF(gd_binding)); dsid_list->gda->n_maps = 3; dsid_list->gda->n_regions = 1; dsid_list->gda->n_segments = 1; dsid_list->gda->maps = (gd_binding*)((char*)dsid_list->gda + SIZEOF(gd_addr)); dsid_list->gda->max_rec_size = gv_cur_region->max_rec_size; map = dsid_list->gda->maps; map ++; memset(map->name, 0, SIZEOF(map->name)); map->name[0] = '%'; map->reg.addr = gv_cur_region; map++; map->reg.addr = gv_cur_region; memset(map->name, -1, SIZEOF(map->name)); dsid_list->gda->tab_ptr = (hash_table_mname *)malloc(SIZEOF(hash_table_mname)); init_hashtab_mname(dsid_list->gda->tab_ptr, 0, HASHTAB_NO_COMPACT, HASHTAB_NO_SPARE_TABLE); change_reg(); if (rc_overflow->top < cs_addrs->hdr->blk_size) { if (rc_overflow->buff) free(rc_overflow->buff); rc_overflow->top = cs_addrs->hdr->blk_size; rc_overflow->buff = (char*)malloc(rc_overflow->top); if (rc_overflow_size < rc_overflow->top) rc_overflow_size = rc_overflow->top; } } for (fdi_ptr = dsid_list; fdi_ptr && (fdi_ptr->dsid != dsid); fdi_ptr = fdi_ptr->next) ; if (!fdi_ptr) { /* need to open new database, add to list, set fdi_ptr */ gd_header = dsid_list->gda; gv_currkey->end = 0; v.mvtype = MV_STR; v.str.len = RC_NSPACE_GLOB_LEN-1; v.str.addr = RC_NSPACE_GLOB; GV_BIND_NAME_AND_ROOT_SEARCH(gd_header, &v.str); if (!gv_target->root) /* No namespace global */ return RC_UNDEFNAMSPC; v.mvtype = MV_STR; v.str.len = SIZEOF(RC_NSPACE_DSI_SUB)-1; v.str.addr = RC_NSPACE_DSI_SUB; mval2subsc(&v,gv_currkey); node2 = node; MV_FORCE_MVAL(&v,node2); mval2subsc(&v,gv_currkey); i = dsid / 256; MV_FORCE_MVAL(&v,i); mval2subsc(&v,gv_currkey); if (gvcst_get(&v)) return RC_UNDEFNAMSPC; for (cp = v.str.addr, i = 1; i < RC_FILESPEC_PIECE; i++) for (; *cp++ != RC_FILESPEC_DELIM; ) ; for (cp1 = cp; *cp1++ != RC_FILESPEC_DELIM; ) ; cp1--; len = (int)(cp1 - cp); if (len > MAX_FN_LEN) return RC_BADFILESPEC; fdi_ptr = (rc_dsid_list *)malloc(SIZEOF(rc_dsid_list)); fdi_ptr->fname = (char *)malloc(len+1); fdi_ptr->dsid = dsid; memcpy(fdi_ptr->fname, cp, len); *(fdi_ptr->fname + (len)) = 0; gv_cur_region = (gd_region *)malloc(SIZEOF(gd_region)); memset(gv_cur_region, 0, SIZEOF(gd_region)); gv_cur_region->dyn.addr = (gd_segment *)malloc(SIZEOF(gd_segment)); memset(gv_cur_region->dyn.addr, 0, SIZEOF(gd_segment)); memcpy(gv_cur_region->dyn.addr->fname, cp, len); gv_cur_region->dyn.addr->fname_len = len; gv_cur_region->dyn.addr->acc_meth = dba_bg; ESTABLISH_RET(rc_fnd_file_ch2, RC_SUCCESS); gvcst_init(gv_cur_region); REVERT; change_reg(); /* check to see if this DB has the reserved bytes field set * correctly. Global pages must always have some extra unused * space left in them (RC_RESERVED bytes) so that the page * will fit into the client buffer when unpacked by the * client. */ if (cs_data->reserved_bytes < RC_RESERVED) { OMI_DBG((omi_debug, "Unable to access database file: \"%s\"\nReserved_bytes field in the file header is too small for GT.CM\n", fdi_ptr->fname)); free(dsid_list->fname); dsid_list->fname = NULL; free(dsid_list); dsid_list = NULL; free(gv_cur_region->dyn.addr); gv_cur_region->dyn.addr = NULL; free(gv_cur_region); gv_cur_region = NULL; return RC_FILEACCESS; } assert(!cs_addrs->hold_onto_crit); /* this ensures we can safely do unconditional grab_crit and rel_crit */ grab_crit(gv_cur_region); cs_data->rc_srv_cnt++; if (!cs_data->dsid) { cs_data->dsid = dsid; cs_data->rc_node = node; } else if (cs_data->dsid != dsid || cs_data->rc_node != node) { cs_data->rc_srv_cnt--; rel_crit(gv_cur_region); OMI_DBG((omi_debug, "Dataset ID/RC node mismatch")); OMI_DBG((omi_debug, "DB file: \"%s\"\n", dsid_list->fname)); OMI_DBG((omi_debug, "Stored DSID: %d\tRC Node: %d\n", cs_data->dsid, cs_data->rc_node)); OMI_DBG((omi_debug, "RC Rq DSID: %d\tRC Node: %d\n", dsid,node)); free(fdi_ptr->fname); fdi_ptr->fname = NULL; free(fdi_ptr); fdi_ptr = NULL; free(gv_cur_region->dyn.addr); gv_cur_region->dyn.addr = NULL; free(gv_cur_region); gv_cur_region = NULL; return RC_FILEACCESS; } rel_crit(gv_cur_region); keysize = DBKEYSIZE(gv_cur_region->max_key_size); GVKEYSIZE_INCREASE_IF_NEEDED(keysize); cs_addrs->dir_tree = (gv_namehead *)malloc(SIZEOF(gv_namehead) + 2 * SIZEOF(gv_key) + 3 * (keysize - 1)); g = cs_addrs->dir_tree; g->first_rec = (gv_key*)(g->clue.base + keysize); g->last_rec = (gv_key*)(g->first_rec->base + keysize); g->clue.top = g->last_rec->top = g->first_rec->top = keysize; g->clue.prev = g->clue.end = 0; g->root = DIR_ROOT; fdi_ptr->gda = (gd_addr*)malloc(SIZEOF(gd_addr) + 3 * SIZEOF(gd_binding)); fdi_ptr->gda->n_maps = 3; fdi_ptr->gda->n_regions = 1; fdi_ptr->gda->n_segments = 1; fdi_ptr->gda->maps = (gd_binding*)((char*)fdi_ptr->gda + SIZEOF(gd_addr)); fdi_ptr->gda->max_rec_size = gv_cur_region->max_rec_size; map = fdi_ptr->gda->maps; map ++; memset(map->name, 0, SIZEOF(map->name)); map->name[0] = '%'; map->reg.addr = gv_cur_region; map++; map->reg.addr = gv_cur_region; memset(map->name, -1, SIZEOF(map->name)); fdi_ptr->gda->tab_ptr = (hash_table_mname *)malloc(SIZEOF(hash_table_mname)); init_hashtab_mname(fdi_ptr->gda->tab_ptr, 0, HASHTAB_NO_COMPACT, HASHTAB_NO_SPARE_TABLE); fdi_ptr->next = dsid_list->next; dsid_list->next = fdi_ptr; } gv_cur_region = fdi_ptr->gda->maps[1].reg.addr; change_reg(); if (rc_overflow->top < cs_addrs->hdr->blk_size) { if (rc_overflow->buff) free(rc_overflow->buff); rc_overflow->top = cs_addrs->hdr->blk_size; rc_overflow->buff = (char*)malloc(rc_overflow->top); if (rc_overflow_size < rc_overflow->top) rc_overflow_size = rc_overflow->top; } if (!rc_overflow -> top) { rc_overflow -> top = rc_overflow_size; rc_overflow->buff = (char *)malloc(rc_overflow->top); } gd_header = fdi_ptr->gda; return RC_SUCCESS; }
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; }
void op_use(mval *v, mval *p) { char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */ io_log_name *nl; /* logical record for passed name */ io_log_name *tl; /* logical record for translated name */ int4 stat; /* status */ mstr tn; /* translated name */ int dollar_zpselect; /* 0 - both, 1 - input only, 2 - output only */ char *c1; /* used to compare $P name */ int nlen; /* len of $P name */ io_log_name *tlp; /* logical record for translated name for $principal */ MV_FORCE_STR(v); MV_FORCE_STR(p); dollar_zpselect = 0; if (io_std_device->in != io_std_device->out) { /* if there is a split $P then determine from the name if it is the value of "$P< /" or "$P> /" if the first then it is $ZPIN so set dollar_zpselect to 1 if the second then it is $ZPOUT so set dollar_zpselect to 2 else set dollar_zpselect to 0 if it is $ZPIN or $ZPOUT get the log_name for $P into nl else use the mval v passed in */ tlp = dollar_principal ? dollar_principal : io_root_log_name->iod->trans_name; nlen = tlp->len; assert(dollar_zpout.len == dollar_zpin.len); if ((nlen + dollar_zpin.len) == v->str.len) { /* passed the length test now compare the 2 pieces, the first one the length of $P and the second $ZPIN or $ZPOUT */ c1 = (char *)tlp->dollar_io; if (!memvcmp(c1, nlen, &(v->str.addr[0]), nlen)) { if (!memvcmp(dollar_zpin.addr, dollar_zpin.len, &(v->str.addr[nlen]), dollar_zpin.len)) dollar_zpselect = 1; else if (!memvcmp(dollar_zpout.addr, dollar_zpout.len, &(v->str.addr[nlen]), dollar_zpout.len)) dollar_zpselect = 2; } } } if (0 == dollar_zpselect) nl = get_log_name(&v->str, NO_INSERT); else nl = get_log_name(&dollar_prin_log, NO_INSERT); if (!nl) { stat = TRANS_LOG_NAME(&v->str, &tn, buf1, SIZEOF(buf1), do_sendmsg_on_log2long); if (stat != SS_NORMAL) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_IONOTOPEN); else { if ((tl = get_log_name(&tn, NO_INSERT)) == 0) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_IONOTOPEN); if (!tl->iod) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_IONOTOPEN); nl = get_log_name(&v->str, INSERT); nl->iod = tl->iod; } } if (nl->iod->state != dev_open) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_IONOTOPEN); if (dollar_principal && nl->iod == dollar_principal->iod) { /* if device is a GTM_PRINCIPAL synonym */ nl = dollar_principal; } else { /* special case U "" , U 0, U $ZPIN, U $ZPOUT to be equivalent to U $P */ /* $ZPIN or $ZPOUT force nl to "0" */ /* note: "" is always the root */ if (nl == io_root_log_name || ((1 == nl->len) && ('0' == nl->dollar_io[0]))) nl = nl->iod->trans_name; } active_device = nl->iod; io_curr_device = nl->iod->pair; io_curr_device.in->name = nl; if (nl->iod->pair.in == nl->iod->pair.out) (nl->iod->disp_ptr->use)(nl->iod, p); else { if (2 != dollar_zpselect) (nl->iod->disp_ptr->use)(nl->iod, p); if (1 != dollar_zpselect) (nl->iod->pair.out->disp_ptr->use)(nl->iod->pair.out, p); } active_device = 0; return; }
void io_init(bool term_ctrl) { static readonly unsigned char open_params_list[2] = { (unsigned char)iop_newversion, (unsigned char)iop_eol }; static readonly unsigned char null_params_list[2] = { (unsigned char)iop_nl, (unsigned char)iop_eol }; static readonly unsigned char no_params = (unsigned char)iop_eol; static readonly unsigned char shr_params[3] = { (unsigned char)iop_shared, (unsigned char)iop_readonly, (unsigned char)iop_eol }; int4 status; mval val; mstr tn; MSTR_CONST (gtm_netout, "GTM_NETOUT"); MSTR_CONST (sys_net, "SYS$NET"); char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */ mval pars; io_log_name *inp, *outp; io_log_name *ln; error_def(ERR_LOGTOOLONG); io_init_name(); /* default logical names */ io_root_log_name = (io_log_name *)malloc(SIZEOF(*io_root_log_name)); memset(io_root_log_name, 0, SIZEOF(*io_root_log_name)); val.mvtype = MV_STR; val.str.addr = "0"; val.str.len = 1; ln = get_log_name(&val.str, INSERT); assert(ln != 0); val.str = gtm_principal; status = TRANS_LOG_NAME(&val.str, &tn, buf1, SIZEOF(buf1), dont_sendmsg_on_log2long); if (SS_NOLOGNAM == status) dollar_principal = 0; else if (SS_NORMAL == status) dollar_principal = get_log_name(&tn, INSERT); # ifdef UNIX else if (SS_LOG2LONG == status) rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1); # endif else rts_error(VARLSTCNT(1) status); /* open devices */ val.str = sys_input; inp = get_log_name(&val.str, INSERT); pars.mvtype = MV_STR; status = TRANS_LOG_NAME(&val.str, &tn, buf1, SIZEOF(buf1), dont_sendmsg_on_log2long); if (SS_NOLOGNAM == status) { pars.str.len = SIZEOF(null_params_list); pars.str.addr = (char *)null_params_list; } else if (SS_NORMAL == status) { if (!io_is_rm(&val.str)) { pars.str.len = SIZEOF(no_params); pars.str.addr = (char *)&no_params; } else if (io_is_sn(&val.str)) { pars.str.len = SIZEOF(open_params_list); pars.str.addr = (char *)open_params_list; } else { pars.str.len = SIZEOF(shr_params); pars.str.addr = (char *)shr_params; } } # ifdef UNIX else if (SS_LOG2LONG == status) rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1); # endif else rts_error(VARLSTCNT(1) status); ESTABLISH(io_init_ch); (*op_open_ptr)(&val, &pars, 0, 0); io_curr_device.in = io_std_device.in = inp->iod; val.str = sys_output; if ((SS_NORMAL == TRANS_LOG_NAME(>m_netout, &tn, buf1, SIZEOF(buf1), do_sendmsg_on_log2long)) && (SS_NORMAL == TRANS_LOG_NAME(&sys_net, &tn, buf1, SIZEOF(buf1), do_sendmsg_on_log2long)) && io_is_sn(&sys_net)) val.str = sys_net; outp = get_log_name(&val.str, INSERT); status = TRANS_LOG_NAME(&val.str, &tn, buf1, SIZEOF(buf1), dont_sendmsg_on_log2long); if ((SS_NORMAL != status) && (SS_NOLOGNAM != status)) { # ifdef UNIX if (SS_LOG2LONG == status) rts_error(VARLSTCNT(5) ERR_LOGTOOLONG, 3, val.str.len, val.str.addr, SIZEOF(buf1) - 1); else # endif rts_error(VARLSTCNT(1) status); } if ((val.str.addr == sys_net.addr) && (pars.str.addr == (char *)open_params_list)) /* sys$net is the only input thing that uses open_params_list */ outp->iod = io_curr_device.in; /* For terminals and mailboxes and sockets, SYS$INPUT and SYS$OUTPUT may point to the same device. If input is one of those, then check translated name for output against translated name for input; in that case they should be joined by their logical names */ if (((tt == io_curr_device.in->type) || (mb == io_curr_device.in->type) || (gtmsocket == io_curr_device.in->type)) && same_device_check(tn, buf1)) outp->iod = io_curr_device.in; if (!outp->iod) { if (status == SS_NOLOGNAM) { pars.str.len = SIZEOF(null_params_list); pars.str.addr = (char *)null_params_list; } else if (status == SS_NORMAL) { pars.str.len = SIZEOF(open_params_list); pars.str.addr = (char *)open_params_list; } (*op_open_ptr)(&val, &pars, 0, 0); } io_curr_device.out = io_std_device.out = outp->iod; term_setup(term_ctrl); io_std_device.out->pair = io_std_device; io_std_device.in->pair = io_std_device; io_std_device.out->perm = io_std_device.in->perm = TRUE; for (ln = io_root_log_name; ln; ln = ln->next) ln->iod = io_std_device.in; if (dollar_principal) dollar_principal->iod = io_std_device.in; pars.str.len = SIZEOF(no_params); pars.str.addr = (char *)&no_params; val.str.len = io_curr_device.in->trans_name->len; val.str.addr = io_std_device.in->trans_name->dollar_io; op_use(&val, &pars); REVERT; return; }