int gtm_init() { rhdtyp *base_addr; unsigned char *transfer_addr; error_def(ERR_CITPNESTED); error_def(ERR_CIMAXLEVELS); if (!gtm_startup_active) { /* call-in invoked from C as base. GT.M hasn't been started up yet. */ image_type = GTM_IMAGE; gtm_env_init(); /* read in all environment variables */ err_init(stop_image_conditional_core); cli_lex_setup(0, NULL); /* Initialize msp to the maximum so if errors occur during GT.M startup below, * the unwind logic in gtmci_ch() will get rid of the whole stack. */ msp = (unsigned char*)-1; } ESTABLISH_RET(gtmci_ch, mumps_status); if (!gtm_startup_active) { /* GT.M is not active yet. Create GT.M startup environment */ invocation_mode = MUMPS_CALLIN; init_gtm(); gtm_savetraps(); /* nullify default $ZTRAP handling */ assert(gtm_startup_active); assert(frame_pointer->flags & SFF_CI); nested_level = 1; } else if (!(frame_pointer->flags & SFF_CI)) { /* Nested call-in: setup a new CI environment (SFF_CI frame on top of base-frame) */ /* Mark the beginning of the new stack so that initialization errors in * call-in frame do not unwind entries of the previous stack (see gtmci_ch).*/ fgncal_stack = msp; /* Report if condition handlers stack may overrun during this callin level. * Every underlying level can not have more than 2 active condition handlers, * plus extra MAX_HANDLERS are reserved for this level. */ if (chnd_end - ctxt <= MAX_HANDLERS) rts_error(VARLSTCNT(3) ERR_CIMAXLEVELS, 1, nested_level); /* Disallow call-ins within a TP boundary since TP restarts are not supported * currently across nested call-ins. When we implement TP restarts across call-ins, * this error needs be changed to a Warning or Notification */ if (0 < dollar_tlevel) rts_error(VARLSTCNT(1) ERR_CITPNESTED); base_addr = make_cimode(); transfer_addr = PTEXT_ADR(base_addr); gtm_init_env(base_addr, transfer_addr); SET_CI_ENV(ci_ret_code_exit); gtmci_isv_save(); nested_level++; } /* Now that GT.M is initialized. Mark the new stack pointer (msp) so that errors * while executing an M routine do not unwind stack below this mark. It important that * the call-in frames (SFF_CI), that hold nesting information (eg. $ECODE/$STACK data * of the previous stack), are kept from being unwound. */ fgncal_stack = msp; REVERT; return 0; }
int main (int argc, char **argv) { int res; DCL_THREADGBL_ACCESS; GTM_THREADGBL_INIT; set_blocksig(); gtm_imagetype_init(MUPIP_IMAGE); invocation_mode = MUMPS_UTILTRIGR; gtm_wcswidth_fnptr = gtm_wcswidth; gtm_env_init(); /* read in all environment variables */ err_init(util_base_ch); UNICODE_ONLY(gtm_strToTitle_ptr = >m_strToTitle); GTM_ICU_INIT_IF_NEEDED; /* Note: should be invoked after err_init (since it may error out) and before CLI parsing */ sig_init(generic_signal_handler, NULL, suspsigs_handler, continue_handler); /* Note: no ^C handler is defined (yet) */ atexit(mupip_exit_handler); licensed = TRUE; in_backup = FALSE; op_open_ptr = mu_op_open; mu_get_term_characterstics(); cli_lex_setup(argc,argv); if (argc < 2) /* Interactive mode */ display_prompt(); /* this call should be after cli_lex_setup() due to S390 A/E conversion */ gtm_chk_dist(argv[0]); INIT_GBL_ROOT(); /* Needed for GVT initialization */ init_gtm(); while (TRUE) { func = 0; if ((res = parse_cmd()) == EOF) break; else if (res) { if (1 < argc) rts_error(VARLSTCNT(4) res, 2, LEN_AND_STR(cli_err_str)); else gtm_putmsg(VARLSTCNT(4) res, 2, LEN_AND_STR(cli_err_str)); } if (func) func(); if (argc > 1) /* Non-interactive mode, exit after command */ break; display_prompt(); } mupip_exit(SS_NORMAL); }
int gtm_main (int argc, char **argv, char **envp) #ifdef __osf__ # pragma pointer_size (restore) #endif { char *ptr, *eq, **p; int eof, parse_ret; int gtmcrypt_errno; # ifdef GTM_SOCKET_SSL_SUPPORT int status; char tlsid_env_name[MAX_TLSID_LEN * 2]; # endif DCL_THREADGBL_ACCESS; GTM_THREADGBL_INIT; gtmenvp = envp; gtm_dist_ok_to_use = TRUE; common_startup_init(GTM_IMAGE); GTMTRIG_DBG_ONLY(ch_at_trigger_init = &mdb_condition_handler); err_init(stop_image_conditional_core); UNICODE_ONLY(gtm_strToTitle_ptr = >m_strToTitle); GTM_ICU_INIT_IF_NEEDED; /* Note: should be invoked after err_init (since it may error out) and before CLI parsing */ cli_lex_setup(argc, argv); /* put the arguments into buffer, then clean up the token buffer * cli_gettoken() copies all arguments except the first one argv[0] * into the buffer (cli_lex_in_ptr->in_str). * i.e. command line: "/usr/library/V990/mumps -run somefile" * the buffer cli_lex_in_ptr->in_str == "-run somefile" */ if (1 < argc) cli_gettoken(&eof); /* cli_gettoken() extracts the first token into cli_token_buf (in tok_extract()) * which should be done in parse_cmd(), So, reset the token buffer here to make * parse_cmd() starts from the first token */ cli_token_buf[0] = '\0'; /* insert the "MUMPS " in the parsing buffer the buffer is now: * cli_lex_in_ptr->in_str == "MUMPS -run somefile" * we didnot change argv[0] */ ptr = cli_lex_in_ptr->in_str; memmove(strlen("MUMPS ") + ptr, ptr, strlen(ptr) + 1); /* BYPASSOK */ MEMCPY_LIT(ptr, "MUMPS "); /* reset the argument buffer pointer, it's changed in cli_gettoken() call above * do NOT reset to 0(NULL) to avoid fetching cmd line args into buffer again * cli_lex_in_ptr->tp is the pointer to indicate current position in the buffer * cli_lex_in_ptr->in_str */ cli_lex_in_ptr->tp = cli_lex_in_ptr->in_str; parse_ret = parse_cmd(); if (parse_ret && (EOF != parse_ret)) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) parse_ret, 2, LEN_AND_STR(cli_err_str)); if (cli_present("DIRECT_MODE")) invocation_mode = MUMPS_DIRECT; else if (cli_present("RUN")) invocation_mode = MUMPS_RUN; gtm_chk_dist(argv[0]); /* this should be after cli_lex_setup() due to S390 A/E conversion in cli_lex_setup */ init_gtm(); # ifdef GTM_TLS if (MUMPS_COMPILE != invocation_mode) { if ((NULL != (ptr = (char *)getenv(GTM_PASSWD_ENV))) && (0 == strlen(ptr))) { INIT_PROC_ENCRYPTION(NULL, gtmcrypt_errno); if (0 != gtmcrypt_errno) { CLEAR_CRYPTERR_MASK(gtmcrypt_errno); assert(!IS_REPEAT_MSG_MASK(gtmcrypt_errno)); assert((ERR_CRYPTDLNOOPEN == gtmcrypt_errno) || (ERR_CRYPTINIT == gtmcrypt_errno)); if (ERR_CRYPTDLNOOPEN == gtmcrypt_errno) gtmcrypt_errno = ERR_CRYPTDLNOOPEN2; else if (ERR_CRYPTINIT == gtmcrypt_errno) gtmcrypt_errno = ERR_CRYPTINIT2; gtmcrypt_errno = SET_CRYPTERR_MASK(gtmcrypt_errno); GTMCRYPT_REPORT_ERROR(gtmcrypt_errno, rts_error, SIZEOF(GTMCRYPT_ERRLIT) - 1, GTMCRYPT_ERRLIT); /* BYPASSOK */ } } # ifdef GTM_SOCKET_SSL_SUPPORT /* The below logic is for prefetching the password for TLS identifiers that may have been set in the environment. * But, since SSL support for Socket devices is not yet implemented, this logic need not be enabled as of this * writing. When SSL support for socket devices is implemented, the surrounding #ifdef can be removed. */ if (NULL != getenv("gtmcrypt_config")) { /* Environment is configured for SSL/TLS (and/or encryption). Check if any environment variable of the form * `gtmtls_passwd_*' is set to NULL string. If so, nudge the SSL/TLS library to read password(s) from the * user. */ for (p = envp; *p; p++) { ptr = *p; if (0 == MEMCMP_LIT(ptr, GTMTLS_PASSWD_ENV_PREFIX)) { /* At least one environment variable of $gtmtls_passwd_* is found. */ eq = strchr(ptr, '='); if (0 != strlen(eq + 1)) break; /* Set to non-empty string. No need to initialize the library now. */ /* Set to empty string. */ if (NULL == tls_ctx) { if (SS_NORMAL != (status = gtm_tls_loadlibrary())) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSDLLNOOPEN, 0, ERR_TEXT, 2, LEN_AND_STR(dl_err)); } if (NULL == (tls_ctx = gtm_tls_init(GTM_TLS_API_VERSION, GTMTLS_OP_INTERACTIVE_MODE))) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_TLSINIT, 0, ERR_TEXT, 2, LEN_AND_STR(gtm_tls_get_error())); } } assert(NULL != tls_ctx); assert((MAX_TLSID_LEN * 2) > (int)(eq - ptr)); memcpy(tlsid_env_name, ptr, (int)(eq - ptr)); tlsid_env_name[(int)(eq - ptr)] = '\0'; gtm_tls_prefetch_passwd(tls_ctx, tlsid_env_name); } } } # endif } # endif dm_start(); return 0; }