diff options
Diffstat (limited to 'erts/etc/common')
-rw-r--r-- | erts/etc/common/Makefile | 2 | ||||
-rw-r--r-- | erts/etc/common/Makefile.in | 96 | ||||
-rw-r--r-- | erts/etc/common/ct_run.c | 66 | ||||
-rw-r--r-- | erts/etc/common/dialyzer.c | 65 | ||||
-rw-r--r-- | erts/etc/common/erlc.c | 63 | ||||
-rw-r--r-- | erts/etc/common/erlexec.c | 195 | ||||
-rw-r--r-- | erts/etc/common/escript.c | 131 | ||||
-rw-r--r-- | erts/etc/common/heart.c | 66 | ||||
-rw-r--r-- | erts/etc/common/inet_gethost.c | 6 | ||||
-rw-r--r-- | erts/etc/common/run_erl_common.c | 696 | ||||
-rw-r--r-- | erts/etc/common/run_erl_common.h | 97 | ||||
-rw-r--r-- | erts/etc/common/run_erl_vsn.h | 30 | ||||
-rw-r--r-- | erts/etc/common/safe_string.c | 123 | ||||
-rw-r--r-- | erts/etc/common/safe_string.h | 65 | ||||
-rw-r--r-- | erts/etc/common/to_erl_common.c | 717 | ||||
-rw-r--r-- | erts/etc/common/to_erl_common.h | 29 | ||||
-rw-r--r-- | erts/etc/common/typer.c | 64 |
17 files changed, 451 insertions, 2060 deletions
diff --git a/erts/etc/common/Makefile b/erts/etc/common/Makefile index bbf51d0efd..bad1d3ddb0 100644 --- a/erts/etc/common/Makefile +++ b/erts/etc/common/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# Copyright Ericsson AB 1997-2016. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in index 8e55fa78c9..5b1b9119ce 100644 --- a/erts/etc/common/Makefile.in +++ b/erts/etc/common/Makefile.in @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1996-2014. All Rights Reserved. +# Copyright Ericsson AB 1996-2017. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,10 +21,6 @@ include $(ERL_TOP)/make/output.mk include $(ERL_TOP)/make/target.mk -ifeq ($(findstring ose,$(TARGET)),ose) -include $(ERL_TOP)/make/$(TARGET)/ose_lm.mk -endif - ERTS_LIB_TYPEMARKER=.$(TYPE) USING_MINGW=@MIXED_CYGWIN_MINGW@ @@ -61,7 +57,7 @@ ERTS_INCL = -I$(ERL_TOP)/erts/include \ CC = @CC@ WFLAGS = @WFLAGS@ CFLAGS = @CFLAGS@ @DEFS@ $(TYPE_FLAGS) @WFLAGS@ -I$(SYSDIR) -I$(EMUDIR) \ - $(ERTS_INCL) -DOTP_SYSTEM_VERSION=\"$(SYSTEM_VSN)\" + -I$(COMSYSDIR) $(ERTS_INCL) -DOTP_SYSTEM_VERSION=\"$(SYSTEM_VSN)\" LD = @LD@ LIBS = @LIBS@ LDFLAGS = @LDFLAGS@ @@ -74,29 +70,27 @@ endif ifeq ($(TARGET),win32) ifeq ($(TYPE),debug) CFLAGS = $(subst -O2,-g,@CFLAGS@ @DEFS@ $(TYPE_FLAGS) @WFLAGS@ -I$(SYSDIR) \ - -I$(EMUDIR) $(ERTS_INCL) -DOTP_SYSTEM_VERSION=\"$(SYSTEM_VSN)\") + -I$(EMUDIR) -I$(COMSYSDIR) $(ERTS_INCL) \ + -DOTP_SYSTEM_VERSION=\"$(SYSTEM_VSN)\") LDFLAGS += -g endif endif + BINDIR = $(ERL_TOP)/bin/$(TARGET) OBJDIR = $(ERL_TOP)/erts/obj$(TYPEMARKER)/$(TARGET) EMUDIR = $(ERL_TOP)/erts/emulator/beam +COMSYSDIR = $(ERL_TOP)/erts/emulator/sys/common EMUOSDIR = $(ERL_TOP)/erts/emulator/@ERLANG_OSTYPE@ SYSDIR = $(ERL_TOP)/erts/emulator/sys/@ERLANG_OSTYPE@ DRVDIR = $(ERL_TOP)/erts/emulator/drivers/@ERLANG_OSTYPE@ UXETC = ../unix -OSEETC = ../ose WINETC = ../win32 ifeq ($(TARGET), win32) ETC = $(WINETC) else -ifeq ($(findstring ose,$(TARGET)),ose) -ETC = $(OSEETC) -else ETC = $(UXETC) endif -endif ifeq ($(TARGET), win32) ERLEXEC = erlexec.dll @@ -180,25 +174,6 @@ PORT_ENTRY_POINT=erl_port_entry ENTRY_LDFLAGS=-entry:$(PORT_ENTRY_POINT) else -ifeq ($(findstring ose,$(TARGET)),ose) -ENTRY_LDFLAGS= -ENTRY_OBJ= -ERLSRV_OBJECTS= -MC_OUTPUTS= -INET_GETHOST = -INSTALL_EMBEDDED_PROGS = $(BINDIR)/run_erl_lm -INSTALL_EMBEDDED_DATA = -INSTALL_TOP = Install -INSTALL_TOP_BIN = -INSTALL_MISC = -INSTALL_SRC = -ERLEXECDIR = . -INSTALL_LIBS = -INSTALL_OBJS = -INSTALL_INCLUDES = -TEXTFILES = Install erl.src -INSTALL_PROGS = $(INSTALL_EMBEDDED_PROGS) -else # UNIX (!win32 && !ose) ENTRY_LDFLAGS= ENTRY_OBJ= ERLSRV_OBJECTS= @@ -223,7 +198,6 @@ INSTALL_PROGS = \ $(BINDIR)/$(ERLEXEC) \ $(INSTALL_EMBEDDED_PROGS) endif -endif .PHONY: etc etc: $(ENTRY_OBJ) $(INSTALL_PROGS) $(INSTALL_LIBS) $(TEXTFILES) $(INSTALL_TOP_BIN) @@ -267,11 +241,11 @@ endif rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/reclaim.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/run_erl.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/to_erl.o + rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/typer.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/dyn_erl.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/safe_string.o - rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/run_erl_common.o - rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/to_erl_common.o - rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/typer.o + rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/run_erl.o + rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/to_erl.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/ct_run.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/vxcall.o rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/erl.o @@ -390,7 +364,7 @@ Install.ini: ../$(TARGET)/Install.src ../../vsn.mk $(TARGET)/Makefile else -RC_GENERATED = +RC_GENERATED = $(ERL_TOP)/erts/$(TARGET)/config.h endif #--------------------------------------------------------- # End of windows specific targets. @@ -423,28 +397,24 @@ $(BINDIR)/inet_gethost@EXEEXT@: $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(ERTS_LIB $(ld_verbose)$(PURIFY) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(LIBS) $(ERTS_INTERNAL_LIBS) # run_erl -$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(OBJDIR)/run_erl_common.o - $(V_LD) $(LDFLAGS) -o $@ $^ $(LIBS) -$(OBJDIR)/run_erl.o: $(ETC)/run_erl.c ../common/run_erl_common.h $(RC_GENERATED) - $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(ETC)/run_erl.c -$(OBJDIR)/run_erl_common.o: ../common/run_erl_common.c ../common/run_erl_common.h $(RC_GENERATED) - $(V_CC) $(CFLAGS) -o $@ -c $< +$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o + $(V_LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(LIBS) +$(OBJDIR)/run_erl.o: $(ETC)/run_erl.c $(RC_GENERATED) + $(V_CC) $(CFLAGS) -o $@ -c $(ETC)/run_erl.c # to_erl -$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o $(OBJDIR)/to_erl_common.o - $(V_LD) $(LDFLAGS) -o $@ $^ -$(OBJDIR)/to_erl.o: $(ETC)/to_erl.c ../common/safe_string.h $(RC_GENERATED) - $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(ETC)/to_erl.c -$(OBJDIR)/to_erl_common.o: ../common/to_erl_common.c ../common/to_erl_common.h $(RC_GENERATED) - $(V_CC) $(CFLAGS) -o $@ -c $< +$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o + $(V_LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o +$(OBJDIR)/to_erl.o: $(ETC)/to_erl.c $(RC_GENERATED) + $(V_CC) $(CFLAGS) -o $@ -c $(ETC)/to_erl.c # dyn_erl $(BINDIR)/dyn_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o $(V_LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o $(OBJDIR)/dyn_erl.o: $(UXETC)/dyn_erl.c $(RC_GENERATED) $(V_CC) $(CFLAGS) -o $@ -c $(UXETC)/dyn_erl.c -$(OBJDIR)/safe_string.o: ../common/safe_string.c $(RC_GENERATED) - $(V_CC) $(CFLAGS) -o $@ -c ../common/safe_string.c +$(OBJDIR)/safe_string.o: $(ETC)/safe_string.c $(RC_GENERATED) + $(V_CC) $(CFLAGS) -o $@ -c $(ETC)/safe_string.c ifneq ($(TARGET),win32) $(BINDIR)/$(ERLEXEC): $(OBJDIR)/$(ERLEXEC).o $(ERTS_LIB) @@ -499,30 +469,6 @@ erl.src: $(UXETC)/erl.src.src ../../vsn.mk $(TARGET)/Makefile -e 's;%VSN%;$(VSN);' \ $(UXETC)/erl.src.src > erl.src -#--------------------------------------------------------- -# OSE specific targets -#--------------------------------------------------------- -ifeq ($(findstring ose,$(TARGET)),ose) -$(OBJDIR)/ose_confd.o: $(OSE_CONFD) - $(V_CC) $(CFLAGS) -o $@ -c $< -$(OBJDIR)/crt0_lm.o: $(CRT0_LM) - $(V_CC) $(CFLAGS) -o $@ -c $< -OSE_LM_OBJS += $(OBJDIR)/ose_confd.o $(OBJDIR)/crt0_lm.o - -$(BINDIR)/run_erl_lm: $(OBJDIR)/run_erl_main.o $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(OBJDIR)/run_erl_common.o $(OBJDIR)/to_erl_common.o $(OSE_LM_OBJS) - $(call build-ose-load-module, $@, $^, $(LIBS), $(RUN_ERL_LMCONF)) - - -$(OBJDIR)/run_erl_main.o: $(OSEETC)/run_erl_main.c $(OSEETC)/run_erl.h ../common/to_erl_common.h $(RC_GENERATED) - $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(OSEETC)/run_erl_main.c - -endif - -#--------------------------------------------------------- -# End of ose specific targets. -#--------------------------------------------------------- - - # ---------------------------------------------------- # Release Target # ---------------------------------------------------- @@ -537,11 +483,9 @@ endif $(INSTALL_DIR) "$(RELEASE_PATH)/erts-$(VSN)/bin" ifneq ($(TARGET), win32) ifneq ($(findstring vxworks,$(TARGET)), vxworks) -ifneq ($(findstring ose,$(TARGET)), ose) $(INSTALL_SCRIPT) erl.src "$(RELEASE_PATH)/erts-$(VSN)/bin" endif endif -endif ifneq ($(INSTALL_PROGS),) $(INSTALL_PROGRAM) $(INSTALL_PROGS) "$(RELEASE_PATH)/erts-$(VSN)/bin" endif diff --git a/erts/etc/common/ct_run.c b/erts/etc/common/ct_run.c index 548514ee6c..6639c83778 100644 --- a/erts/etc/common/ct_run.c +++ b/erts/etc/common/ct_run.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2010-2013. All Rights Reserved. + * Copyright Ericsson AB 2010-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,13 +81,17 @@ static int eargc; /* Number of arguments in eargv. */ */ static void error(char* format, ...); -static char* emalloc(size_t size); +static void* emalloc(size_t size); +#ifdef HAVE_COPYING_PUTENV +static void efree(void *p); +#endif static char* strsave(char* string); static void push_words(char* src); static int run_erlang(char* name, char** argv); static char* get_default_emulator(char* progname); #ifdef __WIN32__ static char* possibly_quote(char* arg); +static void* erealloc(void *p, size_t size); #endif /* @@ -118,6 +122,30 @@ char *strerror(int errnum) } #endif /* !HAVE_STRERROR */ + +static void +set_env(char *key, char *value) +{ +#ifdef __WIN32__ + WCHAR wkey[MAXPATHLEN]; + WCHAR wvalue[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, key, -1, wkey, MAXPATHLEN); + MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, MAXPATHLEN); + if (!SetEnvironmentVariableW(wkey, wvalue)) + error("SetEnvironmentVariable(\"%s\", \"%s\") failed!", key, value); +#else + size_t size = strlen(key) + 1 + strlen(value) + 1; + char *str = emalloc(size); + sprintf(str, "%s=%s", key, value); + if (putenv(str) != 0) + error("putenv(\"%s\") failed!", str); +#ifdef HAVE_COPYING_PUTENV + efree(str); +#endif +#endif +} + + #ifdef __WIN32__ int wmain(int argc, wchar_t **wcargv) { @@ -141,10 +169,10 @@ int main(int argc, char** argv) int i; int len; /* Convert argv to utf8 */ - argv = malloc((argc+1) * sizeof(char*)); + argv = emalloc((argc+1) * sizeof(char*)); for (i=0; i<argc; i++) { len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); - argv[i] = malloc(len*sizeof(char)); + argv[i] = emalloc(len*sizeof(char)); WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); } argv[argc] = NULL; @@ -154,6 +182,11 @@ int main(int argc, char** argv) emulator = get_default_emulator(argv[0]); /* + * Add scriptname to env + */ + set_env("ESCRIPT_NAME", argv[0]); + + /* * Allocate the argv vector to be used for arguments to Erlang. * Arrange for starting to pushing information in the middle of * the array, to allow easy addition of commands in the beginning. @@ -334,7 +367,7 @@ wchar_t *make_commandline(char **argv) buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); + buff = (wchar_t *) erealloc(buff,siz*sizeof(wchar_t)); } p = buff; num=0; @@ -437,15 +470,34 @@ error(char* format, ...) exit(1); } -static char* +static void* emalloc(size_t size) { - char *p = malloc(size); + void *p = malloc(size); if (p == NULL) error("Insufficient memory"); return p; } +#ifdef __WIN32__ +static void * +erealloc(void *p, size_t size) +{ + void *res = realloc(p, size); + if (res == NULL) + error("Insufficient memory"); + return res; +} +#endif + +#ifdef HAVE_COPYING_PUTENV +static void +efree(void *p) +{ + free(p); +} +#endif + static char* strsave(char* string) { diff --git a/erts/etc/common/dialyzer.c b/erts/etc/common/dialyzer.c index c45626606c..c8d977f6de 100644 --- a/erts/etc/common/dialyzer.c +++ b/erts/etc/common/dialyzer.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2006-2013. All Rights Reserved. + * Copyright Ericsson AB 2006-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,13 +63,17 @@ static int eargc; /* Number of arguments in eargv. */ */ static void error(char* format, ...); -static char* emalloc(size_t size); +static void* emalloc(size_t size); +#ifdef HAVE_COPYING_PUTENV +static void efree(void *p); +#endif static char* strsave(char* string); static void push_words(char* src); static int run_erlang(char* name, char** argv); static char* get_default_emulator(char* progname); #ifdef __WIN32__ static char* possibly_quote(char* arg); +static void* erealloc(void *p, size_t size); #endif /* @@ -146,6 +150,29 @@ free_env_val(char *value) #endif } +static void +set_env(char *key, char *value) +{ +#ifdef __WIN32__ + WCHAR wkey[MAXPATHLEN]; + WCHAR wvalue[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, key, -1, wkey, MAXPATHLEN); + MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, MAXPATHLEN); + if (!SetEnvironmentVariableW(wkey, wvalue)) + error("SetEnvironmentVariable(\"%s\", \"%s\") failed!", key, value); +#else + size_t size = strlen(key) + 1 + strlen(value) + 1; + char *str = emalloc(size); + sprintf(str, "%s=%s", key, value); + if (putenv(str) != 0) + error("putenv(\"%s\") failed!", str); +#ifdef HAVE_COPYING_PUTENV + efree(str); +#endif +#endif +} + + #ifdef __WIN32__ int wmain(int argc, wchar_t **wcargv) { @@ -164,10 +191,10 @@ int main(int argc, char** argv) #ifdef __WIN32__ int len; /* Convert argv to utf8 */ - argv = malloc((argc+1) * sizeof(char*)); + argv = emalloc((argc+1) * sizeof(char*)); for (i=0; i<argc; i++) { len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); - argv[i] = malloc(len*sizeof(char)); + argv[i] = emalloc(len*sizeof(char)); WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); } argv[argc] = NULL; @@ -180,6 +207,11 @@ int main(int argc, char** argv) error("Value of environment variable DIALYZER_EMULATOR is too large"); /* + * Add scriptname to env + */ + set_env("ESCRIPT_NAME", argv[0]); + + /* * Allocate the argv vector to be used for arguments to Erlang. * Arrange for starting to pushing information in the middle of * the array, to allow easy addition of commands in the beginning. @@ -310,7 +342,7 @@ wchar_t *make_commandline(char **argv) buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); + buff = (wchar_t *) erealloc(buff,siz*sizeof(wchar_t)); } p = buff; num=0; @@ -413,15 +445,34 @@ error(char* format, ...) exit(1); } -static char* +static void* emalloc(size_t size) { - char *p = malloc(size); + void *p = malloc(size); if (p == NULL) error("Insufficient memory"); return p; } +#ifdef __WIN32__ +static void * +erealloc(void *p, size_t size) +{ + void *res = realloc(p, size); + if (res == NULL) + error("Insufficient memory"); + return res; +} +#endif + +#ifdef HAVE_COPYING_PUTENV +static void +efree(void *p) +{ + free(p); +} +#endif + static char* strsave(char* string) { diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c index f9d909e01c..cbbd2a37cd 100644 --- a/erts/etc/common/erlc.c +++ b/erts/etc/common/erlc.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2013. All Rights Reserved. + * Copyright Ericsson AB 1997-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,13 +71,17 @@ static int pause_after_execution = 0; static char* process_opt(int* pArgc, char*** pArgv, int offset); static void error(char* format, ...); -static char* emalloc(size_t size); +static void* emalloc(size_t size); +#ifdef HAVE_COPYING_PUTENV +static void efree(void *p); +#endif static char* strsave(char* string); static void push_words(char* src); static int run_erlang(char* name, char** argv); static char* get_default_emulator(char* progname); #ifdef __WIN32__ static char* possibly_quote(char* arg); +static void* erealloc(void *p, size_t size); #endif /* @@ -146,6 +150,28 @@ get_env(char *key) } static void +set_env(char *key, char *value) +{ +#ifdef __WIN32__ + WCHAR wkey[MAXPATHLEN]; + WCHAR wvalue[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, key, -1, wkey, MAXPATHLEN); + MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, MAXPATHLEN); + if (!SetEnvironmentVariableW(wkey, wvalue)) + error("SetEnvironmentVariable(\"%s\", \"%s\") failed!", key, value); +#else + size_t size = strlen(key) + 1 + strlen(value) + 1; + char *str = emalloc(size); + sprintf(str, "%s=%s", key, value); + if (putenv(str) != 0) + error("putenv(\"%s\") failed!", str); +#ifdef HAVE_COPYING_PUTENV + efree(str); +#endif +#endif +} + +static void free_env_val(char *value) { #ifdef __WIN32__ @@ -171,10 +197,10 @@ int main(int argc, char** argv) int i; int len; /* Convert argv to utf8 */ - argv = malloc((argc+1) * sizeof(char*)); + argv = emalloc((argc+1) * sizeof(char*)); for (i=0; i<argc; i++) { len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); - argv[i] = malloc(len*sizeof(char)); + argv[i] = emalloc(len*sizeof(char)); WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); } argv[argc] = NULL; @@ -187,6 +213,11 @@ int main(int argc, char** argv) error("Value of environment variable ERLC_EMULATOR is too large"); /* + * Add scriptname to env + */ + set_env("ESCRIPT_NAME", argv[0]); + + /* * Allocate the argv vector to be used for arguments to Erlang. * Arrange for starting to pushing information in the middle of * the array, to allow easy adding of emulator options (like -pa) @@ -370,7 +401,7 @@ wchar_t *make_commandline(char **argv) buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); + buff = (wchar_t *) erealloc(buff,siz*sizeof(wchar_t)); } p = buff; num=0; @@ -478,15 +509,33 @@ error(char* format, ...) exit(1); } -static char* +static void* emalloc(size_t size) { - char *p = malloc(size); + void *p = malloc(size); if (p == NULL) error("Insufficient memory"); return p; } +#ifdef __WIN32__ +static void * +erealloc(void *p, size_t size) +{ + void *res = realloc(p, size); + if (res == NULL) + error("Insufficient memory"); + return res; +} +#endif + +#ifdef HAVE_COPYING_PUTENV +static void +efree(void *p) +{ + free(p); +} +#endif static char* strsave(char* string) { diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index cde0b25a2a..793cb532b3 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2013. All Rights Reserved. + * Copyright Ericsson AB 1996-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ #ifdef __WIN32__ # include "erl_version.h" # include "init_file.h" +# include <Shlobj.h> #endif #define NO 0 @@ -65,6 +66,7 @@ static const char plusM_au_allocs[]= { 'u', /* all alloc_util allocators */ 'B', /* binary_alloc */ + 'I', /* literal_alloc */ 'D', /* std_alloc */ 'E', /* ets_alloc */ 'F', /* fix_alloc */ @@ -73,6 +75,8 @@ static const char plusM_au_allocs[]= { 'R', /* driver_alloc */ 'S', /* sl_alloc */ 'T', /* temp_alloc */ + 'X', /* exec_alloc */ + 'Z', /* test_alloc */ '\0' }; @@ -81,6 +85,8 @@ static char *plusM_au_alloc_switches[] = { "as", "asbcst", "acul", + "acnl", + "acfml", "e", "t", "lmbcs", @@ -120,6 +126,8 @@ static char *plusM_other_switches[] = { "Ym", "Ytp", "Ytt", + "Iscs", + "Xscs", NULL }; @@ -136,6 +144,8 @@ static char *pluss_val_switches[] = { "wt", "ws", "ss", + "ssdcpu", + "ssdio", "pp", "ub", NULL @@ -145,6 +155,10 @@ static char *plush_val_switches[] = { "ms", "mbs", "pds", + "max", + "maxk", + "maxel", + "mqd", "", NULL }; @@ -173,19 +187,9 @@ static char *plusz_val_switches[] = { #endif #define SMP_SUFFIX ".smp" -#define DEBUG_SUFFIX ".debug" -#define EMU_TYPE_SUFFIX_LENGTH strlen(DEBUG_SUFFIX) - -/* - * Define flags for different memory architectures. - */ -#define EMU_TYPE_SMP 0x0001 - -#ifdef __WIN32__ -#define EMU_TYPE_DEBUG 0x0004 -#endif void usage(const char *switchname); +static void usage_format(char *format, ...); void start_epmd(char *epmd); void error(char* format, ...); @@ -193,8 +197,8 @@ void error(char* format, ...); * Local functions. */ -#if !defined(ERTS_HAVE_SMP_EMU) -static void usage_notsup(const char *switchname); +#if !defined(ERTS_HAVE_SMP_EMU) || !defined(ERTS_HAVE_PLAIN_EMU) +static void usage_notsup(const char *switchname, const char *alt); #endif static char **build_args_from_env(char *env_var); static char **build_args_from_string(char *env_var); @@ -209,7 +213,7 @@ 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 char *write_str(char *to, const char *from); static void get_home(void); static void add_epmd_port(void); #ifdef __WIN32__ @@ -243,9 +247,8 @@ 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. */ -static int emu_type_passed = 0; /* Types explicitly set */ +static int start_smp_emu = 0; /* Start the smp emulator. */ +static const char* emu_type = 0; /* Type of emulator (lcnt, valgrind, etc) */ #ifdef __WIN32__ static char *start_emulator_program = NULL; /* For detachec mode - @@ -340,11 +343,11 @@ free_env_val(char *value) } /* - * Add the architecture suffix to the program name if needed, - * except on Windows, where we insert it just before ".DLL". + * Add the type and architecture suffix to the program name if needed. + * On Windows, we insert it just before ".DLL". */ static char* -add_extra_suffixes(char *prog, int type) +add_extra_suffixes(char *prog) { char *res; char *p; @@ -354,16 +357,10 @@ add_extra_suffixes(char *prog, int type) int dll = 0; #endif - if (!type) { - return prog; - } - len = strlen(prog); - /* Worst-case allocation */ - p = emalloc(len + - EMU_TYPE_SUFFIX_LENGTH + - + 1); + /* Allocate enough extra space for suffixes */ + p = emalloc(len + 100); res = p; p = write_str(p, prog); @@ -380,13 +377,11 @@ add_extra_suffixes(char *prog, int type) } #endif -#ifdef __WIN32__ - if (type & EMU_TYPE_DEBUG) { - p = write_str(p, DEBUG_SUFFIX); - type &= ~(EMU_TYPE_DEBUG); + if (emu_type) { + p = write_str(p, "."); + p = write_str(p, emu_type); } -#endif - if (type == EMU_TYPE_SMP) { + if (start_smp_emu) { p = write_str(p, SMP_SUFFIX); } #ifdef __WIN32__ @@ -477,13 +472,11 @@ int main(int argc, char **argv) cpuinfo = erts_cpu_info_create(); /* '-smp auto' is default */ #ifdef ERTS_HAVE_SMP_EMU - if (erts_get_cpu_configured(cpuinfo) > 1) - emu_type |= EMU_TYPE_SMP; + start_smp_emu = 1; #endif #if defined(__WIN32__) && defined(WIN32_ALWAYS_DEBUG) - emu_type_passed |= EMU_TYPE_DEBUG; - emu_type |= EMU_TYPE_DEBUG; + emu_type = "debug"; #endif /* We need to do this before the ordinary processing. */ @@ -508,54 +501,42 @@ int main(int argc, char **argv) if (strcmp(argv[i+1], "auto") == 0) { i++; - smp_auto: - emu_type_passed |= EMU_TYPE_SMP; -#ifdef ERTS_HAVE_SMP_EMU - if (erts_get_cpu_configured(cpuinfo) > 1) - emu_type |= EMU_TYPE_SMP; - else -#endif - emu_type &= ~EMU_TYPE_SMP; - } - else if (strcmp(argv[i+1], "enable") == 0) { + } else if (strcmp(argv[i+1], "enable") == 0) { i++; smp_enable: - emu_type_passed |= EMU_TYPE_SMP; -#ifdef ERTS_HAVE_SMP_EMU - emu_type |= EMU_TYPE_SMP; -#else - usage_notsup("-smp enable"); + ; +#if !defined(ERTS_HAVE_SMP_EMU) + usage_notsup("-smp enable", ""); #endif - } - else if (strcmp(argv[i+1], "disable") == 0) { + } else if (strcmp(argv[i+1], "disable") == 0) { i++; smp_disable: - emu_type_passed |= EMU_TYPE_SMP; - emu_type &= ~EMU_TYPE_SMP; - } - else { - smp: - - emu_type_passed |= EMU_TYPE_SMP; -#ifdef ERTS_HAVE_SMP_EMU - emu_type |= EMU_TYPE_SMP; +#ifdef ERTS_HAVE_PLAIN_EMU + start_smp_emu = 0; #else - usage_notsup("-smp"); + usage_notsup("-smp disable", " Use \"+S 1\" instead."); +#endif + } else { + smp: + ; +#if !defined(ERTS_HAVE_SMP_EMU) + 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; -#ifdef __WIN32__ - } else if (strcmp(argv[i], "-debug") == 0) { - emu_type_passed |= EMU_TYPE_DEBUG; - emu_type |= EMU_TYPE_DEBUG; -#endif } else if (strcmp(argv[i], "-extra") == 0) { break; + } else if (strcmp(argv[i], "-emu_type") == 0) { + if (i + 1 >= argc) { + usage(argv[i]); + } + emu_type = argv[i+1]; + i++; } } i++; @@ -568,13 +549,17 @@ int main(int argc, char **argv) if (strcmp(malloc_lib, "libc") != 0) usage("+MYm"); } - emu = add_extra_suffixes(emu, emu_type); + emu = add_extra_suffixes(emu); emu_name = strsave(emu); erts_snprintf(tmpStr, sizeof(tmpStr), "%s" DIRSEP "%s" BINARY_EXT, bindir, emu); emu = strsave(tmpStr); - add_Eargs(emu); /* Will be argv[0] -- necessary! */ - + s = get_env("ESCRIPT_NAME"); + if(s) { + add_Eargs(s); /* argv[0] = scriptname*/ + } else { + add_Eargs(emu); /* argv[0] = erl or cerl */ + } /* * Add the bindir to the path (unless it is there already). */ @@ -718,7 +703,7 @@ int main(int argc, char **argv) * on itself here. We'll avoid doing that. */ if (strcmp(argv[i], "-make") == 0) { - add_args("-noshell", "-noinput", "-s", "make", "all", NULL); + add_args("-noshell", "-noinput", "-s", "make", "all_or_nothing", NULL); add_Eargs("-B"); haltAfterwards = 1; i = argc; /* Skip rest of command line */ @@ -786,6 +771,24 @@ int main(int argc, char **argv) get_start_erl_data((char *) NULL); } #endif + else if (strcmp(argv[i], "-start_epmd") == 0) { + if (i+1 >= argc) + usage("-start_epmd"); + + if (strcmp(argv[i+1], "true") == 0) { + /* The default */ + no_epmd = 0; + } + else if (strcmp(argv[i+1], "false") == 0) { + no_epmd = 1; + } + else + usage_format("Expected boolean argument for \'-start_epmd\'.\n"); + + add_arg(argv[i]); + add_arg(argv[i+1]); + i++; + } else add_arg(argv[i]); @@ -836,7 +839,6 @@ int main(int argc, char **argv) if (argv[i][3] != '\0') goto the_default; } -#ifdef ERTS_DIRTY_SCHEDULERS else if (argv[i][2] == 'D') { char* type = argv[i]+3; if (strncmp(type, "cpu", 3) != 0 && @@ -848,7 +850,6 @@ int main(int argc, char **argv) (argv[i][3] == 'i' && argv[i][5] != '\0')) goto the_default; } -#endif else if (argv[i][2] != '\0') goto the_default; if (i+1 >= argc) @@ -1018,7 +1019,7 @@ int main(int argc, char **argv) start_epmd(epmd_prog); #if (! defined(__WIN32__)) && defined(DEBUG) - if (start_detached) { + if (start_detached && get_env("ERL_CONSOLE_MODE")) { /* Start the emulator within an xterm. * Move up all arguments and insert * "xterm -e " first. @@ -1142,7 +1143,11 @@ int main(int argc, char **argv) { execv(emu, Eargsp); } - error("Error %d executing \'%s\'.", errno, emu); + if (errno == ENOENT) { + error("The emulator \'%s\' does not exist.", emu); + } else { + error("Error %d executing \'%s\'.", errno, emu); + } return 1; #endif } @@ -1157,16 +1162,16 @@ usage_aux(void) #ifdef __WIN32__ "[-start_erl [datafile]] " #endif - "[-smp " + "[-smp [auto" #ifdef ERTS_HAVE_SMP_EMU - "[enable|" + "|enable" #endif - "auto|disable" -#ifdef ERTS_HAVE_SMP_EMU - "]" +#ifdef ERTS_HAVE_PLAIN_EMU + "|disable" #endif + "]" "] " - "[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] " + "[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] [-start_epmd BOOLEAN] " "[-args_file FILENAME] [+A THREADS] [+a SIZE] [+B[c|d|i]] [+c [BOOLEAN]] " "[+C MODE] [+h HEAP_SIZE_OPTION] [+K BOOLEAN] " "[+l] [+M<SUBSWITCH> <ARGUMENT>] [+P MAX_PROCS] [+Q MAX_PORTS] " @@ -1186,11 +1191,11 @@ usage(const char *switchname) usage_aux(); } -#if !defined(ERTS_HAVE_SMP_EMU) +#if !defined(ERTS_HAVE_SMP_EMU) || !defined(ERTS_HAVE_PLAIN_EMU) static void -usage_notsup(const char *switchname) +usage_notsup(const char *switchname, const char *alt) { - fprintf(stderr, "Argument \'%s\' not supported.\n", switchname); + fprintf(stderr, "Argument \'%s\' not supported.%s\n", switchname, alt); usage_aux(); } #endif @@ -1342,7 +1347,7 @@ is_one_of_strings(char *str, char *strs[]) return 0; } -static char *write_str(char *to, char *from) +static char *write_str(char *to, const char *from) { while (*from) *(to++) = *(from++); @@ -1539,17 +1544,16 @@ static void get_parameters(int argc, char** argv) static void get_home(void) { - int len; - char tmpstr[MAX_PATH+1]; + wchar_t *profile; char* homedrive; char* homepath; homedrive = get_env("HOMEDRIVE"); homepath = get_env("HOMEPATH"); if (!homedrive || !homepath) { - if (len = GetWindowsDirectory(tmpstr,MAX_PATH)) { - home = emalloc(len+1); - strcpy(home,tmpstr); + if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, &profile) == S_OK) { + home = utf16_to_utf8(profile); + /* CoTaskMemFree(profile); */ } else error("HOMEDRIVE or HOMEPATH is not set and GetWindowsDir failed"); } else { @@ -1869,6 +1873,7 @@ read_args_file(char *filename) #undef SAVE_CHAR } + typedef struct { char **argv; int argc; diff --git a/erts/etc/common/escript.c b/erts/etc/common/escript.c index 7fd02ed436..9cd5dd3fab 100644 --- a/erts/etc/common/escript.c +++ b/erts/etc/common/escript.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2007-2013. All Rights Reserved. + * Copyright Ericsson AB 2007-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,14 +71,14 @@ static int eargc; /* Number of arguments in eargv. */ */ static void error(char* format, ...); -static char* emalloc(size_t size); +static void* emalloc(size_t size); static void efree(void *p); static char* strsave(char* string); -static void push_words(char* src); static int run_erlang(char* name, char** argv); static char* get_default_emulator(char* progname); #ifdef __WIN32__ static char* possibly_quote(char* arg); +static void* erealloc(void *p, size_t size); #endif /* @@ -154,6 +154,29 @@ free_env_val(char *value) efree(value); #endif } + +static void +set_env(char *key, char *value) +{ +#ifdef __WIN32__ + WCHAR wkey[MAXPATHLEN]; + WCHAR wvalue[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, key, -1, wkey, MAXPATHLEN); + MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, MAXPATHLEN); + if (!SetEnvironmentVariableW(wkey, wvalue)) + error("SetEnvironmentVariable(\"%s\", \"%s\") failed!", key, value); +#else + size_t size = strlen(key) + 1 + strlen(value) + 1; + char *str = emalloc(size); + sprintf(str, "%s=%s", key, value); + if (putenv(str) != 0) + error("putenv(\"%s\") failed!", str); +#ifdef HAVE_COPYING_PUTENV + efree(str); +#endif +#endif +} + /* * Find absolute path to this program */ @@ -409,7 +432,7 @@ main(int argc, char** argv) char* emulator; char* env; char* basename; - char* absname; + char* def_emu_lookup_path; char scriptname[PMAX]; char** last_opt; char** first_opt; @@ -418,23 +441,15 @@ main(int argc, char** argv) int i; int len; /* Convert argv to utf8 */ - argv = malloc((argc+1) * sizeof(char*)); + argv = emalloc((argc+1) * sizeof(char*)); for (i=0; i<argc; i++) { len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); - argv[i] = malloc(len*sizeof(char)); + argv[i] = emalloc(len*sizeof(char)); WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); } argv[argc] = NULL; #endif - emulator = env = get_env("ESCRIPT_EMULATOR"); - if (emulator == NULL) { - emulator = get_default_emulator(argv[0]); - } - - if (strlen(emulator) >= PMAX) - error("Value of environment variable ESCRIPT_EMULATOR is too large"); - /* * Allocate the argv vector to be used for arguments to Erlang. * Arrange for starting to pushing information in the middle of @@ -445,21 +460,10 @@ main(int argc, char** argv) eargv_base = (char **) emalloc(eargv_size*sizeof(char*)); eargv = eargv_base; eargc = 0; - push_words(emulator); eargc_base = eargc; eargv = eargv + eargv_size/2; eargc = 0; - free_env_val(env); - - /* - * Push initial arguments. - */ - - PUSH("+B"); - PUSH2("-boot", "start_clean"); - PUSH("-noshell"); - /* Determine basename of the executable */ for (basename = argv[0]+strlen(argv[0]); basename > argv[0] && !(IS_DIRSEP(basename[-1])); @@ -475,6 +479,7 @@ main(int argc, char** argv) #else if (strcmp(basename, "escript") == 0) { #endif + def_emu_lookup_path = argv[0]; /* * Locate all options before the script name. */ @@ -493,22 +498,40 @@ main(int argc, char** argv) argc--; argv++; } else { + char *absname = find_prog(argv[0]); #ifdef __WIN32__ - int len; -#endif - absname = find_prog(argv[0]); -#ifdef __WIN32__ - len = strlen(absname); + int len = strlen(absname); if (len >= 4 && _stricmp(absname+len-4, ".exe") == 0) { absname[len-4] = '\0'; } #endif - erts_snprintf(scriptname, sizeof(scriptname), "%s.escript", absname); - efree(absname); + efree(absname); + def_emu_lookup_path = scriptname; + } + + /* Determine path to emulator */ + emulator = env = get_env("ESCRIPT_EMULATOR"); + + if (emulator == NULL) { + emulator = get_default_emulator(def_emu_lookup_path); } + if (strlen(emulator) >= PMAX) + error("Value of environment variable ESCRIPT_EMULATOR is too large"); + + /* + * Push initial arguments. + */ + + PUSH(emulator); + free_env_val(env); + + PUSH("+B"); + PUSH2("-boot", "start_clean"); + PUSH("-noshell"); + /* * Read options from the %%! row in the script and add them as args */ @@ -545,7 +568,12 @@ main(int argc, char** argv) while (--eargc_base >= 0) { UNSHIFT(eargv_base[eargc_base]); } - + + /* + * Add scriptname to env + */ + set_env("ESCRIPT_NAME", scriptname); + /* * Invoke Erlang with the collected options. */ @@ -554,26 +582,6 @@ main(int argc, char** argv) return run_erlang(eargv[0], eargv); } -static void -push_words(char* src) -{ - char sbuf[PMAX]; - char* dst; - - dst = sbuf; - while ((*dst++ = *src++) != '\0') { - if (isspace((int)*src)) { - *dst = '\0'; - PUSH(strsave(sbuf)); - dst = sbuf; - do { - src++; - } while (isspace((int)*src)); - } - } - if (sbuf[0]) - PUSH(strsave(sbuf)); -} #ifdef __WIN32__ wchar_t *make_commandline(char **argv) { @@ -594,7 +602,7 @@ wchar_t *make_commandline(char **argv) buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); + buff = (wchar_t *) erealloc(buff,siz*sizeof(wchar_t)); } p = buff; num=0; @@ -694,15 +702,26 @@ error(char* format, ...) exit(1); } -static char* +static void* emalloc(size_t size) { - char *p = malloc(size); + void *p = malloc(size); if (p == NULL) error("Insufficient memory"); return p; } +#ifdef __WIN32__ +static void * +erealloc(void *p, size_t size) +{ + void *res = realloc(p, size); + if (res == NULL) + error("Insufficient memory"); + return res; +} +#endif + static void efree(void *p) { diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c index aaaffbca79..8f1e89b638 100644 --- a/erts/etc/common/heart.c +++ b/erts/etc/common/heart.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2013. All Rights Reserved. + * Copyright Ericsson AB 1996-2016. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,13 +48,10 @@ * * HEART_BEATING * - * This program expects a heart beat messages. If it does not receive a - * heart beat message from Erlang within heart_beat_timeout seconds, it - * reboots the system. The variable heart_beat_timeout is exported (so - * that it can be set from the shell in VxWorks, as is the variable - * heart_beat_report_delay). When using Solaris, the system is rebooted - * by executing the command stored in the environment variable - * HEART_COMMAND. + * This program expects a heart beat message. If it does not receive a + * heart beat message from Erlang within heart_beat_timeout seconds, it + * reboots the system. The system is rebooted by executing the command + * stored in the environment variable HEART_COMMAND. * * BLOCKING DESCRIPTORS * @@ -119,6 +116,8 @@ #define HEART_COMMAND_ENV "HEART_COMMAND" #define ERL_CRASH_DUMP_SECONDS_ENV "ERL_CRASH_DUMP_SECONDS" #define HEART_KILL_SIGNAL "HEART_KILL_SIGNAL" +#define HEART_NO_KILL "HEART_NO_KILL" + #define MSG_HDR_SIZE (2) #define MSG_HDR_PLUS_OP_SIZE (3) @@ -147,27 +146,17 @@ struct msg { /* Maybe interesting to change */ /* Times in seconds */ -#define HEART_BEAT_BOOT_DELAY 60 /* 1 minute */ #define SELECT_TIMEOUT 5 /* Every 5 seconds we reset the watchdog timer */ /* heart_beat_timeout is the maximum gap in seconds between two - consecutive heart beat messages from Erlang, and HEART_BEAT_BOOT_DELAY - is the the extra delay that wd_keeper allows for, to give heart a - chance to reboot in the "normal" way before the hardware watchdog - enters the scene. heart_beat_report_delay is the time allowed for reporting - before rebooting under VxWorks. */ + consecutive heart beat messages from Erlang. */ int heart_beat_timeout = 60; -int heart_beat_report_delay = 30; -int heart_beat_boot_delay = HEART_BEAT_BOOT_DELAY; /* All current platforms have a process identifier that fits in an unsigned long and where 0 is an impossible or invalid value */ unsigned long heart_beat_kill_pid = 0; -#define VW_WD_TIMEOUT (heart_beat_timeout+heart_beat_report_delay+heart_beat_boot_delay) -#define SOL_WD_TIMEOUT (heart_beat_timeout+heart_beat_boot_delay) - /* reasons for reboot */ #define R_TIMEOUT (1) #define R_CLOSED (2) @@ -295,7 +284,6 @@ free_env_val(char *value) static void get_arguments(int argc, char** argv) { int i = 1; int h; - int w; unsigned long p; while (i < argc) { @@ -311,15 +299,6 @@ static void get_arguments(int argc, char** argv) { i++; } break; - case 'w': - if (strcmp(argv[i], "-wt") == 0) - if (sscanf(argv[i+1],"%i",&w) ==1) - if ((w > 10) && (w <= 65535)) { - heart_beat_boot_delay = w; - fprintf(stderr,"heart_beat_boot_delay = %d\n",w); - i++; - } - break; case 'p': if (strcmp(argv[i], "-pid") == 0) if (sscanf(argv[i+1],"%lu",&p) ==1){ @@ -345,7 +324,7 @@ static void get_arguments(int argc, char** argv) { } i++; } - debugf("arguments -ht %d -wt %d -pid %lu\n",h,w,p); + debugf("arguments -ht %d -pid %lu\n",h,p); } int main(int argc, char **argv) { @@ -472,10 +451,6 @@ message_loop(erlin_fd, erlout_fd) switch (mp->op) { case HEART_BEAT: timestamp(&last_received); -#ifdef USE_WATCHDOG - /* reset the hardware watchdog timer */ - wd_reset(); -#endif break; case SHUT_DOWN: return R_SHUT_DOWN; @@ -528,6 +503,12 @@ static void kill_old_erlang(void){ HANDLE erlh; DWORD exit_code; + char* envvar = NULL; + + envvar = get_env(HEART_NO_KILL); + if (envvar && strcmp(envvar, "TRUE") == 0) + return; + if(heart_beat_kill_pid != 0){ if((erlh = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE | @@ -559,10 +540,14 @@ kill_old_erlang(void){ pid_t pid; int i, res; int sig = SIGKILL; - char *sigenv = NULL; + char *envvar = NULL; + + envvar = get_env(HEART_NO_KILL); + if (envvar && strcmp(envvar, "TRUE") == 0) + return; - sigenv = get_env(HEART_KILL_SIGNAL); - if (sigenv && strcmp(sigenv, "SIGABRT") == 0) { + envvar = get_env(HEART_KILL_SIGNAL); + if (envvar && strcmp(envvar, "SIGABRT") == 0) { print_error("kill signal SIGABRT requested"); sig = SIGABRT; } @@ -666,11 +651,6 @@ void win_system(char *command) */ static void do_terminate(int erlin_fd, int reason) { - /* - When we get here, we have HEART_BEAT_BOOT_DELAY secs to finish - (plus heart_beat_report_delay if under VxWorks), so we don't need - to call wd_reset(). - */ int ret = 0, tmo=0; char *tmo_env; @@ -718,14 +698,12 @@ do_terminate(int erlin_fd, int reason) { print_error("Would reboot. Terminating."); else { kill_old_erlang(); - /* suppress gcc warning with 'if' */ ret = system(command); print_error("Executed \"%s\" -> %d. Terminating.",command, ret); } free_env_val(command); } else { kill_old_erlang(); - /* suppress gcc warning with 'if' */ ret = system((char*)&cmd[0]); print_error("Executed \"%s\" -> %d. Terminating.",cmd, ret); } diff --git a/erts/etc/common/inet_gethost.c b/erts/etc/common/inet_gethost.c index e298c5e7f7..b746487668 100644 --- a/erts/etc/common/inet_gethost.c +++ b/erts/etc/common/inet_gethost.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2012. All Rights Reserved. + * Copyright Ericsson AB 1998-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -2646,7 +2646,7 @@ static void *my_realloc(void *old, size_t size) BOOL create_mesq(MesQ **q) { - MesQ *tmp = malloc(sizeof(MesQ)); + MesQ *tmp = ALLOC(sizeof(MesQ)); tmp->data_present = CreateEvent(NULL, TRUE, FALSE,NULL); if (tmp->data_present == NULL) { free(tmp); @@ -2717,7 +2717,7 @@ BOOL close_mesq(MesQ *q) LeaveCriticalSection(&(q->crit)); return FALSE; } - /* Noone else is supposed to use this object any more */ + /* No one else is supposed to use this object any more */ LeaveCriticalSection(&(q->crit)); DeleteCriticalSection(&(q->crit)); CloseHandle(q->data_present); diff --git a/erts/etc/common/run_erl_common.c b/erts/etc/common/run_erl_common.c deleted file mode 100644 index c03d5e3ae2..0000000000 --- a/erts/etc/common/run_erl_common.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2014. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <time.h> -#include <unistd.h> - -#ifdef __ANDROID__ -# include <termios.h> -#endif - -#ifdef HAVE_SYSLOG_H -# include <syslog.h> -#endif - -#ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -#endif - -#ifdef __OSE__ -# include "ramlog.h" -#endif - -#include "run_erl_common.h" -#include "safe_string.h" - -#define DEFAULT_LOG_GENERATIONS 5 -#define LOG_MAX_GENERATIONS 1000 /* No more than 1000 log files */ -#define LOG_MIN_GENERATIONS 2 /* At least two to switch between */ -#define DEFAULT_LOG_MAXSIZE 100000 -#define LOG_MIN_MAXSIZE 1000 /* Smallast value for changing log file */ -#define LOG_STUBNAME "erlang.log." -#define LOG_PERM 0664 -#define DEFAULT_LOG_ACTIVITY_MINUTES 5 -#define DEFAULT_LOG_ALIVE_MINUTES 15 -#define DEFAULT_LOG_ALIVE_FORMAT "%a %b %e %T %Z %Y" -#define ALIVE_BUFFSIZ 1024 - -#define STATUSFILENAME "/run_erl.log" - -#define PIPE_STUBNAME "erlang.pipe" -#define PIPE_STUBLEN strlen(PIPE_STUBNAME) -#define PERM (S_IWUSR | S_IRUSR | S_IWOTH | S_IROTH | S_IWGRP | S_IRGRP) - -/* OSE has defined O_SYNC but it is not recognized by open */ -#if !defined(O_SYNC) || defined(__OSE__) -#undef O_SYNC -#define O_SYNC 0 -#define USE_FSYNC 1 -#endif - -/* Global variable definitions - * We need this complex way of handling global variables because of how - * OSE works here. We want to make it possible to run the shell command - * run_erl multiple times with different global variables without them - * effecting eachother. - */ - -#define STATUSFILE (RE_DATA->statusfile) -#define LOG_DIR (RE_DATA->log_dir) -#define STDSTATUS (RE_DATA->stdstatus) -#define LOG_GENERATIONS (RE_DATA->log_generations) -#define LOG_MAXSIZE (RE_DATA->log_maxsize) -#define LOG_ACTIVITY_MINUTES (RE_DATA->log_activity_minutes) -#define LOG_ALIVE_IN_GMT (RE_DATA->log_alive_in_gmt) -#define LOG_ALIVE_FORMAT (RE_DATA->log_alive_format) -#define RUN_DAEMON (RE_DATA->run_daemon) -#define LOG_ALIVE_MINUTES (RE_DATA->log_alive_minutes) -#define LOG_NUM (RE_DATA->log_num) -#define LFD (RE_DATA->lfd) -#define PROTOCOL_VER (RE_DATA->protocol_ver) - -struct run_erl_ { - /* constant config data */ - char statusfile[FILENAME_BUFSIZ]; - char log_dir[FILENAME_BUFSIZ]; - FILE *stdstatus; - int log_generations; - int log_maxsize; - int log_activity_minutes; - int log_alive_in_gmt; - char log_alive_format[ALIVE_BUFFSIZ+1]; - int run_daemon; - int log_alive_minutes; - /* Current log number and log fd */ - int log_num; - int lfd; - unsigned protocol_ver; -}; - -typedef struct run_erl_ run_erl; - -#ifdef __OSE__ -static OSPPDKEY run_erl_pp_key; -#define RE_DATA (*(run_erl**)ose_get_ppdata(run_erl_pp_key)) -#else -static run_erl re; -#define RE_DATA (&re) -#endif - -/* prototypes */ - -static int next_log(int log_num); -static int prev_log(int log_num); -static int find_next_log_num(void); -static int open_log(int log_num, int flags); - -/* - * getenv_int: - */ -static char *getenv_int(const char *name) { -#ifdef __OSE__ - return get_env(get_bid(current_process()),name); -#else - return getenv(name); -#endif -} - -/* - * next_log: - * Returns the index number that follows the given index number. - * (Wrapping after log_generations) - */ -static int next_log(int log_num) { - return log_num>=LOG_GENERATIONS?1:log_num+1; -} - -/* - * prev_log: - * Returns the index number that precedes the given index number. - * (Wrapping after log_generations) - */ -static int prev_log(int log_num) { - return log_num<=1?LOG_GENERATIONS:log_num-1; -} - -/* - * find_next_log_num() - * Searches through the log directory to check which logs that already - * exist. It finds the "hole" in the sequence, and returns the index - * number for the last log in the log sequence. If there is no hole, index - * 1 is returned. - */ -static int find_next_log_num(void) { - int i, next_gen, log_gen; - DIR *dirp; - struct dirent *direntp; - int log_exists[LOG_MAX_GENERATIONS+1]; - int stub_len = strlen(LOG_STUBNAME); - - /* Initialize exiting log table */ - - for(i=LOG_GENERATIONS; i>=0; i--) - log_exists[i] = 0; - dirp = opendir(LOG_DIR); - if(!dirp) { - ERRNO_ERR1(LOG_ERR,"Can't access log directory '%s'", LOG_DIR); - exit(1); - } - - /* Check the directory for existing logs */ - - while((direntp=readdir(dirp)) != NULL) { - if(strncmp(direntp->d_name,LOG_STUBNAME,stub_len)==0) { - int num = atoi(direntp->d_name+stub_len); - if(num < 1 || num > LOG_GENERATIONS) - continue; - log_exists[num] = 1; - } - } - closedir(dirp); - - /* Find out the next available log file number */ - - next_gen = 0; - for(i=LOG_GENERATIONS; i>=0; i--) { - if(log_exists[i]) - if(next_gen) - break; - else - ; - else - next_gen = i; - } - - /* Find out the current log file number */ - - if(next_gen) - log_gen = prev_log(next_gen); - else - log_gen = 1; - - return log_gen; -} /* find_next_log_num() */ - -static int open_log(int log_num, int flags) -{ - char buf[FILENAME_MAX]; - time_t now; - struct tm *tmptr; - char log_buffer[ALIVE_BUFFSIZ+1]; - - /* Remove the next log (to keep a "hole" in the log sequence) */ - sn_printf(buf, sizeof(buf), "%s/%s%d", - LOG_DIR, LOG_STUBNAME, next_log(log_num)); - unlink(buf); - - /* Create or continue on the current log file */ - sn_printf(buf, sizeof(buf), "%s/%s%d", LOG_DIR, LOG_STUBNAME, log_num); - - LFD = sf_open(buf, flags, LOG_PERM); - - if(LFD <0){ - ERRNO_ERR1(LOG_ERR,"Can't open log file '%s'.", buf); - exit(1); - } - - /* Write a LOGGING STARTED and time stamp into the log file */ - time(&now); - if (LOG_ALIVE_IN_GMT) { - tmptr = gmtime(&now); - } else { - tmptr = localtime(&now); - } - if (!strftime(log_buffer, ALIVE_BUFFSIZ, LOG_ALIVE_FORMAT, - tmptr)) { - strn_cpy(log_buffer, sizeof(log_buffer), - "(could not format time in 256 positions " - "with current format string.)"); - } - log_buffer[ALIVE_BUFFSIZ] = '\0'; - - sn_printf(buf, sizeof(buf), "\n=====\n===== LOGGING STARTED %s\n=====\n", - log_buffer); - if (erts_run_erl_write_all(LFD, buf, strlen(buf)) < 0) - erts_run_erl_log_status("Error in writing to log.\n"); - -#if USE_FSYNC - fsync(LFD); -#endif - - return LFD; -} - -/* Instead of making sure basename exists, we do our own */ -char *simple_basename(char *path) -{ - char *ptr; - for (ptr = path; *ptr != '\0'; ++ptr) { - if (*ptr == '/') { - path = ptr + 1; - } - } - return path; -} - -ssize_t sf_read(int fd, void *buffer, size_t len) { - ssize_t n = 0; - - do { n = read(fd, buffer, len); } while (n < 0 && errno == EINTR); - - return n; -} - -ssize_t sf_write(int fd, const void *buffer, size_t len) { - ssize_t n = 0; - - do { n = write(fd, buffer, len); } while (n < 0 && errno == EINTR); - - return n; -} - -int sf_open(const char *path, int type, mode_t mode) { - int fd = 0; - - do { fd = open(path, type, mode); } while(fd < 0 && errno == EINTR); - - return fd; -} - -int sf_close(int fd) { - int res = 0; - - do { res = close(fd); } while(res < 0 && errno == EINTR); - - return res; -} - -/* Call write() until entire buffer has been written or error. - * Return len or -1. - */ -int erts_run_erl_write_all(int fd, const char* buf, int len) -{ - int left = len; - int written; - for (;;) { - do { - written = write(fd,buf,left); - } while (written < 0 && errno == EINTR); - if (written == left) { - return len; - } - if (written < 0) { - return -1; - } - left -= written; - buf += written; - } - return written; -} - -/* erts_run_erl_log_status() - * Prints the arguments to a status file - * Works like printf (see vfrpintf) - */ -void erts_run_erl_log_status(const char *format,...) -{ - va_list args; - time_t now; - - if (STDSTATUS == NULL) - STDSTATUS = fopen(STATUSFILE, "w"); - if (STDSTATUS == NULL) - return; - now = time(NULL); - fprintf(STDSTATUS, "run_erl [%d] %s", -#ifdef __OSE__ - (int)current_process(), -#else - (int)getpid(), -#endif - ctime(&now)); - va_start(args, format); - vfprintf(STDSTATUS, format, args); - va_end(args); - fflush(STDSTATUS); - return; -} - -/* Fetch the current log alive minutes */ -int erts_run_erl_log_alive_minutes() { - return LOG_ALIVE_MINUTES; -} - -/* error_logf() - * Prints the arguments to stderr or syslog - * Works like printf (see vfprintf) - */ -void erts_run_erl_log_error(int priority, int line, const char *format, ...) -{ - va_list args; - va_start(args, format); - -#ifdef HAVE_SYSLOG_H - if (RUN_DAEMON) { - vsyslog(priority,format,args); - } - else -#endif -#ifdef __OSE__ - if (RUN_DAEMON) { - char *buff = malloc(sizeof(char)*1024); - vsnprintf(buff,1024,format, args); - ramlog_printf(buff); - } - else -#endif - { - time_t now = time(NULL); - fprintf(stderr, "run_erl:%d [%d] %s", line, -#ifdef __OSE__ - (int)current_process(), -#else - (int)getpid(), -#endif - ctime(&now)); - vfprintf(stderr, format, args); - } - va_end(args); -} - -/* erts_run_erl_log_write() - * Writes a message to lfd. If the current log file is full, - * a new log file is opened. - */ -int erts_run_erl_log_write(char* buf, size_t len) -{ - int size; - ssize_t res; - /* Decide if new logfile needed, and open if so */ - - size = lseek(LFD,0,SEEK_END); - if(size+len > LOG_MAXSIZE) { - int res; - do { - res = close(LFD); - } while (res < 0 && errno == EINTR); - LOG_NUM = next_log(LOG_NUM); - LFD = open_log(LOG_NUM, O_RDWR|O_CREAT|O_TRUNC|O_SYNC); - } - - /* Write to log file */ - - if ((res = erts_run_erl_write_all(LFD, buf, len)) < 0) { - erts_run_erl_log_status("Error in writing to log.\n"); - } - -#if USE_FSYNC - fsync(LFD); -#endif - return res; -} - -int erts_run_erl_log_activity(int timeout,time_t now,time_t last_activity) { - char log_alive_buffer[ALIVE_BUFFSIZ+1]; - char buf[BUFSIZ]; - - if (timeout || now - last_activity > LOG_ACTIVITY_MINUTES*60) { - /* Either a time out: 15 minutes without action, */ - /* or something is coming in right now, but it's a long time */ - /* since last time, so let's write a time stamp this message */ - struct tm *tmptr; - if (LOG_ALIVE_IN_GMT) { - tmptr = gmtime(&now); - } else { - tmptr = localtime(&now); - } - if (!strftime(log_alive_buffer, ALIVE_BUFFSIZ, LOG_ALIVE_FORMAT, - tmptr)) { - strn_cpy(log_alive_buffer, sizeof(log_alive_buffer), - "(could not format time in 256 positions " - "with current format string.)"); - } - log_alive_buffer[ALIVE_BUFFSIZ] = '\0'; - - sn_printf(buf, sizeof(buf), "\n===== %s%s\n", - timeout?"ALIVE ":"", log_alive_buffer); - return erts_run_erl_log_write(buf, strlen(buf)); - } - return 0; -} - -int erts_run_erl_log_open() { - - LOG_NUM = find_next_log_num(); - LFD = open_log(LOG_NUM, O_RDWR|O_APPEND|O_CREAT|O_SYNC); - return 0; -} - -int erts_run_erl_log_init(int daemon, char* logdir) { - char *p; - -#ifdef __OSE__ - run_erl **re_pp; - if (!run_erl_pp_key) - ose_create_ppdata("run_erl_ppdata",&run_erl_pp_key); - re_pp = (run_erl **)ose_get_ppdata(run_erl_pp_key); - *re_pp = malloc(sizeof(run_erl)); -#endif - - STDSTATUS = NULL; - LOG_GENERATIONS = DEFAULT_LOG_GENERATIONS; - LOG_MAXSIZE = DEFAULT_LOG_MAXSIZE; - LOG_ACTIVITY_MINUTES = DEFAULT_LOG_ACTIVITY_MINUTES; - LOG_ALIVE_IN_GMT = 0; - RUN_DAEMON = 0; - LOG_ALIVE_MINUTES = DEFAULT_LOG_ALIVE_MINUTES; - LFD = 0; - PROTOCOL_VER = RUN_ERL_LO_VER; /* assume lowest to begin with */ - - /* Get values for LOG file handling from the environment */ - if ((p = getenv_int("RUN_ERL_LOG_ALIVE_MINUTES"))) { - LOG_ALIVE_MINUTES = atoi(p); - if (!LOG_ALIVE_MINUTES) { - ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ALIVE_MINUTES is 1 " - "(current value is %s)",p); - } - LOG_ACTIVITY_MINUTES = LOG_ALIVE_MINUTES / 3; - if (!LOG_ACTIVITY_MINUTES) { - ++LOG_ACTIVITY_MINUTES; - } - } - if ((p = getenv_int( - "RUN_ERL_LOG_ACTIVITY_MINUTES"))) { - LOG_ACTIVITY_MINUTES = atoi(p); - if (!LOG_ACTIVITY_MINUTES) { - ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ACTIVITY_MINUTES is 1 " - "(current value is %s)",p); - } - } - if ((p = getenv_int("RUN_ERL_LOG_ALIVE_FORMAT"))) { - if (strlen(p) > ALIVE_BUFFSIZ) { - ERROR1(LOG_ERR, "RUN_ERL_LOG_ALIVE_FORMAT can contain a maximum of " - "%d characters", ALIVE_BUFFSIZ); - } - strn_cpy(LOG_ALIVE_FORMAT, sizeof(LOG_ALIVE_FORMAT), p); - } else { - strn_cpy(LOG_ALIVE_FORMAT, sizeof(LOG_ALIVE_FORMAT), - DEFAULT_LOG_ALIVE_FORMAT); - } - if ((p = getenv_int("RUN_ERL_LOG_ALIVE_IN_UTC")) - && strcmp(p,"0")) { - ++LOG_ALIVE_IN_GMT; - } - if ((p = getenv_int("RUN_ERL_LOG_GENERATIONS"))) { - LOG_GENERATIONS = atoi(p); - if (LOG_GENERATIONS < LOG_MIN_GENERATIONS) - ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_GENERATIONS is %d", - LOG_MIN_GENERATIONS); - if (LOG_GENERATIONS > LOG_MAX_GENERATIONS) - ERROR1(LOG_ERR,"Maximum RUN_ERL_LOG_GENERATIONS is %d", - LOG_MAX_GENERATIONS); - } - - if ((p = getenv_int("RUN_ERL_LOG_MAXSIZE"))) { - LOG_MAXSIZE = atoi(p); - if (LOG_MAXSIZE < LOG_MIN_MAXSIZE) - ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_MAXSIZE is %d", LOG_MIN_MAXSIZE); - } - - RUN_DAEMON = daemon; - - strn_cpy(LOG_DIR, sizeof(LOG_DIR), logdir); - strn_cpy(STATUSFILE, sizeof(STATUSFILE), LOG_DIR); - strn_cat(STATUSFILE, sizeof(STATUSFILE), STATUSFILENAME); - - return 0; -} - -/* create_fifo() - * Creates a new fifo with the given name and permission. - */ -static int create_fifo(char *name, int perm) -{ - if ((mkfifo(name, perm) < 0) && (errno != EEXIST)) - return -1; - return 0; -} - -/* - * w- and r_pipename have to be pre-allocated of atleast FILENAME_MAX size - */ -int erts_run_erl_open_fifo(char *pipename,char *w_pipename,char *r_pipename) { - int calculated_pipename = 0; - int highest_pipe_num = 0; - int fd; - - /* - * Create FIFOs and open them - */ - - if(*pipename && pipename[strlen(pipename)-1] == '/') { - /* The user wishes us to find a unique pipe name in the specified */ - /* directory */ - DIR *dirp; - struct dirent *direntp; - - calculated_pipename = 1; - dirp = opendir(pipename); - if(!dirp) { - ERRNO_ERR1(LOG_ERR,"Can't access pipe directory '%s'.", pipename); - return 1; - } - - /* Check the directory for existing pipes */ - - while((direntp=readdir(dirp)) != NULL) { - if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) { - int num = atoi(direntp->d_name+PIPE_STUBLEN+1); - if(num > highest_pipe_num) - highest_pipe_num = num; - } - } - closedir(dirp); - strn_catf(pipename, BUFSIZ, "%s.%d", - PIPE_STUBNAME, highest_pipe_num+1); - } /* if */ - - for(;;) { - /* write FIFO - is read FIFO for `to_erl' program */ - strn_cpy(w_pipename, BUFSIZ, pipename); - strn_cat(w_pipename, BUFSIZ, ".r"); - if (create_fifo(w_pipename, PERM) < 0) { - ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for writing.", - w_pipename); - return 1; - } - - /* read FIFO - is write FIFO for `to_erl' program */ - strn_cpy(r_pipename, BUFSIZ, pipename); - strn_cat(r_pipename, BUFSIZ, ".w"); - - /* Check that nobody is running run_erl already */ - if ((fd = sf_open(r_pipename, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) { - /* Open as client succeeded -- run_erl is already running! */ - sf_close(fd); - if (calculated_pipename) { - ++highest_pipe_num; - strn_catf(pipename, BUFSIZ, "%s.%d", - PIPE_STUBNAME, highest_pipe_num+1); - continue; - } - ERROR1(LOG_ERR, "Erlang already running on pipe %s.\n", pipename); - unlink(w_pipename); - return 1; - } - if (create_fifo(r_pipename, PERM) < 0) { - unlink(w_pipename); - ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.", - r_pipename); - return 1; - } - break; - } - return 0; -} - -/* Extract any control sequences that are ment only for run_erl - * and should not be forwarded to the pty. - */ -int erts_run_erl_extract_ctrl_seq(char* buf, int len, int mfd) -{ - static const char prefix[] = "\033_"; - static const char suffix[] = "\033\\"; - char* bufend = buf + len; - char* start = buf; - char* command; - char* end; - - for (;;) { - start = find_str(start, bufend-start, prefix); - if (!start) break; - - command = start + strlen(prefix); - end = find_str(command, bufend-command, suffix); - if (end) { - unsigned col, row; - if (sscanf(command,"version=%u", &PROTOCOL_VER)==1) { - /*fprintf(stderr,"to_erl v%u\n", protocol_ver);*/ - } - else if (sscanf(command,"winsize=%u,%u", &col, &row)==2) { -#ifdef TIOCSWINSZ - struct winsize ws; - ws.ws_col = col; - ws.ws_row = row; - if (ioctl(mfd, TIOCSWINSZ, &ws) < 0) { - ERRNO_ERR0(LOG_ERR,"Failed to set window size"); - } -#endif - } - else { - ERROR2(LOG_ERR, "Ignoring unknown ctrl command '%.*s'\n", - (int)(end-command), command); - } - - /* Remove ctrl sequence from buf */ - end += strlen(suffix); - memmove(start, end, bufend-end); - bufend -= end - start; - } - else { - ERROR2(LOG_ERR, "Missing suffix in ctrl sequence '%.*s'\n", - (int)(bufend-start), start); - break; - } - } - return bufend - buf; -} diff --git a/erts/etc/common/run_erl_common.h b/erts/etc/common/run_erl_common.h deleted file mode 100644 index cecf7521f9..0000000000 --- a/erts/etc/common/run_erl_common.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2013. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Functions that are common to both OSE and unix implementations of run_erl - */ -#ifndef ERL_RUN_ERL_LOG_H -#define ERL_RUN_ERL_LOG_H - -#include <stdio.h> -#include <time.h> -#include <unistd.h> - -#include "run_erl_vsn.h" - -/* Log handling */ -int erts_run_erl_log_init(int run_daemon, char* logdir); -int erts_run_erl_log_open(void); -int erts_run_erl_log_close(void); -int erts_run_erl_log_write(char *buff, size_t len); -int erts_run_erl_log_activity(int timeout, time_t now, time_t last_activity); - -void erts_run_erl_log_status(const char *format,...); -void erts_run_erl_log_error(int priority, int line, const char *format,...); - -int erts_run_erl_open_fifo(char *pipename,char *w_pipename,char *r_pipename); -int erts_run_erl_log_alive_minutes(void); -int erts_run_erl_extract_ctrl_seq(char* buf, int len, int mfd); - -/* File operations */ -ssize_t sf_read(int fd, void *buffer, size_t len); -ssize_t sf_write(int fd, const void *buffer, size_t len); -int sf_open(const char *path, int type, mode_t mode); -int sf_close(int fd); -int erts_run_erl_write_all(int fd, const char* buf, int len); -char *simple_basename(char *path); - -#ifndef LOG_ERR -#ifdef __OSE__ -#define LOG_ERR 0 -#else -#define LOG_ERR NULL -#endif -#endif - -#define ERROR0(Prio,Format) erts_run_erl_log_error(Prio,__LINE__,Format"\n") -#define ERROR1(Prio,Format,A1) erts_run_erl_log_error(Prio,__LINE__,Format"\n",A1) -#define ERROR2(Prio,Format,A1,A2) erts_run_erl_log_error(Prio,__LINE__,Format"\n",A1,A2) - -#ifdef HAVE_STRERROR -# define ADD_ERRNO(Format) "errno=%d '%s'\n"Format"\n",errno,strerror(errno) -#else -# define ADD_ERRNO(Format) "errno=%d\n"Format"\n",errno -#endif -#define ERRNO_ERR0(Prio,Format) erts_run_erl_log_error(Prio,__LINE__,ADD_ERRNO(Format)) -#define ERRNO_ERR1(Prio,Format,A1) erts_run_erl_log_error(Prio,__LINE__,ADD_ERRNO(Format),A1) -#define ERRNO_ERR2(Prio,Format,A1,A2) erts_run_erl_log_error(Prio,__LINE__,ADD_ERRNO(Format),A1,A2) - -#define RUN_ERL_USAGE \ - "%s (pipe_name|pipe_dir/) log_dir \"command [parameters ...]\"" \ - "\n\nDESCRIPTION:\n" \ - "You may also set the environment variables RUN_ERL_LOG_GENERATIONS\n" \ - "and RUN_ERL_LOG_MAXSIZE to the number of log files to use and the\n" \ - "size of the log file when to switch to the next log file\n" - -#ifndef FILENAME_MAX -#define FILENAME_MAX 250 -#endif - -#define FILENAME_BUFSIZ FILENAME_MAX - -#ifdef O_NONBLOCK -# define DONT_BLOCK_PLEASE O_NONBLOCK -#else -# define DONT_BLOCK_PLEASE O_NDELAY -# ifndef EAGAIN -# define EAGAIN -3898734 -# endif -#endif - -#endif diff --git a/erts/etc/common/run_erl_vsn.h b/erts/etc/common/run_erl_vsn.h deleted file mode 100644 index 2c3e67e81c..0000000000 --- a/erts/etc/common/run_erl_vsn.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/* - * The protocol version number used between to_erl and run_erl. - */ -#define RUN_ERL_HI_VER 1 /* My preferred protocol version */ -#define RUN_ERL_LO_VER 0 /* The lowest version I accept to talk with */ - -/* Version history: - * 0: Older, without version handshake - * 1: R12B-3, version handshake + window size ctrl - */ diff --git a/erts/etc/common/safe_string.c b/erts/etc/common/safe_string.c deleted file mode 100644 index cdcdbf16f0..0000000000 --- a/erts/etc/common/safe_string.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Module: safe_string.c - * - * This is a bunch of generic string operation - * that are safe regarding buffer overflow. - * - * All string functions terminate the process with an error message - * on buffer overflow. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "safe_string.h" -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <stdlib.h> - - -static void string_overflow_handler(const char* format, ...) -{ - va_list args; - va_start(args, format); - vfprintf(stderr,format,args); - va_end(args); - exit(1); -} - -int vsn_printf(char* dst, size_t size, const char* format, va_list args) -{ - int ret = vsnprintf(dst, size, format, args); - if (ret >= size || ret < 0) { - string_overflow_handler("Buffer truncated '%s'\n",dst); - } - return ret; -} - -int sn_printf(char* dst, size_t size, const char* format, ...) -{ - va_list args; - int ret; - va_start(args, format); - ret = vsn_printf(dst,size,format,args); - va_end(args); - return ret; -} - -int strn_cpy(char* dst, size_t size, const char* src) -{ - return sn_printf(dst,size,"%s",src); -} - -int strn_cat(char* dst, size_t size, const char* src) -{ - return strn_catf(dst,size,"%s",src); -} - -int strn_catf(char* dst, size_t size, const char* format, ...) -{ - int ret; - va_list args; -#ifdef _GNU_SOURCE - int len = strnlen(dst,size); -#else - int len = strlen(dst); -#endif - - if (len >= size) { - string_overflow_handler("Buffer already overflowed '%.*s'\n", - size, dst); - } - va_start(args, format); - ret = vsn_printf(dst+len, size-len, format, args); - va_end(args); - return len+ret; -} - -char* find_str(const char* haystack, int hsize, const char* needle) -{ - int i = 0; - int nsize = strlen(needle); - hsize -= nsize - 1; - for (i=0; i<hsize; i++) { - if (haystack[i]==needle[0] && strncmp(haystack+i,needle,nsize)==0) { - return (char*)(haystack+i); - } - } - return NULL; -} - -#ifndef HAVE_MEMMOVE -void* memmove(void *dest, const void *src, size_t n) -{ - int i; - if (src > dest) { - for (i=0; i<n; i++) ((char*)dest)[i] = ((char*)src)[i]; - } - else { - for (i=(int)(n-1); i>=0; i--) ((char*)dest)[i] = ((char*)src)[i]; - } - return dest; -} -#endif /* HAVE_MEMMOVE */ diff --git a/erts/etc/common/safe_string.h b/erts/etc/common/safe_string.h deleted file mode 100644 index f9d2b2023a..0000000000 --- a/erts/etc/common/safe_string.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2008-2009. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Module: safe_string.h - * - * This is an interface to a bunch of generic string operation - * that are safe regarding buffer overflow. - * - * All string functions terminate the process with an error message - * on buffer overflow. - */ - -#include <stdio.h> -#include <stdarg.h> - -/* Like vsnprintf() - */ -int vsn_printf(char* dst, size_t size, const char* format, va_list args); - -/* Like snprintf() - */ -int sn_printf(char* dst, size_t size, const char* format, ...); - -/* Like strncpy() - * Returns length of copied string. - */ -int strn_cpy(char* dst, size_t size, const char* src); - -/* Almost like strncat() - * size is sizeof entire dst buffer. - * Returns length of resulting string. - */ -int strn_cat(char* dst, size_t size, const char* src); - -/* Combination of strncat() and snprintf() - * size is sizeof entire dst buffer. - * Returns length of resulting string. - */ -int strn_catf(char* dst, size_t size, const char* format, ...); - -/* Simular to strstr() but search size bytes of haystack - * without regard to '\0' characters. - */ -char* find_str(const char* haystack, int size, const char* needle); - -#ifndef HAVE_MEMMOVE -void* memmove(void *dest, const void *src, size_t n); -#endif diff --git a/erts/etc/common/to_erl_common.c b/erts/etc/common/to_erl_common.c deleted file mode 100644 index 8aa94ccfa4..0000000000 --- a/erts/etc/common/to_erl_common.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2013. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Module: to_erl.c - * - * This module implements a process that opens two specified FIFOs, one - * for reading and one for writing; reads from its stdin, and writes what - * it has read to the write FIF0; reads from the read FIFO, and writes to - * its stdout. - * - ________ _________ - | |--<-- pipe.r (fifo1) --<--| | - | to_erl | | run_erl | (parent) - |________|-->-- pipe.w (fifo2) -->--|_________| - ^ master pty - | - | slave pty - ____V____ - | | - | "erl" | (child) - |_________| - */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/types.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <dirent.h> -#include <errno.h> - -#ifdef __OSE__ -#include <aio.h> -#include "ose.h" -#include "efs.h" -#include "ose_spi/fm.sig" -#else /* __UNIX__ */ -#include <termios.h> -#include <signal.h> -#endif - -#ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -#endif - -#include "to_erl_common.h" -#include "run_erl_vsn.h" -#include "safe_string.h" /* strn_cpy, strn_catf, sn_printf, etc. */ - -#if defined(O_NONBLOCK) -# define DONT_BLOCK_PLEASE O_NONBLOCK -#else -# define DONT_BLOCK_PLEASE O_NDELAY -# if !defined(EAGAIN) -# define EAGAIN -3898734 -# endif -#endif - -#ifdef HAVE_STRERROR -# define STRERROR(x) strerror(x) -#else -# define STRERROR(x) "" -#endif - -#define noDEBUG - -#ifdef __OSE__ -#define PIPE_DIR "/pipe/" -#else -#define PIPE_DIR "/tmp/" -#endif -#define PIPE_STUBNAME "erlang.pipe" -#define PIPE_STUBLEN strlen(PIPE_STUBNAME) - -#ifdef DEBUG -#define STATUS(s) { fprintf(stderr, (s)); fflush(stderr); } -#else -#define STATUS(s) -#endif - -#ifndef FILENAME_MAX -#define FILENAME_MAX 250 -#endif - -static int tty_eof = 0; -static int protocol_ver = RUN_ERL_LO_VER; /* assume lowest to begin with */ - -static int write_all(int fd, const char* buf, int len); -static int version_handshake(char* buf, int len, int wfd); - - -#ifdef __OSE__ - -#define SET_AIO(REQ,FD,SIZE,BUFF) \ - /* Make sure to clean data structure of previous request */ \ - memset(&(REQ),0,sizeof(REQ)); \ - (REQ).aio_fildes = FD; \ - (REQ).aio_offset = FM_POSITION_CURRENT; \ - (REQ).aio_nbytes = SIZE; \ - (REQ).aio_buf = BUFF; \ - (REQ).aio_sigevent.sigev_notify = SIGEV_NONE - -#define READ_AIO(REQ,FD,SIZE,BUFF) \ - SET_AIO(REQ,FD,SIZE,BUFF); \ - if (aio_read(&(REQ)) != 0) \ - fprintf(stderr,"aio_read of child_read_req(%d) failed" \ - "with error %d\n",FD,errno) - -union SIGNAL { - SIGSELECT signo; - struct FmReadPtr fm_read_ptr; -}; - -#else /* __UNIX__ */ -static int recv_sig = 0; -static struct termios tty_smode, tty_rmode; -static int window_size_seq(char* buf, size_t bufsz); -#ifdef DEBUG -static void show_terminal_settings(struct termios *); -#endif - -static void handle_ctrlc(int sig) -{ - /* Reinstall the handler, and signal break flag */ - signal(SIGINT,handle_ctrlc); - recv_sig = SIGINT; -} - -static void handle_sigwinch(int sig) -{ - recv_sig = SIGWINCH; -} -#endif - -static void usage(char *pname) -{ - fprintf(stderr, "Usage: "); - fprintf(stderr,TO_ERL_USAGE,pname); -} - -int to_erl(int argc, char **argv) -{ - char FIFO1[FILENAME_MAX], FIFO2[FILENAME_MAX]; - int i, len, wfd, rfd; - char pipename[FILENAME_MAX]; - int pipeIx = 1; - int force_lock = 0; - int got_some = 0; - -#ifdef __OSE__ - struct aiocb stdin_read_req, pipe_read_req; - FmHandle stdin_fh, pipe_fh; - char *stdin_buf, *pipe_buf; - char *buf; - union SIGNAL *sig; -#else /* __UNIX__ */ - char buf[BUFSIZ]; - fd_set readfds; -#endif - - if (argc >= 2 && argv[1][0]=='-') { - switch (argv[1][1]) { - case 'h': - usage(argv[0]); - exit(1); - case 'F': - force_lock = 1; - break; - default: - fprintf(stderr,"Invalid option '%s'\n",argv[1]); - exit(1); - } - pipeIx = 2; - } - -#ifdef DEBUG - fprintf(stderr, "%s: pid is : %d\n", argv[0],(int) -#ifdef __OSE__ - current_process() -#else /* __UNIX__ */ - getpid() -#endif - ); -#endif - - strn_cpy(pipename, sizeof(pipename), - (argv[pipeIx] ? argv[pipeIx] : PIPE_DIR)); - - if(*pipename && pipename[strlen(pipename)-1] == '/') { - /* The user wishes us to find a pipe name in the specified */ - /* directory */ - int highest_pipe_num = 0; - DIR *dirp; - struct dirent *direntp; - - dirp = opendir(pipename); - if(!dirp) { - fprintf(stderr, "Can't access pipe directory %s: %s\n", pipename, strerror(errno)); - exit(1); - } - - /* Check the directory for existing pipes */ - - while((direntp=readdir(dirp)) != NULL) { - if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) { - int num = atoi(direntp->d_name+PIPE_STUBLEN+1); - if(num > highest_pipe_num) - highest_pipe_num = num; - } - } - closedir(dirp); - strn_catf(pipename, sizeof(pipename), (highest_pipe_num?"%s.%d":"%s"), - PIPE_STUBNAME, highest_pipe_num); - } /* if */ - - /* read FIFO */ - sn_printf(FIFO1,sizeof(FIFO1),"%s.r",pipename); - /* write FIFO */ - sn_printf(FIFO2,sizeof(FIFO2),"%s.w",pipename); - -#ifndef __OSE__ - /* Check that nobody is running to_erl on this pipe already */ - if ((wfd = open (FIFO1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) { - /* Open as server succeeded -- to_erl is already running! */ - close(wfd); - fprintf(stderr, "Another to_erl process already attached to pipe " - "%s.\n", pipename); - if (force_lock) { - fprintf(stderr, "But we proceed anyway by force (-F).\n"); - } - else { - exit(1); - } - } -#endif - - if ((rfd = open (FIFO1, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) { -#ifdef DEBUG - fprintf(stderr, "Could not open FIFO %s for reading.\n", FIFO1); -#endif - fprintf(stderr, "No running Erlang on pipe %s: %s\n", pipename, strerror(errno)); - exit(1); - } -#ifdef DEBUG - fprintf(stderr, "to_erl: %s opened for reading\n", FIFO1); -#endif - - if ((wfd = open (FIFO2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) { -#ifdef DEBUG - fprintf(stderr, "Could not open FIFO %s for writing.\n", FIFO2); -#endif - fprintf(stderr, "No running Erlang on pipe %s: %s\n", pipename, strerror(errno)); - close(rfd); - exit(1); - } -#ifdef DEBUG - fprintf(stderr, "to_erl: %s opened for writing\n", FIFO2); -#endif - -#ifndef __OSE__ - fprintf(stderr, "Attaching to %s (^D to exit)\n\n", pipename); -#else - fprintf(stderr, "Attaching to %s (^C to exit)\n\n", pipename); -#endif - -#ifndef __OSE__ - /* Set break handler to our handler */ - signal(SIGINT,handle_ctrlc); - - /* - * Save the current state of the terminal, and set raw mode. - */ - if (tcgetattr(0, &tty_rmode) , 0) { - fprintf(stderr, "Cannot get terminals current mode\n"); - exit(-1); - } - tty_smode = tty_rmode; - tty_eof = '\004'; /* Ctrl+D to exit */ -#ifdef DEBUG - show_terminal_settings(&tty_rmode); -#endif - tty_smode.c_iflag = - 1*BRKINT |/*Signal interrupt on break.*/ - 1*IGNPAR |/*Ignore characters with parity errors.*/ - 1*ISTRIP |/*Strip character.*/ - 0; - -#if 0 -0*IGNBRK |/*Ignore break condition.*/ -0*PARMRK |/*Mark parity errors.*/ -0*INPCK |/*Enable input parity check.*/ -0*INLCR |/*Map NL to CR on input.*/ -0*IGNCR |/*Ignore CR.*/ -0*ICRNL |/*Map CR to NL on input.*/ -0*IUCLC |/*Map upper-case to lower-case on input.*/ -0*IXON |/*Enable start/stop output control.*/ -0*IXANY |/*Enable any character to restart output.*/ -0*IXOFF |/*Enable start/stop input control.*/ -0*IMAXBEL|/*Echo BEL on input line too long.*/ -#endif - - tty_smode.c_oflag = - 1*OPOST |/*Post-process output.*/ - 1*ONLCR |/*Map NL to CR-NL on output.*/ -#ifdef XTABS - 1*XTABS |/*Expand tabs to spaces. (Linux)*/ -#endif -#ifdef OXTABS - 1*OXTABS |/*Expand tabs to spaces. (FreeBSD)*/ -#endif -#ifdef NL0 - 1*NL0 |/*Select newline delays*/ -#endif -#ifdef CR0 - 1*CR0 |/*Select carriage-return delays*/ -#endif -#ifdef TAB0 - 1*TAB0 |/*Select horizontal tab delays*/ -#endif -#ifdef BS0 - 1*BS0 |/*Select backspace delays*/ -#endif -#ifdef VT0 - 1*VT0 |/*Select vertical tab delays*/ -#endif -#ifdef FF0 - 1*FF0 |/*Select form feed delays*/ -#endif - 0; - -#if 0 -0*OLCUC |/*Map lower case to upper on output.*/ -0*OCRNL |/*Map CR to NL on output.*/ -0*ONOCR |/*No CR output at column 0.*/ -0*ONLRET |/*NL performs CR function.*/ -0*OFILL |/*Use fill characters for delay.*/ -0*OFDEL |/*Fill is DEL, else NULL.*/ -0*NL1 | -0*CR1 | -0*CR2 | -0*CR3 | -0*TAB1 | -0*TAB2 | -0*TAB3 |/*Expand tabs to spaces.*/ -0*BS1 | -0*VT1 | -0*FF1 | -#endif - - /* JALI: removed setting the tty_smode.c_cflag flags, since this is not */ - /* advisable if this is a *real* terminal, such as the console. In fact */ - /* this may hang the entire machine, deep, deep down (signalling break */ - /* or toggling the abort switch doesn't help) */ - - tty_smode.c_lflag = - 0; - -#if 0 -0*ISIG |/*Enable signals.*/ -0*ICANON |/*Canonical input (erase and kill processing).*/ -0*XCASE |/*Canonical upper/lower presentation.*/ -0*ECHO |/*Enable echo.*/ -0*ECHOE |/*Echo erase character as BS-SP-BS.*/ -0*ECHOK |/*Echo NL after kill character.*/ -0*ECHONL |/*Echo NL.*/ -0*NOFLSH |/*Disable flush after interrupt or quit.*/ -0*TOSTOP |/*Send SIGTTOU for background output.*/ -0*ECHOCTL|/*Echo control characters as ^char, delete as ^?.*/ -0*ECHOPRT|/*Echo erase character as character erased.*/ -0*ECHOKE |/*BS-SP-BS erase entire line on line kill.*/ -0*FLUSHO |/*Output is being flushed.*/ -0*PENDIN |/*Retype pending input at next read or input character.*/ -0*IEXTEN |/*Enable extended (implementation-defined) functions.*/ -#endif - - tty_smode.c_cc[VMIN] =0;/* Note that VMIN is the same as VEOF! */ - tty_smode.c_cc[VTIME] =0;/* Note that VTIME is the same as VEOL! */ - tty_smode.c_cc[VINTR] =3; - - tcsetattr(0, TCSADRAIN, &tty_smode); - -#ifdef DEBUG - show_terminal_settings(&tty_smode); -#endif - -#endif /* !__OSE__ */ - /* - * "Write a ^L to the FIFO which causes the other end to redisplay - * the input line." - * This does not seem to work as was intended in old comment above. - * However, this control character is now (R12B-3) used by run_erl - * to trigger the version handshaking between to_erl and run_erl - * at the start of every new to_erl-session. - */ - - if (write(wfd, "\014", 1) < 0) { - fprintf(stderr, "Error in writing ^L to FIFO.\n"); - } - -#ifdef __OSE__ - /* we have a tiny stack so we malloc the buffers */ - stdin_buf = malloc(sizeof(char) * BUFSIZ); - pipe_buf = malloc(sizeof(char) * BUFSIZ); - - efs_examine_fd(rfd,FLIB_FD_HANDLE,&pipe_fh); - efs_examine_fd(0,FLIB_FD_HANDLE,&stdin_fh); - READ_AIO(stdin_read_req,0,BUFSIZ,stdin_buf); - READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_buf); -#endif - - /* - * read and write - */ - while (1) { -#ifndef __OSE__ - FD_ZERO(&readfds); - FD_SET(0, &readfds); - FD_SET(rfd, &readfds); - if (select(rfd + 1, &readfds, NULL, NULL, NULL) < 0) { - if (recv_sig) { - FD_ZERO(&readfds); - } - else { - fprintf(stderr, "Error in select.\n"); - break; - } - } - len = 0; - - /* - * Read from terminal and write to FIFO - */ - if (recv_sig) { - switch (recv_sig) { - case SIGINT: - fprintf(stderr, "[Break]\n\r"); - buf[0] = '\003'; - len = 1; - break; - case SIGWINCH: - len = window_size_seq(buf,sizeof(buf)); - break; - default: - fprintf(stderr,"Unexpected signal: %u\n",recv_sig); - } - recv_sig = 0; - } - else -#else /* __OSE__ */ - SIGSELECT sigsel[] = {0}; - sig = receive(sigsel); - len = 0; -#endif -#ifndef __OSE__ - if (FD_ISSET(0,&readfds)) { - len = read(0, buf, sizeof(buf)); -#else /* __OSE__ */ - if (sig->signo == FM_READ_PTR_REPLY && - sig->fm_read_ptr.handle == stdin_fh) { - len = sig->fm_read_ptr.status == EFS_SUCCESS ? sig->fm_read_ptr.actual : -1; - buf = sig->fm_read_ptr.buffer; -#endif - if (len <= 0) { - close(rfd); - close(wfd); - if (len < 0) { - fprintf(stderr, "Error in reading from stdin.\n"); - } else { - fprintf(stderr, "[EOF]\n\r"); - } - break; - } - /* check if there is an eof character in input */ - for (i = 0; i < len-1 && buf[i] != tty_eof; i++); - if (buf[i] == tty_eof) { - fprintf(stderr, "[Quit]\n\r"); - break; - } - } - - if (len) { -#ifdef DEBUG - if(write(1, buf, len)); -#endif - if (write_all(wfd, buf, len) != len) { - fprintf(stderr, "Error in writing to FIFO.\n"); - close(rfd); - close(wfd); - break; - } - STATUS("\" OK\r\n"); -#ifdef __OSE__ - aio_dispatch(sig); - READ_AIO(stdin_read_req, 0, BUFSIZ, stdin_buf); -#endif - } - - /* - * Read from FIFO, write to terminal. - */ -#ifndef __OSE__ - if (FD_ISSET(rfd, &readfds)) { - STATUS("FIFO read: "); - len = read(rfd, buf, BUFSIZ); -#else /* __OSE__ */ - if (sig->signo == FM_READ_PTR_REPLY && - sig->fm_read_ptr.handle == pipe_fh) { - len = sig->fm_read_ptr.status == EFS_SUCCESS ? sig->fm_read_ptr.actual : -1; - buf = sig->fm_read_ptr.buffer; -#endif - if (len < 0 && errno == EAGAIN) { - /* - * No data this time, but the writing end of the FIFO is still open. - * Do nothing. - */ - ; - } else if (len <= 0) { - /* - * Either an error or end of file. In either case, break out - * of the loop. - */ - close(rfd); - close(wfd); - if (len < 0) { - fprintf(stderr, "Error in reading from FIFO.\n"); - } else - fprintf(stderr, "[End]\n\r"); - break; - } else { - if (!got_some) { - if ((len=version_handshake(buf,len,wfd)) < 0) { - close(rfd); - close(wfd); - break; - } -#ifndef __OSE__ - if (protocol_ver >= 1) { - /* Tell run_erl size of terminal window */ - signal(SIGWINCH, handle_sigwinch); - raise(SIGWINCH); - } -#endif - got_some = 1; - } - - /* - * We successfully read at least one character. Write what we got. - */ - STATUS("Terminal write: \""); - if (write_all(1, buf, len) != len) { - fprintf(stderr, "Error in writing to terminal.\n"); - close(rfd); - close(wfd); - break; - } - STATUS("\" OK\r\n"); -#ifdef __OSE__ - aio_dispatch(sig); - READ_AIO(pipe_read_req, rfd, BUFSIZ, pipe_buf); -#endif - } - } - } - -#ifndef __OSE__ - /* - * Reset terminal characterstics - * XXX - */ - tcsetattr(0, TCSADRAIN, &tty_rmode); -#endif - return 0; -} - -/* Call write() until entire buffer has been written or error. - * Return len or -1. - */ -static int write_all(int fd, const char* buf, int len) -{ - int left = len; - int written; - while (left) { - written = write(fd,buf,left); - if (written < 0) { - return -1; - } - left -= written; - buf += written; - } - return len; -} - -#ifndef __OSE__ -static int window_size_seq(char* buf, size_t bufsz) -{ -#ifdef TIOCGWINSZ - struct winsize ws; - static const char prefix[] = "\033_"; - static const char suffix[] = "\033\\"; - /* This Esc sequence is called "Application Program Command" - and seems suitable to use for our own customized stuff. */ - - if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) { - int len = sn_printf(buf, bufsz, "%swinsize=%u,%u%s", - prefix, ws.ws_col, ws.ws_row, suffix); - return len; - } -#endif /* TIOCGWINSZ */ - return 0; -} -#endif /* !__OSE__ */ - -/* to_erl run_erl - * | | - * |---------- '\014' -------->| (session start) - * | | - * |<---- "[run_erl v1-0]" ----| (version interval) - * | | - * |--- Esc_"version=1"Esc\ -->| (common version) - * | | - */ -static int version_handshake(char* buf, int len, int wfd) -{ - unsigned re_high=0, re_low; - char *end = find_str(buf,len,"]\n"); - - if (end && sscanf(buf,"[run_erl v%u-%u",&re_high,&re_low)==2) { - char wbuf[30]; - int wlen; - - if (re_low > RUN_ERL_HI_VER || re_high < RUN_ERL_LO_VER) { - fprintf(stderr,"Incompatible versions: to_erl=v%u-%u run_erl=v%u-%u\n", - RUN_ERL_HI_VER, RUN_ERL_LO_VER, re_high, re_low); - return -1; - } - /* Choose highest common version */ - protocol_ver = re_high < RUN_ERL_HI_VER ? re_high : RUN_ERL_HI_VER; - - wlen = sn_printf(wbuf, sizeof(wbuf), "\033_version=%u\033\\", - protocol_ver); - if (write_all(wfd, wbuf, wlen) < 0) { - fprintf(stderr,"Failed to send version handshake\n"); - return -1; - } - end += 2; - len -= (end-buf); - memmove(buf,end,len); - - } - else { /* we assume old run_erl without version handshake */ - protocol_ver = 0; - } - - if (re_high != RUN_ERL_HI_VER) { - fprintf(stderr,"run_erl has different version, " - "using common protocol level %u\n", protocol_ver); - } - - return len; -} - - -#if defined(DEBUG) && !defined(__OSE__) -#define S(x) ((x) > 0 ? 1 : 0) - -static void show_terminal_settings(struct termios *t) -{ - fprintf(stderr,"c_iflag:\n"); - fprintf(stderr,"Signal interrupt on break: BRKINT %d\n", S(t->c_iflag & BRKINT)); - fprintf(stderr,"Map CR to NL on input: ICRNL %d\n", S(t->c_iflag & ICRNL)); - fprintf(stderr,"Ignore break condition: IGNBRK %d\n", S(t->c_iflag & IGNBRK)); - fprintf(stderr,"Ignore CR: IGNCR %d\n", S(t->c_iflag & IGNCR)); - fprintf(stderr,"Ignore char with par. err's: IGNPAR %d\n", S(t->c_iflag & IGNPAR)); - fprintf(stderr,"Map NL to CR on input: INLCR %d\n", S(t->c_iflag & INLCR)); - fprintf(stderr,"Enable input parity check: INPCK %d\n", S(t->c_iflag & INPCK)); - fprintf(stderr,"Strip character ISTRIP %d\n", S(t->c_iflag & ISTRIP)); - fprintf(stderr,"Enable start/stop input ctrl IXOFF %d\n", S(t->c_iflag & IXOFF)); - fprintf(stderr,"ditto output ctrl IXON %d\n", S(t->c_iflag & IXON)); - fprintf(stderr,"Mark parity errors PARMRK %d\n", S(t->c_iflag & PARMRK)); - fprintf(stderr,"\n"); - fprintf(stderr,"c_oflag:\n"); - fprintf(stderr,"Perform output processing OPOST %d\n", S(t->c_oflag & OPOST)); - fprintf(stderr,"\n"); - fprintf(stderr,"c_cflag:\n"); - fprintf(stderr,"Ignore modem status lines CLOCAL %d\n", S(t->c_cflag & CLOCAL)); - fprintf(stderr,"\n"); - fprintf(stderr,"c_local:\n"); - fprintf(stderr,"Enable echo ECHO %d\n", S(t->c_lflag & ECHO)); - fprintf(stderr,"\n"); - fprintf(stderr,"c_cc:\n"); - fprintf(stderr,"c_cc[VEOF] %d\n", t->c_cc[VEOF]); -} -#endif /* DEBUG && !__OSE__ */ diff --git a/erts/etc/common/to_erl_common.h b/erts/etc/common/to_erl_common.h deleted file mode 100644 index a139da418f..0000000000 --- a/erts/etc/common/to_erl_common.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2013. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef ERL_TO_ERL_H -#define ERL_TO_ERL_H - -#define TO_ERL_USAGE "to_erl [-h|-F] %s\n" \ - "\t-h\tThis help text.\n" \ - "\t-f\tForce connection even though pipe is locked by other to_erl process." - -int to_erl(int argc, char **argv); - -#endif diff --git a/erts/etc/common/typer.c b/erts/etc/common/typer.c index 0aa0996808..6bae9f96b7 100644 --- a/erts/etc/common/typer.c +++ b/erts/etc/common/typer.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2006-2011. All Rights Reserved. + * Copyright Ericsson AB 2006-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,13 +63,17 @@ static int eargc; /* Number of arguments in eargv. */ */ static void error(char* format, ...); -static char* emalloc(size_t size); +static void* emalloc(size_t size); +#ifdef HAVE_COPYING_PUTENV +static void efree(void *p); +#endif static char* strsave(char* string); static void push_words(char* src); static int run_erlang(char* name, char** argv); static char* get_default_emulator(char* progname); #ifdef __WIN32__ static char* possibly_quote(char* arg); +static void* erealloc(void *p, size_t size); #endif /* @@ -100,6 +104,29 @@ char *strerror(int errnum) } #endif /* !HAVE_STRERROR */ +static void +set_env(char *key, char *value) +{ +#ifdef __WIN32__ + WCHAR wkey[MAXPATHLEN]; + WCHAR wvalue[MAXPATHLEN]; + MultiByteToWideChar(CP_UTF8, 0, key, -1, wkey, MAXPATHLEN); + MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, MAXPATHLEN); + if (!SetEnvironmentVariableW(wkey, wvalue)) + error("SetEnvironmentVariable(\"%s\", \"%s\") failed!", key, value); +#else + size_t size = strlen(key) + 1 + strlen(value) + 1; + char *str = emalloc(size); + sprintf(str, "%s=%s", key, value); + if (putenv(str) != 0) + error("putenv(\"%s\") failed!", str); +#ifdef HAVE_COPYING_PUTENV + efree(str); +#endif +#endif +} + + #ifdef __WIN32__ int wmain(int argc, wchar_t **wcargv) { @@ -118,16 +145,20 @@ main(int argc, char** argv) int i; int len; /* Convert argv to utf8 */ - argv = malloc((argc+1) * sizeof(char*)); + argv = emalloc((argc+1) * sizeof(char*)); for (i=0; i<argc; i++) { len = WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, NULL, 0, NULL, NULL); - argv[i] = malloc(len*sizeof(char)); + argv[i] = emalloc(len*sizeof(char)); WideCharToMultiByte(CP_UTF8, 0, wcargv[i], -1, argv[i], len, NULL, NULL); } argv[argc] = NULL; #endif emulator = get_default_emulator(argv[0]); + /* + * Add scriptname to env + */ + set_env("ESCRIPT_NAME", argv[0]); /* * Allocate the argv vector to be used for arguments to Erlang. @@ -232,7 +263,7 @@ wchar_t *make_commandline(char **argv) buff = (wchar_t *) emalloc(siz*sizeof(wchar_t)); } else if (siz < num) { siz = num; - buff = (wchar_t *) realloc(buff,siz*sizeof(wchar_t)); + buff = (wchar_t *) erealloc(buff,siz*sizeof(wchar_t)); } p = buff; num=0; @@ -332,15 +363,34 @@ error(char* format, ...) exit(1); } -static char* +static void* emalloc(size_t size) { - char *p = malloc(size); + void *p = malloc(size); if (p == NULL) error("Insufficient memory"); return p; } +#ifdef __WIN32__ +static void * +erealloc(void *p, size_t size) +{ + void *res = realloc(p, size); + if (res == NULL) + error("Insufficient memory"); + return res; +} +#endif + +#ifdef HAVE_COPYING_PUTENV +static void +efree(void *p) +{ + free(p); +} +#endif + static char* strsave(char* string) { |