erlexec.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 1,752 行 · 第 1/3 页
C
1,752 行
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ *//* * This is a C version of the erl.exec Bourne shell script, including * additions required for Windows NT. */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include "sys.h"#include "erl_driver.h"#include <stdlib.h>#include <stdarg.h>#include "erl_misc_utils.h"#ifdef __WIN32__# include "erl_version.h"# include "init_file.h"#endif#define NO 0#define YES 1#ifdef __WIN32__#define INI_FILENAME "erl.ini"#define INI_SECTION "erlang"#define DIRSEP "\\"#define PATHSEP ";"#define NULL_DEVICE "nul"#define BINARY_EXT ".exe"#else#define PATHSEP ":"#define DIRSEP "/"#define NULL_DEVICE "/dev/null"#define BINARY_EXT ""#endif#define QUOTE(s) s/* +M alloc_util allocators */static const char plusM_au_allocs[]= { 'B', /* binary_alloc */ 'D', /* std_alloc */ 'E', /* ets_alloc */ 'H', /* eheap_alloc */ 'L', /* ll_alloc */ 'S', /* sl_alloc */ 'T', /* temp_alloc */ '\0'};/* +M alloc_util allocator specific arguments */static char *plusM_au_alloc_switches[] = { "as", "asbcst", "e", "lmbcs", "mbcgs", "mbsd", "mmbcs", "mmmbc", "mmsbc", "msbclt", "rsbcmt", "rsbcst", "sbct", "smbcs", NULL};/* +M other arguments */static char *plusM_other_switches[] = { "ea", "ummc", "uycs", "im", "is", "it", "Mamcbf", "Mrmcbf", "Mmcs", "Mcci", "Fe", "Ye", "Ym", "Ytp", "Ytt", NULL};/* * Define sleep(seconds) in terms of Sleep() on Windows. */#ifdef __WIN32__#define sleep(seconds) Sleep(seconds*1000)#endif#define SMP_SUFFIX ".smp"#define HYBRID_SUFFIX ".hybrid"/* The length of the longest memory architecture suffix. */#define EMU_TYPE_SUFFIX_LENGTH strlen(HYBRID_SUFFIX)/* * Define flags for different memory architectures. */#define EMU_TYPE_SMP 0x0001#define EMU_TYPE_HYBRID 0x0002void usage(const char *switchname);void start_epmd(char *epmd);void error(char* format, ...);/* * Local functions. */#if !defined(ERTS_HAVE_SMP_EMU) || !defined(ERTS_HAVE_HYBRID_EMU)static void usage_notsup(const char *switchname);#endifstatic void usage_msg(const char *msg);static char **build_args_from_env(char *env_var);static char **build_args_from_string(char *env_var);static void initial_argv_massage(int *argc, char ***argv);static void get_parameters(int argc, char** argv);static void add_arg(char *new_arg);static void add_args(char *first_arg, ...);static void ensure_EargsSz(int sz);static void add_Eargs(char *new_arg);static void *emalloc(size_t size);static void *erealloc(void *p, size_t size);static void efree(void *p);static char* strsave(char* string);static int is_one_of_strings(char *str, char *strs[]);static char *write_str(char *to, char *from);static void get_home(void);#ifdef __WIN32__static void get_start_erl_data(char *);static char* get_value(HKEY key, char* value_name, BOOL mustExit);static char* possibly_quote(char* arg);/* * Functions from win_erlexec.c */int start_win_emulator(char* emu, char** argv, int start_detached);int start_emulator(char* emu, char** argv, int start_detached);#endif/* * Variables. */int nohup = 0;int keep_window = 0;static char **Eargsp = NULL; /* Emulator arguments (to appear first). */static int EargsSz = 0; /* Size of Eargsp */static int EargsCnt = 0; /* Number of emulator arguments. */static char **argsp = NULL; /* Common arguments. */static int argsCnt = 0; /* Number of common arguments */static int argsSz = 0; /* Size of argsp */static char tmpStr[10240]; /* Temporary string buffer. */static int verbose = 0; /* If non-zero, print some extra information. */static int start_detached = 0; /* If non-zero, the emulator should be * started detached (in the background). */static int emu_type = 0; /* If non-zero, start beam.ARCH or beam.ARCH.exe * instead of beam or beam.exe, where ARCH is defined by flags. */#ifdef __WIN32__static char* key_val_name = ERLANG_VERSION; /* Used by the registry * access functions. */static char* boot_script = NULL; /* used by option -start_erl and -boot */static char* config_script = NULL; /* used by option -start_erl and -config */static HANDLE this_module_handle;static int run_werl;#endif/* * Needed parameters to be fetched from the environment (Unix) * or the ini file (Win32). */static char* bindir; /* Location of executables. */static char* rootdir; /* Root location of Erlang installation. */static char* emu; /* Emulator to run. */static char* progname; /* Name of this program. */static char* home; /* Path of user's home directory. *//* * Add the arcitecture suffix to the program name if needed, * except on Windows, where we insert it just before ".EXE". */static char*add_extra_suffixes(char *prog, int type){ char *res; char *p; int len;#ifdef __WIN32__ char *exe_p; int exe = 0;#endif if (!type) { return prog; } len = strlen(prog); /* Worst-case allocation */ p = emalloc(len + EMU_TYPE_SUFFIX_LENGTH + + 1); res = p; p = write_str(p, prog);#ifdef __WIN32__ exe_p = res + len - 4; if (exe_p >= res) { if (exe_p[0] == '.' && (exe_p[1] == 'e' || exe_p[1] == 'E') && (exe_p[2] == 'x' || exe_p[2] == 'X') && (exe_p[3] == 'e' || exe_p[3] == 'E')) { p = exe_p; exe = 1; } }#endif if (type == EMU_TYPE_SMP) { p = write_str(p, SMP_SUFFIX); } else if (type == EMU_TYPE_HYBRID) { p = write_str(p, HYBRID_SUFFIX); }#ifdef __WIN32__ if (exe) { p = write_str(p, ".exe"); }#endif return res;}#ifdef __WIN32____declspec(dllexport) int win_erlexec(int argc, char **argv, HANDLE module, int windowed)#elseint main(int argc, char **argv)#endif{ int haltAfterwards = 0; /* If true, put 's erlang halt' at the end * of the arguments. */ int isdistributed = 0; int no_epmd = 0; int i; char* s; char *epmd_prog = NULL; char *malloc_lib; int process_args = 1; int print_args_exit = 0;#ifdef __WIN32__ this_module_handle = module; run_werl = windowed; /* if we started this erl just to get a detached emulator, * the arguments are already prepared for beam, so we skip * directly to start_emulator */ s = getenv("ERL_CONSOLE_MODE"); if (s != NULL && strcmp(s, "detached")==0) { ensure_EargsSz(argc + 1); memcpy((void *) Eargsp, (void *) argv, argc * sizeof(char *)); Eargsp[argc] = NULL; goto skip_arg_massage; } #endif initial_argv_massage(&argc, &argv); /* Merge with env; expand -args_file */ i = 1;#ifdef __WIN32__ /* Not used? /rickard */ if ((argc > 2) && (strcmp(argv[i], "-regkey") == 0)) { key_val_name = strsave(argv[i+1]); i = 3; }#endif get_parameters(argc, argv); /* * Construct the path of the executable. */ /* We need to do this before the ordinary processing. */ malloc_lib = getenv("ERL_MALLOC_LIB"); while (i < argc) { if (argv[i][0] == '+') { if (argv[i][1] == 'M' && argv[i][2] == 'Y' && argv[i][3] == 'm') { if (argv[i][4] == '\0') { if (++i < argc) malloc_lib = argv[i]; else usage("+MYm"); } else malloc_lib = &argv[i][4]; } } else if (argv[i][0] == '-') { if (strcmp(argv[i], "-smp") == 0) { if (i + 1 >= argc) goto smp; if (strcmp(argv[i+1], "auto") == 0) { i++; smp_auto:#ifdef ERTS_HAVE_SMP_EMU if (erts_no_of_cpus() > 1) emu_type |= EMU_TYPE_SMP; else#endif emu_type &= ~EMU_TYPE_SMP; } else if (strcmp(argv[i+1], "enable") == 0) { i++; smp_enable:#ifdef ERTS_HAVE_SMP_EMU emu_type |= EMU_TYPE_SMP;#else usage_notsup("-smp enable");#endif } else if (strcmp(argv[i+1], "disable") == 0) { i++; smp_disable: emu_type &= ~EMU_TYPE_SMP; } else { smp:#ifdef ERTS_HAVE_SMP_EMU emu_type |= EMU_TYPE_SMP;#else usage_notsup("-smp");#endif } } else if (strcmp(argv[i], "-smpenable") == 0) { goto smp_enable; } else if (strcmp(argv[i], "-smpauto") == 0) { goto smp_auto; } else if (strcmp(argv[i], "-smpdisable") == 0) { goto smp_disable; } else if (strcmp(argv[i], "-hybrid") == 0) {#ifdef ERTS_HAVE_HYBRID_EMU emu_type |= EMU_TYPE_HYBRID;#else usage_notsup("-hybrid");#endif } else if (strcmp(argv[i], "-extra") == 0) { break; } } i++; } if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) usage_msg("Hybrid heap emulator with SMP support selected. The " "combination hybrid heap and SMP support is currently not " "supported."); if (malloc_lib) { if (strcmp(malloc_lib, "libc") != 0) usage("+MYm"); }#if !defined(__WIN32__) emu = add_extra_suffixes(emu, emu_type); sprintf(tmpStr, "%s" DIRSEP "%s" BINARY_EXT, bindir, emu); emu = strsave(tmpStr);#endif add_Eargs(emu); /* Will be argv[0] -- necessary! */ /* * Add the bindir to the path (unless it is there already). */ if ((s = getenv("PATH")) == NULL) { sprintf(tmpStr, "PATH=%s" PATHSEP "%s" DIRSEP "bin", bindir, rootdir); } else if (strstr(s, bindir) == NULL) { sprintf(tmpStr, "PATH=%s" PATHSEP "%s" DIRSEP "bin" PATHSEP "%s", bindir, rootdir, s); } else { sprintf(tmpStr, "PATH=%s", s); } putenv(strsave(tmpStr)); i = 1;#ifdef __WIN32__#define ADD_BOOT_CONFIG \ if (boot_script) \ add_args("-boot", boot_script, NULL); \ if (config_script) \ add_args("-config", config_script, NULL);#else#define ADD_BOOT_CONFIG#endif get_home(); add_args("-home", home, NULL); while (i < argc) { if (!process_args) { /* Copy arguments after '-extra' */ add_arg(argv[i]); i++; } else { switch (argv[i][0]) { case '-': switch (argv[i][1]) {#ifdef __WIN32__ case 'b': if (strcmp(argv[i], "-boot") == 0) { if (boot_script) error("Conflicting -start_erl and -boot options"); if (i+1 >= argc) usage("-boot"); boot_script = strsave(argv[i+1]); i++; } else { add_arg(argv[i]); } break;#endif case 'c': if (strcmp(argv[i], "-compile") == 0) { /* * Note that the shell script erl.exec does an recursive call * on itself here. We'll avoid doing that. */ add_args("-noshell", "-noinput", "-s", "c", "lc_batch", NULL); add_Eargs("-B"); haltAfterwards = 0; }#ifdef __WIN32__ else if (strcmp(argv[i], "-config") == 0){ if (config_script) error("Conflicting -start_erl and -config options"); if (i+1 >= argc) usage("-config"); config_script = strsave(argv[i+1]); i++; }#endif else { add_arg(argv[i]); } break; case 'd': if (strcmp(argv[i], "-detached") != 0) { add_arg(argv[i]); } else { start_detached = 1; add_args("-noshell", "-noinput", NULL); } break; case 'i': if (strcmp(argv[i], "-instr") == 0) { add_Eargs("-Mim"); add_Eargs("true"); } else add_arg(argv[i]); break; case 'e': if (strcmp(argv[i], "-extra") == 0) { process_args = 0; ADD_BOOT_CONFIG; add_arg(argv[i]); } else if (strcmp(argv[i], "-emu_args") == 0) { /* -emu_args */ verbose = 1; } else if (strcmp(argv[i], "-emu_args_exit") == 0) { print_args_exit = 1; } else if (strcmp(argv[i], "-env") == 0) { /* -env VARNAME VARVALUE */ if (i+2 >= argc) usage("-env"); sprintf(tmpStr, "%s=%s", argv[i+1], argv[i+2]); putenv(strsave(tmpStr)); i += 2; } else if (strcmp(argv[i], "-epmd") == 0) { if (i+1 >= argc) usage("-epmd"); epmd_prog = argv[i+1]; ++i; } else { add_arg(argv[i]); } break; case 'k': if (strcmp(argv[i], "-keep_window") == 0) { keep_window = 1; } else add_arg(argv[i]); break; case 'm': /* * Note that the shell script erl.exec does an recursive call * on itself here. We'll avoid doing that. */ if (strcmp(argv[i], "-make") == 0) { add_args("-noshell", "-noinput", "-s", "make", "all", NULL); add_Eargs("-B"); haltAfterwards = 1; i = argc; /* Skip rest of command line */ } else if (strcmp(argv[i], "-man") == 0) {#if defined(__WIN32__) error("-man not supported on Windows");#else argv[i] = "man"; sprintf(tmpStr, "MANPATH=%s/man", rootdir); putenv(strsave(tmpStr)); execvp("man", argv+i); error("Could not execute the 'man' command.");#endif } else add_arg(argv[i]); break; case 'n': if (strcmp(argv[i], "-name") == 0) { /* -name NAME */ if (i+1 >= argc) usage("-name"); /* * Note: Cannot use add_args() here, due to non-defined * evaluation order. */ add_arg(argv[i]); add_arg(argv[i+1]); isdistributed = 1; i++; } else if (strcmp(argv[i], "-noinput") == 0) { add_args("-noshell", "-noinput", NULL); } else if (strcmp(argv[i], "-nohup") == 0) { add_arg("-nohup"); nohup = 1; } else if (strcmp(argv[i], "-no_epmd") == 0) { add_arg("-no_epmd"); no_epmd = 1; } else { add_arg(argv[i]); } break; case 's': /* -sname NAME */ if (strcmp(argv[i], "-sname") == 0) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?