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 + -
显示快捷键?