Eterm os_getenv_1(Process* p, Eterm key) { Eterm str; int len, res; char *key_str, *val; char buf[1024]; size_t val_size = sizeof(buf); len = is_string(key); if (!len) { BIF_ERROR(p, BADARG); } /* Leave at least one byte in buf for value */ key_str = len < sizeof(buf)-2 ? &buf[0] : erts_alloc(ERTS_ALC_T_TMP, len+1); if (intlist_to_buf(key, key_str, len) != len) erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__); key_str[len] = '\0'; if (key_str != &buf[0]) val = &buf[0]; else { val_size -= len + 1; val = &buf[len + 1]; } res = erts_sys_getenv(key_str, val, &val_size); if (res < 0) { no_var: str = am_false; } else { Eterm* hp; if (res > 0) { val = erts_alloc(ERTS_ALC_T_TMP, val_size); while (1) { res = erts_sys_getenv(key_str, val, &val_size); if (res == 0) break; else if (res < 0) goto no_var; else val = erts_realloc(ERTS_ALC_T_TMP, val, val_size); } } if (val_size) hp = HAlloc(p, val_size*2); str = buf_to_intlist(&hp, val, val_size, NIL); } if (key_str != &buf[0]) erts_free(ERTS_ALC_T_TMP, key_str); if (val < &buf[0] || &buf[sizeof(buf)-1] < val) erts_free(ERTS_ALC_T_TMP, val); BIF_RET(str); }
BIF_RETTYPE os_getenv_1(BIF_ALIST_1) { Process* p = BIF_P; Eterm str; Sint len; int res; char *key_str, *val; char buf[STATIC_BUF_SIZE]; size_t val_size = sizeof(buf); key_str = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE, ERTS_ALC_T_TMP,1,0,&len); if (!key_str) { BIF_ERROR(p, BADARG); } if (key_str != &buf[0]) val = &buf[0]; else { /* len includes zero byte */ val_size -= len; val = &buf[len]; } res = erts_sys_getenv(key_str, val, &val_size); if (res < 0) { no_var: str = am_false; } else { if (res > 0) { val = erts_alloc(ERTS_ALC_T_TMP, val_size); while (1) { res = erts_sys_getenv(key_str, val, &val_size); if (res == 0) break; else if (res < 0) goto no_var; else val = erts_realloc(ERTS_ALC_T_TMP, val, val_size); } } str = erts_convert_native_to_filename(p,(byte *)val); } if (key_str != &buf[0]) erts_free(ERTS_ALC_T_TMP, key_str); if (val < &buf[0] || &buf[sizeof(buf)-1] < val) erts_free(ERTS_ALC_T_TMP, val); BIF_RET(str); }
void erl_start(int argc, char **argv) { int i = 1; char* arg=NULL; char* Parg = NULL; int have_break_handler = 1; char envbuf[21]; /* enough for any 64-bit integer */ size_t envbufsz; int ncpu = early_init(&argc, argv); envbufsz = sizeof(envbuf); if (erts_sys_getenv(ERL_MAX_ETS_TABLES_ENV, envbuf, &envbufsz) == 0) user_requested_db_max_tabs = atoi(envbuf); else user_requested_db_max_tabs = 0; envbufsz = sizeof(envbuf); if (erts_sys_getenv("ERL_FULLSWEEP_AFTER", envbuf, &envbufsz) == 0) { Uint16 max_gen_gcs = atoi(envbuf); erts_smp_atomic32_set_nob(&erts_max_gen_gcs, (erts_aint32_t) max_gen_gcs); } #if (defined(__APPLE__) && defined(__MACH__)) || defined(__DARWIN__) /* * The default stack size on MacOS X is too small for pcre. */ erts_sched_thread_suggested_stack_size = 256; #endif #ifdef DEBUG verbose = DEBUG_DEFAULT; #endif erts_error_logger_warnings = am_error; while (i < argc) { if (argv[i][0] != '-') { erts_usage(); } if (strcmp(argv[i], "--") == 0) { /* end of emulator options */ i++; break; } switch (argv[i][1]) { /* * NOTE: -M flags are handled (and removed from argv) by * erts_alloc_init(). * * The -d, -m, -S, -t, and -T flags was removed in * Erlang 5.3/OTP R9C. * * -S, and -T has been reused in Erlang 5.5/OTP R11B. * * -d has been reused in a patch R12B-4. */ case '#' : arg = get_arg(argv[i]+2, argv[i+1], &i); if ((display_items = atoi(arg)) == 0) { erts_fprintf(stderr, "bad display items%s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("using display items %d\n",display_items)); break; case 'f': if (!strncmp(argv[i],"-fn",3)) { arg = get_arg(argv[i]+3, argv[i+1], &i); switch (*arg) { case 'u': erts_set_user_requested_filename_encoding(ERL_FILENAME_UTF8); break; case 'l': erts_set_user_requested_filename_encoding(ERL_FILENAME_LATIN1); break; case 'a': erts_set_user_requested_filename_encoding(ERL_FILENAME_UNKNOWN); default: erts_fprintf(stderr, "bad filename encoding %s, can be (l,u or a)\n", arg); erts_usage(); } break; } else { erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]); erts_usage(); } case 'L': erts_no_line_info = 1; break; case 'v': #ifdef DEBUG if (argv[i][2] == '\0') { verbose |= DEBUG_SYSTEM; } else { char *ch; for (ch = argv[i]+2; *ch != '\0'; ch++) { switch (*ch) { case 's': verbose |= DEBUG_SYSTEM; break; case 'g': verbose |= DEBUG_PRIVATE_GC; break; case 'M': verbose |= DEBUG_MEMORY; break; case 'a': verbose |= DEBUG_ALLOCATION; break; case 't': verbose |= DEBUG_THREADS; break; case 'p': verbose |= DEBUG_PROCESSES; break; case 'm': verbose |= DEBUG_MESSAGES; break; default : erts_fprintf(stderr,"Unknown verbose option: %c\n",*ch); } } } erts_printf("Verbose level: "); if (verbose & DEBUG_SYSTEM) erts_printf("SYSTEM "); if (verbose & DEBUG_PRIVATE_GC) erts_printf("PRIVATE_GC "); if (verbose & DEBUG_MEMORY) erts_printf("PARANOID_MEMORY "); if (verbose & DEBUG_ALLOCATION) erts_printf("ALLOCATION "); if (verbose & DEBUG_THREADS) erts_printf("THREADS "); if (verbose & DEBUG_PROCESSES) erts_printf("PROCESSES "); if (verbose & DEBUG_MESSAGES) erts_printf("MESSAGES "); erts_printf("\n"); #else erts_fprintf(stderr, "warning: -v (only in debug compiled code)\n"); #endif break; case 'V' : { char tmp[256]; tmp[0] = tmp[1] = '\0'; #ifdef DEBUG strcat(tmp, ",DEBUG"); #endif #ifdef ERTS_SMP strcat(tmp, ",SMP"); #endif #ifdef USE_THREADS strcat(tmp, ",ASYNC_THREADS"); #endif #ifdef HIPE strcat(tmp, ",HIPE"); #endif erts_fprintf(stderr, "Erlang "); if (tmp[1]) { erts_fprintf(stderr, "(%s) ", tmp+1); } erts_fprintf(stderr, "(" EMULATOR ") emulator version " ERLANG_VERSION "\n"); erl_exit(0, ""); } break; case 'H': /* undocumented */ fprintf(stderr, "The undocumented +H option has been removed (R10B-6).\n\n"); break; case 'h': { char *sub_param = argv[i]+2; /* set default heap size * * h|ms - min_heap_size * h|mbs - min_bin_vheap_size * */ if (has_prefix("mbs", sub_param)) { arg = get_arg(sub_param+3, argv[i+1], &i); if ((BIN_VH_MIN_SIZE = atoi(arg)) <= 0) { erts_fprintf(stderr, "bad heap size %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("using minimum binary virtual heap size %d\n", BIN_VH_MIN_SIZE)); } else if (has_prefix("ms", sub_param)) { arg = get_arg(sub_param+2, argv[i+1], &i); if ((H_MIN_SIZE = atoi(arg)) <= 0) { erts_fprintf(stderr, "bad heap size %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE)); } else { /* backward compatibility */ arg = get_arg(argv[i]+2, argv[i+1], &i); if ((H_MIN_SIZE = atoi(arg)) <= 0) { erts_fprintf(stderr, "bad heap size %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE)); } break; } case 'd': /* * Never produce crash dumps for internally detected * errors; only produce a core dump. (Generation of * crash dumps is destructive and makes it impossible * to inspect the contents of process heaps in the * core dump.) */ erts_no_crash_dump = 1; break; case 'e': if (sys_strcmp("c", argv[i]+2) == 0) { erts_ets_always_compress = 1; } else { /* set maximum number of ets tables */ arg = get_arg(argv[i]+2, argv[i+1], &i); if (( user_requested_db_max_tabs = atoi(arg) ) < 0) { erts_fprintf(stderr, "bad maximum number of ets tables %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("using maximum number of ets tables %d\n", user_requested_db_max_tabs)); } break; case 'i': /* define name of module for initial function */ init = get_arg(argv[i]+2, argv[i+1], &i); break; case 'b': /* define name of initial function */ boot = get_arg(argv[i]+2, argv[i+1], &i); break; case 'B': if (argv[i][2] == 'i') /* +Bi */ ignore_break = 1; else if (argv[i][2] == 'c') /* +Bc */ replace_intr = 1; else if (argv[i][2] == 'd') /* +Bd */ have_break_handler = 0; else if (argv[i+1][0] == 'i') { /* +B i */ get_arg(argv[i]+2, argv[i+1], &i); ignore_break = 1; } else if (argv[i+1][0] == 'c') { /* +B c */ get_arg(argv[i]+2, argv[i+1], &i); replace_intr = 1; } else if (argv[i+1][0] == 'd') { /* +B d */ get_arg(argv[i]+2, argv[i+1], &i); have_break_handler = 0; } else /* +B */ have_break_handler = 0; break; case 'K': /* If kernel poll support is present, erl_sys_args() will remove the K parameter and value */ get_arg(argv[i]+2, argv[i+1], &i); erts_fprintf(stderr, "kernel-poll not supported; \"K\" parameter ignored\n", arg); break; case 'P': /* set maximum number of processes */ Parg = get_arg(argv[i]+2, argv[i+1], &i); erts_proc.max = atoi(Parg); /* Check of result is delayed until later. This is because +R may be given after +P. */ break; case 'S' : /* Was handled in early_init() just read past it */ (void) get_arg(argv[i]+2, argv[i+1], &i); break; case 's' : { char *estr; int res; char *sub_param = argv[i]+2; if (has_prefix("bt", sub_param)) { arg = get_arg(sub_param+2, argv[i+1], &i); res = erts_init_scheduler_bind_type_string(arg); if (res != ERTS_INIT_SCHED_BIND_TYPE_SUCCESS) { switch (res) { case ERTS_INIT_SCHED_BIND_TYPE_NOT_SUPPORTED: estr = "not supported"; break; case ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_CPU_TOPOLOGY: estr = "no cpu topology available"; break; case ERTS_INIT_SCHED_BIND_TYPE_ERROR_NO_BAD_TYPE: estr = "invalid type"; break; default: estr = "undefined error"; break; } erts_fprintf(stderr, "setting scheduler bind type '%s' failed: %s\n", arg, estr); erts_usage(); } } else if (has_prefix("bwt", sub_param)) { arg = get_arg(sub_param+3, argv[i+1], &i); if (erts_sched_set_busy_wait_threshold(arg) != 0) { erts_fprintf(stderr, "bad scheduler busy wait threshold: %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("scheduler wakup threshold: %s\n", arg)); } else if (has_prefix("cl", sub_param)) { arg = get_arg(sub_param+2, argv[i+1], &i); if (sys_strcmp("true", arg) == 0) erts_sched_compact_load = 1; else if (sys_strcmp("false", arg) == 0) erts_sched_compact_load = 0; else { erts_fprintf(stderr, "bad scheduler compact load value '%s'\n", arg); erts_usage(); } } else if (has_prefix("ct", sub_param)) { arg = get_arg(sub_param+2, argv[i+1], &i); res = erts_init_cpu_topology_string(arg); if (res != ERTS_INIT_CPU_TOPOLOGY_OK) { switch (res) { case ERTS_INIT_CPU_TOPOLOGY_INVALID_ID: estr = "invalid identifier"; break; case ERTS_INIT_CPU_TOPOLOGY_INVALID_ID_RANGE: estr = "invalid identifier range"; break; case ERTS_INIT_CPU_TOPOLOGY_INVALID_HIERARCHY: estr = "invalid hierarchy"; break; case ERTS_INIT_CPU_TOPOLOGY_INVALID_ID_TYPE: estr = "invalid identifier type"; break; case ERTS_INIT_CPU_TOPOLOGY_INVALID_NODES: estr = "invalid nodes declaration"; break; case ERTS_INIT_CPU_TOPOLOGY_MISSING_LID: estr = "missing logical identifier"; break; case ERTS_INIT_CPU_TOPOLOGY_NOT_UNIQUE_LIDS: estr = "not unique logical identifiers"; break; case ERTS_INIT_CPU_TOPOLOGY_NOT_UNIQUE_ENTITIES: estr = "not unique entities"; break; case ERTS_INIT_CPU_TOPOLOGY_MISSING: estr = "missing cpu topology"; break; default: estr = "undefined error"; break; } erts_fprintf(stderr, "bad cpu topology '%s': %s\n", arg, estr); erts_usage(); } } else if (sys_strcmp("nsp", sub_param) == 0) erts_use_sender_punish = 0; else if (sys_strcmp("wt", sub_param) == 0) { arg = get_arg(sub_param+2, argv[i+1], &i); if (erts_sched_set_wakeup_other_thresold(arg) != 0) { erts_fprintf(stderr, "scheduler wakeup threshold: %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("scheduler wakeup threshold: %s\n", arg)); } else if (sys_strcmp("ws", sub_param) == 0) { arg = get_arg(sub_param+2, argv[i+1], &i); if (erts_sched_set_wakeup_other_type(arg) != 0) { erts_fprintf(stderr, "scheduler wakeup strategy: %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("scheduler wakeup threshold: %s\n", arg)); } else if (has_prefix("ss", sub_param)) { /* suggested stack size (Kilo Words) for scheduler threads */ arg = get_arg(sub_param+2, argv[i+1], &i); erts_sched_thread_suggested_stack_size = atoi(arg); if ((erts_sched_thread_suggested_stack_size < ERTS_SCHED_THREAD_MIN_STACK_SIZE) || (erts_sched_thread_suggested_stack_size > ERTS_SCHED_THREAD_MAX_STACK_SIZE)) { erts_fprintf(stderr, "bad stack size for scheduler threads %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("suggested scheduler thread stack size %d kilo words\n", erts_sched_thread_suggested_stack_size)); } else { erts_fprintf(stderr, "bad scheduling option %s\n", argv[i]); erts_usage(); } break; } case 't': /* set atom table size */ arg = get_arg(argv[i]+2, argv[i+1], &i); errno = 0; erts_atom_table_size = strtol(arg, NULL, 10); if (errno != 0 || erts_atom_table_size < MIN_ATOM_TABLE_SIZE || erts_atom_table_size > MAX_ATOM_TABLE_SIZE) { erts_fprintf(stderr, "bad atom table size %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("setting maximum number of atoms to %d\n", erts_atom_table_size)); break; case 'T' : arg = get_arg(argv[i]+2, argv[i+1], &i); errno = 0; erts_modified_timing_level = atoi(arg); if ((erts_modified_timing_level == 0 && errno != 0) || erts_modified_timing_level < 0 || erts_modified_timing_level >= ERTS_MODIFIED_TIMING_LEVELS) { erts_fprintf(stderr, "bad modified timing level %s\n", arg); erts_usage(); } else { VERBOSE(DEBUG_SYSTEM, ("using modified timing level %d\n", erts_modified_timing_level)); } break; case 'R': { /* set compatibility release */ arg = get_arg(argv[i]+2, argv[i+1], &i); erts_compat_rel = atoi(arg); if (erts_compat_rel < ERTS_MIN_COMPAT_REL || erts_compat_rel > this_rel_num()) { erts_fprintf(stderr, "bad compatibility release number %s\n", arg); erts_usage(); } ASSERT(ERTS_MIN_COMPAT_REL >= 7); switch (erts_compat_rel) { case 7: case 8: case 9: erts_use_r9_pids_ports = 1; default: break; } break; } case 'A': /* Was handled in early init just read past it */ (void) get_arg(argv[i]+2, argv[i+1], &i); break; case 'a': /* suggested stack size (Kilo Words) for threads in thread pool */ arg = get_arg(argv[i]+2, argv[i+1], &i); erts_async_thread_suggested_stack_size = atoi(arg); if ((erts_async_thread_suggested_stack_size < ERTS_ASYNC_THREAD_MIN_STACK_SIZE) || (erts_async_thread_suggested_stack_size > ERTS_ASYNC_THREAD_MAX_STACK_SIZE)) { erts_fprintf(stderr, "bad stack size for async threads %s\n", arg); erts_usage(); } VERBOSE(DEBUG_SYSTEM, ("suggested async-thread stack size %d kilo words\n", erts_async_thread_suggested_stack_size)); break; case 'r': { char *sub_param = argv[i]+2; if (has_prefix("g", sub_param)) { get_arg(sub_param+1, argv[i+1], &i); /* already handled */ } else { erts_ets_realloc_always_moves = 1; } break; } case 'n': /* XXX obsolete */ break; case 'c': if (argv[i][2] == 0) { /* -c: documented option */ erts_disable_tolerant_timeofday = 1; } #ifdef ERTS_OPCODE_COUNTER_SUPPORT else if (argv[i][2] == 'i') { /* -ci: undcoumented option*/ count_instructions = 1; } #endif break; case 'W': arg = get_arg(argv[i]+2, argv[i+1], &i); switch (arg[0]) { case 'i': erts_error_logger_warnings = am_info; break; case 'w': erts_error_logger_warnings = am_warning; break; case 'e': /* The default */ erts_error_logger_warnings = am_error; default: erts_fprintf(stderr, "unrecognized warning_map option %s\n", arg); erts_usage(); } break; case 'z': { char *sub_param = argv[i]+2; int new_limit; if (has_prefix("dbbl", sub_param)) { arg = get_arg(sub_param+4, argv[i+1], &i); new_limit = atoi(arg); if (new_limit < 1 || INT_MAX/1024 < new_limit) { erts_fprintf(stderr, "Invalid dbbl limit: %d\n", new_limit); erts_usage(); } else { erts_dist_buf_busy_limit = new_limit*1024; } } else { erts_fprintf(stderr, "bad -z option %s\n", argv[i]); erts_usage(); } break; } default: erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]); erts_usage(); } i++; } /* Delayed check of +P flag */ if (erts_proc.max < ERTS_MIN_PROCESSES || erts_proc.max > ERTS_MAX_PROCESSES || (erts_use_r9_pids_ports && erts_proc.max > ERTS_MAX_R9_PROCESSES)) { erts_fprintf(stderr, "bad number of processes %s\n", Parg); erts_usage(); } /* Restart will not reinstall the break handler */ #ifdef __WIN32__ if (ignore_break) erts_set_ignore_break(); else if (replace_intr) erts_replace_intr(); else init_break_handler(); #else if (ignore_break) erts_set_ignore_break(); else if (have_break_handler) init_break_handler(); if (replace_intr) erts_replace_intr(); #endif boot_argc = argc - i; /* Number of arguments to init */ boot_argv = &argv[i]; erl_init(ncpu); load_preloaded(); erts_end_staging_code_ix(); erts_commit_staging_code_ix(); erts_initialized = 1; erl_first_process_otp("otp_ring0", NULL, 0, boot_argc, boot_argv); #ifdef ERTS_SMP erts_start_schedulers(); /* Let system specific code decide what to do with the main thread... */ erts_sys_main_thread(); /* May or may not return! */ #else erts_thr_set_main_status(1, 1); #if ERTS_USE_ASYNC_READY_Q erts_get_scheduler_data()->aux_work_data.async_ready.queue = erts_get_async_ready_queue(1); #endif set_main_stack_size(); process_main(); #endif }
int erts_sys_getenv_raw(char *key, char *value, size_t *size) { return erts_sys_getenv(key, value, size); }