erl.exec.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 1,007 行 · 第 1/2 页

C
1,007
字号
/* ``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$ */#include "ose.h"#include "dbgprintf.h"#include "malloc.h"#include "errno.h"#include "sys/stat.h"#include "unistd.h"#include "shell.h"#include "efs.h"#include "efs_err.h"#include "fm.sig"#include "heapapi.h"#include "outfmt.h"#include "stdlib.h"#include "stdio.h"#include "string.h"#ifndef MAXPATHLEN#define MAXPATHLEN 2048#endif#define NO 0#define YES 1#define PATHSEP ":"#define DIRSEP "/"#define NULL_DEVICE "/dev/null"#define BINARY_EXT ""#define QUOTE(s) svoid usage(const char *switchname);void ose_error(char* str, int n);/* * Local functions. */static void mergeargs(int *argc, char ***argv, char **addargs);static char **build_args_from_env(void);static void get_parameters(int argc, char** argv);static void add_arg(char *new_arg);static void add_Eargs(char *new_arg);static int dirq(const char *dirpath);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 void get_home(void);static int start_erl_ose(void);static int ose_execvp(char *cmd, char **args);static void print_args(char **args);static void set_oldshell(int *argc, char ***argv);static void reset_drivers(void);void start_epmd(char *epmd);PROCESS get_erl_bid(void);/* * Variables. */int nohup = 0;int keep_window = 0;static char* Eargsp[100];	/* Emulator arguments (to appear first). */static int EargsCnt = 0;	/* Number of emulator arguments. */static char *argsp[100];	/* Common arguments. */static int argsCnt = 0;		/* Number of common arguments */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). *//* these variables are allocated memory for by get_env() during startup, the erts   process will free them before terminating */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. */static char **erl_argv;static int erl_argc = 0;PROCESS erl_block;PROCESS erlang_starter_;extern PROCESS erl_tmp_;extern int config_dns(void);extern int erl_main(int, char **);extern int erl_set_memory_block(int, int, int, int, int);extern int erl_memory_show(void);PROCESS get_erl_bid() {  return get_bid(erl_tmp_);}static int restart = 0;OS_PROCESS(erts) {  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;  int process_args = 1;  int argc = 0;  char **argv;  start_detached = 0;  if(!restart) {    /* allocate max heap memory that erts needs */    if((s = get_env(erl_block, "OSE_EXT_HEAP_SIZE")) != NULL) {      char* addr_str;      if((addr_str = get_env(erl_block, "OSE_EXT_HEAP_ADDR")) != NULL) {	size_t ext_heap_size;	unsigned int ext_heap_addr;	ext_heap_size = (size_t)atol(s);	ext_heap_addr = (unsigned int)atol(addr_str);	erl_dbg_fprintf(stdout, "Will extend heap %u bytes from address %X\n", 			ext_heap_size, ext_heap_addr);	heap_extend_heap((void*)ext_heap_addr, ext_heap_size);	free_buf((union SIGNAL **) &addr_str);	free_buf((union SIGNAL **) &s);      } else {	erl_dbg_fprintf(stderr, "Warning: Variable OSE_EXT_HEAP_ADDR not defined!\n");	free_buf((union SIGNAL **) &s);      }    } else {      if((s = get_env(erl_block, "OSE_EXT_HEAP_ADDR")) != NULL) {	erl_dbg_fprintf(stderr, "Warning: Variable OSE_EXT_HEAP_SIZE not defined!\n");	free_buf((union SIGNAL **) &s);      }    }  } else {    erl_dbg_fprintf(stdout, "erts restarting...\n");    reset_drivers();  }    /* set restart indication so that extend heap is never called twice */  restart = 1;  /* assign memory block for erlang */  if((s = get_env(erl_block, "ERL_HEAP_SIZE")) != NULL) {    char* addr_str;    if((addr_str = get_env(erl_block, "ERL_HEAP_ADDR")) != NULL) {      int erl_heap_size;      int erl_heap_addr;      erl_heap_size = atoi(s);      erl_heap_addr = atoi(addr_str);      erl_dbg_fprintf(stdout, "Will reserve %d bytes from address %X for Erlang\n", 		      erl_heap_size, erl_heap_addr);      erl_set_memory_block((int)erl_heap_size, erl_heap_addr, 1, 1, 0);      free_buf((union SIGNAL **) &addr_str);      free_buf((union SIGNAL **) &s);    } else {      free_buf((union SIGNAL **) &s);      erl_dbg_fprintf(stderr, "Error: ERL_HEAP_ADDR not defined!\n");      kill_proc(current_process());    }  } else {    erl_dbg_fprintf(stderr, "Warning: ERL_HEAP_SIZE and/or ERL_HEAP_ADDR not defined! ");    erl_dbg_fprintf(stderr, "ELIB_MALLOC must not be used!\n");  }  /* copy the argv structure from command shell process */  argv = (char **)malloc((erl_argc+1) * sizeof(char*));  while(argc < erl_argc) {    argv[argc] = (char *)malloc(strlen(erl_argv[argc])+1);    strcpy(argv[argc], erl_argv[argc]);    argc++;  }  argv[argc] = NULL;  EargsCnt = 0;  argsCnt = 0;  set_oldshell(&argc, &argv);    mergeargs(&argc, &argv, build_args_from_env());  get_parameters(argc, argv);  add_Eargs(emu);		/* Will be argv[0] -- necessary! */  /* add the bindir to the path (unless it is there already) */  sprintf(tmpStr, "%s" DIRSEP "bin", rootdir);  bindir = strsave(tmpStr);  if((s = get_env(erl_block, "PATH")) != NULL) {    if(strstr(s, bindir) == NULL)      sprintf(tmpStr, "%s" PATHSEP "%s", bindir, s);    else       sprintf(tmpStr, "%s", s);    free_buf((union SIGNAL **) &s);  }  set_env(erl_block, "PATH", strsave(tmpStr));  get_home();  add_arg("-home");  add_arg(home);  i = 0;  while (i < argc) {    if (process_args) {      switch (argv[i][0]) {      case '-':	switch (argv[i][1]) {	  	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_arg("-noshell");	    add_arg("-noinput");	    add_arg("-s");	    add_arg("c");	    add_arg("lc_batch");	    add_Eargs("-B");	    haltAfterwards = 0;	  }	  else {	    add_arg(argv[i]);	  }	  break;	  	case 'd':	  if (strcmp(argv[i], "-detached") != 0) {	    add_arg(argv[i]);	  } else {	    start_detached = 1;	    add_arg("-noshell");	    add_arg("-noinput");	  }	  break;	  	case 'i':	  if (strcmp(argv[i], "-instr") == 0)	    ;	/* already handled above */	  else	    add_arg(argv[i]);	  break;	  	case 'e':	  if (strcmp(argv[i], "-extra") == 0) {	    process_args = 0;	    add_arg(argv[i]);	  } else if (strcmp(argv[i], "-emu_args") == 0) { /* -emu_args */	    verbose = 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_arg("-noshell");	    add_arg("-noinput");	    add_arg("-s"); 	    add_arg("make"); 	    add_arg("all");	    add_Eargs("-B");	    haltAfterwards = 1;	    i = argc; /* Skip rest of command line */	  } else if (strcmp(argv[i], "-man") == 0) {    	    argv[i] = "man";	    sprintf(tmpStr, "%s/man", rootdir);	    set_env(erl_block, "MANPATH", strsave(tmpStr));	    if(ose_execvp("man", argv+i) < 0)	      ose_error("Could not execute the 'man' command.", 0);      	    else	      return;	      	  } 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], "-noshell") == 0) {	    add_arg("-noshell");	    add_arg("-noinp_shell");	    start_detached = 1;	  } else if (strcmp(argv[i], "-noinput") == 0) {	    add_arg("-noshell");	    add_arg("-noinput");	    start_detached = 1;	  } 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) {	    if (i+1 >= argc)	      usage("-sname");	    add_arg(argv[i]);	    add_arg(argv[i+1]);	    isdistributed = 1;	    i++;	  }	      	  else	    add_arg(argv[i]);	  	  break;	  	case 'v':	/* -version */	  if (strcmp(argv[i], "-version") == 0)	    add_Eargs("-V");	  else	    add_arg(argv[i]);	  break;	  	case 'x':	  if (argv[i][2] != '\0') {	    add_arg(argv[i]);	  } else {	    	    sprintf(tmpStr, "%s/lib/xerl", rootdir);	    if (dirq(tmpStr)) {	      sprintf(tmpStr, "%s/lib/pxw", rootdir);	      if (dirq(tmpStr)) {		add_arg("-x");		add_arg("-noshell");		break;	      }	    }	    ose_error("You need the 'xerl' and 'pxw' bundles to run 'erl -x'", 0);	  }	  break;	  	default:	  add_arg(argv[i]);	  break;	} /* switch(argv[i][1] */	break;	      case '+':	switch (argv[i][1]) {	case 'i':	case 'b':	case 's':	case 'h':	case '#':	case 'P':	  {	    char xx[3];	    xx[0] = '-';	    xx[1] = argv[i][1];	    xx[2] = '\0';	    if (i+1 >= argc) {	      xx[0] = '+';	      usage(xx);	    }	    add_Eargs(xx);	    add_Eargs(argv[i+1]);	    i++;	    break;	  }	default:	  argv[i][0] = '-'; /* Change +option to -option. */	  add_Eargs(argv[i]);	}	break;	      default:	if(strcmp(argv[i], "start_erl") != 0)	  add_arg(argv[i]);      } /* switch(argv[i][0] */      i++;    } else {      add_arg(argv[i]);      i++;    }  }	        /* Doesn't conflict with -extra, since -make skips all the rest of     the arguments. */  if (haltAfterwards) {    add_arg("-s");    add_arg("erlang");    add_arg("halt");  }    /* start_epmd */  if (isdistributed && !no_epmd)    start_epmd(epmd_prog);    add_Eargs("--");  add_Eargs("-root");  add_Eargs(rootdir);  add_Eargs("-progname");  add_Eargs(progname);  add_Eargs("--");  for (i = 0; i < argsCnt; i++)    Eargsp[EargsCnt++] = argsp[i];  Eargsp[EargsCnt] = NULL;    if (verbose) {    printf("Executing: %s", emu);    for (i = 1; i < EargsCnt; i++)      printf(" %s", Eargsp[i]);    printf("\n\n");  }  start_erl_ose();}static void print_args(char **args) {  int i=0;  while(args[i] != NULL)    printf("%s ", args[i++]);  printf("\n");  fflush(stdout);}void testva(char* format, ...) {  char buf[100];  va_list va;  va_start(va, format);  vsprintf(buf,format,va);  printf("%s", buf);}#ifndef HAVE_GETHRTIME#define HAVE_GETHRTIME#endifstatic int start_erl_ose(void) {  char *start_mode;  /* signal fsem to sync with shell cmd process (so that shell command      function may return if erts is started detached */   signal_fsem(erlang_starter_);  /* use block variable to indicate for sys which mode we're in */  if(!start_detached) {    start_mode = strsave("shell");    set_env(erl_block, "ERL_START_MODE", start_mode);    /* also attach to shell command process if erts is in interactive mode */    attach(NULL, erlang_starter_);  } else {    start_mode = strsave("noshell");    set_env(erl_block, "ERL_START_MODE", start_mode);  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?