aboutsummaryrefslogtreecommitdiffstats
path: root/erts/etc
diff options
context:
space:
mode:
Diffstat (limited to 'erts/etc')
-rw-r--r--erts/etc/common/Makefile.in30
-rw-r--r--erts/etc/common/ct_run.c545
-rw-r--r--erts/etc/common/dialyzer.c12
-rw-r--r--erts/etc/common/erlc.c118
-rw-r--r--erts/etc/common/erlexec.c112
-rw-r--r--erts/etc/common/escript.c52
-rw-r--r--erts/etc/common/heart.c15
-rw-r--r--erts/etc/common/inet_gethost.c25
-rw-r--r--erts/etc/common/typer.c9
-rw-r--r--erts/etc/unix/Install.src4
-rw-r--r--erts/etc/unix/cerl.src101
-rw-r--r--erts/etc/unix/format_man_pages31
-rw-r--r--erts/etc/unix/run_erl.c111
-rw-r--r--erts/etc/unix/to_erl.c10
-rw-r--r--erts/etc/win32/Install.c31
-rwxr-xr-xerts/etc/win32/cygwin_tools/vc/ld.sh10
-rwxr-xr-xerts/etc/win32/cygwin_tools/vc/rc.sh12
-rw-r--r--erts/etc/win32/erlsrv/erlsrv_interactive.c191
-rw-r--r--erts/etc/win32/erlsrv/erlsrv_interactive.h4
-rw-r--r--erts/etc/win32/erlsrv/erlsrv_service.c6
-rw-r--r--erts/etc/win32/nsis/Makefile4
-rwxr-xr-xerts/etc/win32/nsis/dll_version_helper.sh83
-rw-r--r--erts/etc/win32/nsis/erlang20.nsi10
-rwxr-xr-xerts/etc/win32/nsis/find_redist.sh89
-rw-r--r--erts/etc/win32/start_erl.c161
25 files changed, 1409 insertions, 367 deletions
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index 3db4fcba61..4754328c0b 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -96,9 +96,9 @@ endif
# On windows we always need reentrant libraries.
ifeq ($(TARGET),win32)
-ERLEXEC_XLIBS=-L../../lib/internal/$(TARGET) -lerts_internal_r$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
+ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal_r$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
else
-ERLEXEC_XLIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@
+ERTS_INTERNAL_LIBS=-L../../lib/internal/$(TARGET) -lerts_internal$(ERTS_LIB_TYPEMARKER) @ERTS_INTERNAL_X_LIBS@ -lm
endif
# ----------------------------------------------------
@@ -178,7 +178,7 @@ MC_OUTPUTS= \
MT_FLAG="-MD"
endif
INET_GETHOST = $(BINDIR)/inet_gethost.exe
-INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer.exe $(BINDIR)/dialyzer.exe $(BINDIR)/erlc.exe $(BINDIR)/start_erl.exe $(BINDIR)/escript.exe
+INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer.exe $(BINDIR)/dialyzer.exe $(BINDIR)/erlc.exe $(BINDIR)/start_erl.exe $(BINDIR)/escript.exe $(BINDIR)/ct_run.exe
INSTALL_SRC = $(WINETC)/start_erl.c $(WINETC)/Nmakefile.start_erl
ERLEXECDIR=.
INSTALL_LIBS =
@@ -211,7 +211,7 @@ ERLSRV_OBJECTS=
MC_OUTPUTS=
INET_GETHOST = $(BINDIR)/inet_gethost@EXEEXT@
INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer@EXEEXT@ $(BINDIR)/dialyzer@EXEEXT@ \
- $(BINDIR)/erlc@EXEEXT@ $(BINDIR)/escript@EXEEXT@ \
+ $(BINDIR)/erlc@EXEEXT@ $(BINDIR)/escript@EXEEXT@ $(BINDIR)/ct_run@EXEEXT@ \
$(BINDIR)/run_erl $(BINDIR)/to_erl $(BINDIR)/dyn_erl
INSTALL_EMBEDDED_DATA = ../unix/start.src ../unix/start_erl.src
INSTALL_TOP = Install
@@ -274,6 +274,7 @@ endif
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)/typer.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
rm -f $(ERL_TOP)/erts/obj*/$(TARGET)/werl.o
@@ -295,7 +296,7 @@ $(OBJDIR)/inet_gethost.o: inet_gethost.c
$(CC) $(CFLAGS) -o $@ -c inet_gethost.c
$(BINDIR)/inet_gethost@EXEEXT@: $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ)
- $(PURIFY) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) $(ENTRY_LDFLAGS) -o $@ $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o
$(LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(LIBS)
@@ -320,35 +321,42 @@ $(OBJDIR)/safe_string.o: ../unix/safe_string.c
ifneq ($(TARGET),win32)
$(BINDIR)/$(ERLEXEC): $(OBJDIR)/$(ERLEXEC).o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/$(ERLEXEC).o $(ERLEXEC_XLIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/$(ERLEXEC).o $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/$(ERLEXEC).o: $(ERLEXECDIR)/$(ERLEXEC).c
$(CC) -I$(EMUDIR) $(CFLAGS) -o $@ -c $(ERLEXECDIR)/$(ERLEXEC).c
endif
$(BINDIR)/erlc@EXEEXT@: $(OBJDIR)/erlc.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erlc.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erlc.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/erlc.o: erlc.c
$(CC) $(CFLAGS) -o $@ -c erlc.c
$(BINDIR)/dialyzer@EXEEXT@: $(OBJDIR)/dialyzer.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/dialyzer.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/dialyzer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/dialyzer.o: dialyzer.c
$(CC) $(CFLAGS) -o $@ -c dialyzer.c
$(BINDIR)/typer@EXEEXT@: $(OBJDIR)/typer.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/typer.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/typer.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/typer.o: typer.c
$(CC) $(CFLAGS) -o $@ -c typer.c
$(BINDIR)/escript@EXEEXT@: $(OBJDIR)/escript.o
- $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/escript.o -L$(OBJDIR) $(LIBS)
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/escript.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
$(OBJDIR)/escript.o: escript.c
$(CC) $(CFLAGS) -o $@ -c escript.c
+$(BINDIR)/ct_run@EXEEXT@: $(OBJDIR)/ct_run.o
+ $(PURIFY) $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/ct_run.o -L$(OBJDIR) $(LIBS) $(ERTS_INTERNAL_LIBS)
+
+$(OBJDIR)/ct_run.o: ct_run.c
+ $(CC) $(CFLAGS) -o $@ -c ct_run.c
+
+
#------------------------------------------------------------------------
# Windows specific targets
# The windows platform is quite different from the others. erl/werl are small C programs
@@ -360,7 +368,7 @@ $(OBJDIR)/escript.o: escript.c
ifeq ($(TARGET),win32)
$(BINDIR)/$(ERLEXEC): $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ)
- $(LD) -dll $(LDFLAGS) -o $@ $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ) $(ERLEXEC_XLIBS)
+ $(LD) -dll $(LDFLAGS) -o $@ $(OBJDIR)/erlexec.o $(OBJDIR)/win_erlexec.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ) $(ERTS_INTERNAL_LIBS)
$(BINDIR)/erl@EXEEXT@: $(OBJDIR)/erl.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ)
$(LD) $(LDFLAGS) -o $@ $(OBJDIR)/erl.o $(OBJDIR)/init_file.o $(OBJDIR)/$(ERLRES_OBJ)
diff --git a/erts/etc/common/ct_run.c b/erts/etc/common/ct_run.c
new file mode 100644
index 0000000000..7aaab716f7
--- /dev/null
+++ b/erts/etc/common/ct_run.c
@@ -0,0 +1,545 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2010. All Rights Reserved.
+ *
+ * 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 online 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.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * Purpose: Common Test front-end.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "sys.h"
+#ifdef __WIN32__
+#include <winbase.h>
+#endif
+
+#include <ctype.h>
+
+#define NO 0
+#define YES 1
+
+#define ASIZE(a) (sizeof(a)/sizeof(a[0]))
+
+static int debug = 0; /* Bit flags for debug printouts. */
+
+static char** eargv_base; /* Base of vector. */
+static char** eargv; /* First argument for erl. */
+
+static int eargc; /* Number of arguments in eargv. */
+
+#ifdef __WIN32__
+# define QUOTE(s) possibly_quote(s)
+# define IS_DIRSEP(c) ((c) == '/' || (c) == '\\')
+# define ERL_NAME "erl.exe"
+#else
+# define QUOTE(s) s
+# define IS_DIRSEP(c) ((c) == '/')
+# define ERL_NAME "erl"
+#endif
+
+#define UNSHIFT(s) eargc++, eargv--; eargv[0] = QUOTE(s)
+#define PUSH(s) eargv[eargc++] = QUOTE(s)
+#define PUSH2(s, t) PUSH(s); PUSH(t)
+#define PUSH3(s, t, u) PUSH2(s, t); PUSH(u)
+#define PUSH4(s, t, u, v) PUSH2(s, t); PUSH2(u, v)
+
+/*
+ * The possible modes to start Common Test
+ */
+
+#define NORMAL_MODE 0
+#define VTS_MODE 1
+#define CT_SHELL_MODE 2
+#define MASTER_MODE 3
+#define ERL_SHELL_MODE 4
+
+/*
+ * Distribution
+ */
+
+#define SHORT_NAME 0
+#define FULL_NAME 1
+
+/*
+ * Local functions.
+ */
+
+static void error(char* format, ...);
+static char* emalloc(size_t size);
+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);
+static void print_deprecation_warning(char *progname);
+#ifdef __WIN32__
+static char* possibly_quote(char* arg);
+#endif
+
+/*
+ * Supply a strerror() function if libc doesn't.
+ */
+#ifndef HAVE_STRERROR
+
+extern int sys_nerr;
+
+#ifndef SYS_ERRLIST_DECLARED
+extern const char * const sys_errlist[];
+#endif /* !SYS_ERRLIST_DECLARED */
+
+char *strerror(int errnum)
+{
+ static char *emsg[1024];
+
+ if (errnum != 0) {
+ if (errnum > 0 && errnum < sys_nerr)
+ sprintf((char *) &emsg[0], "(%s)", sys_errlist[errnum]);
+ else
+ sprintf((char *) &emsg[0], "errnum = %d ", errnum);
+ }
+ else {
+ emsg[0] = '\0';
+ }
+ return (char *) &emsg[0];
+}
+#endif /* !HAVE_STRERROR */
+
+int
+main(int argc, char** argv)
+{
+ int eargv_size;
+ int eargc_base; /* How many arguments in the base of eargv. */
+ char* emulator;
+ char nodename[100];
+ char browser[100];
+ int ct_mode;
+ int dist_mode;
+ int cnt;
+ int erl_args;
+ char** argv0 = argv;
+
+ print_deprecation_warning(argv[0]);
+
+ emulator = get_default_emulator(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.
+ */
+
+ eargv_size = argc*4+100;
+ 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;
+
+ strcpy(nodename, "ct");
+ dist_mode = SHORT_NAME;
+ browser[0] = '\0';
+ ct_mode = NORMAL_MODE;
+ erl_args = argc;
+ cnt = 1;
+
+ /*
+ * Check various flags before building command line
+ */
+
+ while (cnt < argc) {
+ if (strcmp(argv[1], "-erl_args") == 0) {
+ erl_args = cnt;
+ }
+ else if (strcmp(argv[1], "-sname") == 0) {
+ strncpy(nodename, argv[2], sizeof(nodename));
+ nodename[sizeof(nodename)-1] = '\0';
+ cnt++, argv++;
+ }
+ else if (strcmp(argv[1], "-name") == 0) {
+ strncpy(nodename, argv[2], sizeof(nodename));
+ nodename[sizeof(nodename)-1] = '\0';
+ dist_mode = FULL_NAME;
+ cnt++, argv++;
+ }
+ else {
+ if (cnt < erl_args) {
+ if (strcmp(argv[1], "-vts") == 0) {
+ ct_mode = VTS_MODE;
+ }
+ else if (strcmp(argv[1], "-browser") == 0) {
+ strncpy(browser, argv[2], sizeof(browser));
+ browser[sizeof(browser)-1] = '\0';
+ cnt++, argv++;
+ }
+ else if (strcmp(argv[1], "-shell") == 0) {
+ ct_mode = CT_SHELL_MODE;
+ }
+ else if (strcmp(argv[1], "-ctmaster") == 0) {
+ strcpy(nodename, "ct_master");
+ ct_mode = MASTER_MODE;
+ }
+ else if (strcmp(argv[1], "-ctname") == 0) {
+ strncpy(nodename, argv[2], sizeof(nodename));
+ nodename[sizeof(nodename)-1] = '\0';
+ ct_mode = ERL_SHELL_MODE;
+ cnt++, argv++;
+ }
+ }
+ }
+ cnt++, argv++;
+ }
+
+ argv = argv0;
+
+ /*
+ * Push initial arguments.
+ */
+
+ if (dist_mode == FULL_NAME) {
+ PUSH2("-name", nodename);
+ }
+ else {
+ PUSH2("-sname", nodename);
+ }
+
+ /*
+ * Push everything else
+ */
+
+ if (ct_mode == VTS_MODE) {
+ PUSH4("-s", "webtool", "script_start", "vts");
+ if (browser[0] != '\0') PUSH(browser);
+ PUSH3("-s", "ct_run", "script_start");
+ }
+ else if (ct_mode == CT_SHELL_MODE) {
+ PUSH3("-s", "ct_run", "script_start");
+ }
+ else if (ct_mode == NORMAL_MODE) {
+ PUSH3("-s", "ct_run", "script_start");
+ PUSH3("-s", "erlang", "halt");
+ }
+
+ cnt = 1;
+ while (cnt < argc) {
+ if (strcmp(argv[1], "-erl_args") == 0) {
+ PUSH("-ct_erl_args");
+ }
+ else if ((strcmp(argv[1], "-sname") == 0) || (strcmp(argv[1], "-name") == 0)) {
+ cnt++, argv++;
+ }
+ else if (cnt < erl_args) {
+ if (strcmp(argv[1], "-config") == 0)
+ PUSH("-ct_config");
+ else if (strcmp(argv[1], "-decrypt_key") == 0)
+ PUSH("-ct_decrypt_key");
+ else if (strcmp(argv[1], "-decrypt_file") == 0)
+ PUSH("-ct_decrypt_file");
+ else
+ PUSH(argv[1]);
+ }
+ else {
+ PUSH(argv[1]);
+ }
+ cnt++, argv++;
+ }
+
+ /*
+ * Move up the commands for invoking the emulator and adjust eargv
+ * accordingly.
+ */
+
+ while (--eargc_base >= 0) {
+ UNSHIFT(eargv_base[eargc_base]);
+ }
+
+ /*
+ * Invoke Erlang with the collected options.
+ */
+
+ PUSH(NULL);
+
+ return run_erlang(eargv[0], eargv);
+}
+
+static void
+push_words(char* src)
+{
+ char sbuf[MAXPATHLEN];
+ 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__
+char *make_commandline(char **argv)
+{
+ static char *buff = NULL;
+ static int siz = 0;
+ int num = 0;
+ char **arg, *p;
+
+ if (*argv == NULL) {
+ return "";
+ }
+ for (arg = argv; *arg != NULL; ++arg) {
+ num += strlen(*arg)+1;
+ }
+ if (!siz) {
+ siz = num;
+ buff = malloc(siz*sizeof(char));
+ } else if (siz < num) {
+ siz = num;
+ buff = realloc(buff,siz*sizeof(char));
+ }
+ p = buff;
+ for (arg = argv; *arg != NULL; ++arg) {
+ strcpy(p,*arg);
+ p+=strlen(*arg);
+ *p++=' ';
+ }
+ *(--p) = '\0';
+
+ if (debug) {
+ printf("Processed commandline:%s\n",buff);
+ }
+ return buff;
+}
+
+int my_spawnvp(char **argv)
+{
+ STARTUPINFO siStartInfo;
+ PROCESS_INFORMATION piProcInfo;
+ DWORD ec;
+
+ memset(&siStartInfo,0,sizeof(STARTUPINFO));
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.dwFlags = STARTF_USESTDHANDLES;
+ siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ siStartInfo.wShowWindow = SW_HIDE;
+ siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
+
+
+ if (!CreateProcess(NULL,
+ make_commandline(argv),
+ NULL,
+ NULL,
+ TRUE,
+ 0,
+ NULL,
+ NULL,
+ &siStartInfo,
+ &piProcInfo)) {
+ return -1;
+ }
+ CloseHandle(piProcInfo.hThread);
+
+ WaitForSingleObject(piProcInfo.hProcess,INFINITE);
+ if (!GetExitCodeProcess(piProcInfo.hProcess,&ec)) {
+ return 0;
+ }
+ return (int) ec;
+}
+#endif /* __WIN32__ */
+
+
+static int
+run_erlang(char* progname, char** argv)
+{
+#ifdef __WIN32__
+ int status;
+#endif
+
+ if (debug) {
+ int i = 0;
+ while (argv[i] != NULL)
+ printf(" %s", argv[i++]);
+ printf("\n");
+ }
+
+#ifdef __WIN32__
+ /*
+ * Alas, we must wait here for the program to finish.
+ * Otherwise, the shell from which we were executed will think
+ * we are finished and print a prompt and read keyboard input.
+ */
+
+ status = my_spawnvp(argv)/*_spawnvp(_P_WAIT,progname,argv)*/;
+ if (status == -1) {
+ fprintf(stderr, "ct_run: Error executing '%s': %d", progname,
+ GetLastError());
+ }
+ return status;
+#else
+ execvp(progname, argv);
+ error("Error %d executing \'%s\'.", errno, progname);
+ return 2;
+#endif
+}
+
+static void
+error(char* format, ...)
+{
+ char sbuf[1024];
+ va_list ap;
+
+ va_start(ap, format);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
+ va_end(ap);
+ fprintf(stderr, "ct_run: %s\n", sbuf);
+ exit(1);
+}
+
+static char*
+emalloc(size_t size)
+{
+ char *p = malloc(size);
+ if (p == NULL)
+ error("Insufficient memory");
+ return p;
+}
+
+static char*
+strsave(char* string)
+{
+ char* p = emalloc(strlen(string)+1);
+ strcpy(p, string);
+ return p;
+}
+
+/* Instead of making sure basename exists, we do our own */
+static char *simple_basename(char *path)
+{
+ char *ptr;
+ for (ptr = path; *ptr != '\0'; ++ptr) {
+ if (*ptr == '/' || *ptr == '\\') {
+ path = ptr + 1;
+ }
+ }
+ return path;
+}
+
+static void print_deprecation_warning(char* progpath)
+{
+ char *basename = simple_basename(progpath);
+ if(strcmp(basename,"run_test") == 0 ||
+ strcmp(basename, "run_test.exe") == 0) {
+ printf("---***---\nDeprecated: run_test is deprecated and will be removed in R16B,\n please use ct_run instead\n---***---\n");
+ }
+}
+
+static char*
+get_default_emulator(char* progname)
+{
+ char sbuf[MAXPATHLEN];
+ char* s;
+
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
+ strcpy(sbuf, progname);
+ for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
+ if (IS_DIRSEP(*s)) {
+ strcpy(s+1, ERL_NAME);
+#ifdef __WIN32__
+ if (_access(sbuf, 0) != -1) {
+ return strsave(sbuf);
+ }
+#else
+ if (access(sbuf, 1) != -1) {
+ return strsave(sbuf);
+ }
+#endif
+ break;
+ }
+ }
+ return ERL_NAME;
+}
+
+#ifdef __WIN32__
+static char*
+possibly_quote(char* arg)
+{
+ int mustQuote = NO;
+ int n = 0;
+ char* s;
+ char* narg;
+
+ if (arg == NULL) {
+ return arg;
+ }
+
+ /*
+ * Scan the string to find out if it needs quoting and return
+ * the original argument if not.
+ */
+
+ for (s = arg; *s; s++, n++) {
+ switch(*s) {
+ case ' ':
+ mustQuote = YES;
+ continue;
+ case '"':
+ mustQuote = YES;
+ n++;
+ continue;
+ case '\\':
+ if(s[1] == '"')
+ n++;
+ continue;
+ default:
+ continue;
+ }
+ }
+ if (!mustQuote) {
+ return arg;
+ }
+
+ /*
+ * Insert the quotes and put a backslash in front of every quote
+ * inside the string.
+ */
+
+ s = narg = emalloc(n+2+1);
+ for (*s++ = '"'; *arg; arg++, s++) {
+ if (*arg == '"' || (*arg == '\\' && arg[1] == '"')) {
+ *s++ = '\\';
+ }
+ *s = *arg;
+ }
+ if (s[-1] == '\\') {
+ *s++ ='\\';
+ }
+ *s++ = '"';
+ *s = '\0';
+ return narg;
+}
+#endif /* __WIN32__ */
diff --git a/erts/etc/common/dialyzer.c b/erts/etc/common/dialyzer.c
index 4b4c1124f1..04e9199ef3 100644
--- a/erts/etc/common/dialyzer.c
+++ b/erts/etc/common/dialyzer.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2011. All Rights Reserved.
*
* 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
@@ -147,6 +147,9 @@ main(int argc, char** argv)
env = get_env("DIALYZER_EMULATOR");
emulator = env ? env : get_default_emulator(argv[0]);
+ if (strlen(emulator) >= MAXPATHLEN)
+ error("Value of environment variable DIALYZER_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
@@ -228,7 +231,7 @@ main(int argc, char** argv)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[MAXPATHLEN];
char* dst;
dst = sbuf;
@@ -360,7 +363,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "dialyzer: %s\n", sbuf);
exit(1);
@@ -389,6 +392,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/common/erlc.c b/erts/etc/common/erlc.c
index 09aca19e6c..35c360a99d 100644
--- a/erts/etc/common/erlc.c
+++ b/erts/etc/common/erlc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2011. All Rights Reserved.
*
* 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
@@ -28,6 +28,7 @@
#include <winbase.h>
/* FIXE ME config_win32.h? */
#define HAVE_STRERROR 1
+#define snprintf _snprintf
#endif
#include <ctype.h>
@@ -148,10 +149,6 @@ int
main(int argc, char** argv)
{
char cwd[MAXPATHLEN]; /* Current working directory. */
- char** rpc_eargv; /* Pointer to the beginning of arguments
- * if calling a running Erlang system
- * via erl_rpc().
- */
int eargv_size;
int eargc_base; /* How many arguments in the base of eargv. */
char* emulator;
@@ -160,6 +157,9 @@ main(int argc, char** argv)
env = get_env("ERLC_EMULATOR");
emulator = env ? env : get_default_emulator(argv[0]);
+ if (strlen(emulator) >= MAXPATHLEN)
+ error("Value of environment variable ERLC_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
@@ -170,7 +170,7 @@ main(int argc, char** argv)
* base of the eargv vector, and move it up later.
*/
- eargv_size = argc*4+100;
+ eargv_size = argc*6+100;
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
@@ -189,7 +189,6 @@ main(int argc, char** argv)
PUSH2("-mode", "minimal");
PUSH2("-boot", "start_clean");
PUSH3("-s", "erl_compile", "compile_cmdline");
- rpc_eargv = eargv+eargc;
/*
* Push standard arguments to Erlang.
@@ -262,6 +261,95 @@ main(int argc, char** argv)
case 'I':
PUSH2("@i", process_opt(&argc, &argv, 0));
break;
+ case 'M':
+ {
+ char *buf, *key, *val;
+ size_t buf_len;
+
+ if (argv[1][2] == '\0') { /* -M */
+ /* Push the following options:
+ * o 'makedep'
+ * o {makedep_output, standard_io}
+ */
+ buf = strsave("makedep");
+ PUSH2("@option", buf);
+
+ key = "makedep_output";
+ val = "standard_io";
+ buf_len = 1 + strlen(key) + 1 + strlen(val) + 1 + 1;
+ buf = emalloc(buf_len);
+ snprintf(buf, buf_len, "{%s,%s}", key, val);
+ PUSH2("@option", buf);
+ } else if (argv[1][3] == '\0') {
+ switch(argv[1][2]) {
+ case 'D': /* -MD */
+ /* Push the following options:
+ * o 'makedep'
+ */
+ buf = strsave("makedep");
+ PUSH2("@option", buf);
+ break;
+ case 'F': /* -MF <file> */
+ /* Push the following options:
+ * o 'makedep'
+ * o {makedep_output, <file>}
+ */
+ buf = strsave("makedep");
+ PUSH2("@option", buf);
+
+ key = "makedep_output";
+ val = process_opt(&argc, &argv, 1);
+ buf_len = 1 + strlen(key) + 2 + strlen(val) + 2 + 1;
+ buf = emalloc(buf_len);
+ snprintf(buf, buf_len, "{%s,\"%s\"}", key, val);
+ PUSH2("@option", buf);
+ break;
+ case 'T': /* -MT <target> */
+ /* Push the following options:
+ * o {makedep_target, <target>}
+ */
+ key = "makedep_target";
+ val = process_opt(&argc, &argv, 1);
+ buf_len = 1 + strlen(key) + 2 + strlen(val) + 2 + 1;
+ buf = emalloc(buf_len);
+ snprintf(buf, buf_len, "{%s,\"%s\"}", key, val);
+ PUSH2("@option", buf);
+ break;
+ case 'Q': /* -MQ <target> */
+ /* Push the following options:
+ * o {makedep_target, <target>}
+ * o makedep_quote_target
+ */
+ key = "makedep_target";
+ val = process_opt(&argc, &argv, 1);
+ buf_len = 1 + strlen(key) + 2 + strlen(val) + 2 + 1;
+ buf = emalloc(buf_len);
+ snprintf(buf, buf_len, "{%s,\"%s\"}", key, val);
+ PUSH2("@option", buf);
+
+ buf = strsave("makedep_quote_target");
+ PUSH2("@option", buf);
+ break;
+ case 'G': /* -MG */
+ /* Push the following options:
+ * o makedep_add_missing
+ */
+ buf = strsave("makedep_add_missing");
+ PUSH2("@option", buf);
+ break;
+ case 'P': /* -MP */
+ /* Push the following options:
+ * o makedep_phony
+ */
+ buf = strsave("makedep_add_missing");
+ PUSH2("@option", buf);
+ break;
+ default:
+ goto error;
+ }
+ }
+ }
+ break;
case 'o':
PUSH2("@outdir", process_opt(&argc, &argv, 0));
break;
@@ -419,7 +507,7 @@ process_opt(int* pArgc, char*** pArgv, int offset)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[MAXPATHLEN];
char* dst;
dst = sbuf;
@@ -563,6 +651,15 @@ usage(void)
{"-hybrid", "compile using hybrid-heap emulator"},
{"-help", "shows this help text"},
{"-I path", "where to search for include files"},
+ {"-M", "generate a rule for make(1) describing the dependencies"},
+ {"-MF file", "write the dependencies to 'file'"},
+ {"-MT target", "change the target of the rule emitted by dependency "
+ "generation"},
+ {"-MQ target", "same as -MT but quote characters special to make(1)"},
+ {"-MG", "consider missing headers as generated files and add them to "
+ "the dependencies"},
+ {"-MP", "add a phony target for each dependency"},
+ {"-MD", "same as -M -MT file (with default 'file')"},
{"-o name", "name output directory or file"},
{"-pa path", "add path to the front of Erlang's code path"},
{"-pz path", "add path to the end of Erlang's code path"},
@@ -595,7 +692,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "erlc: %s\n", sbuf);
exit(1);
@@ -624,6 +721,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index f79f5cc978..2bd576d8e8 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* 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
@@ -64,6 +64,7 @@
static const char plusM_au_allocs[]= {
'u', /* all alloc_util allocators */
'B', /* binary_alloc */
+ 'C', /* sbmbc_alloc */
'D', /* std_alloc */
'E', /* ets_alloc */
'H', /* eheap_alloc */
@@ -93,6 +94,8 @@ static char *plusM_au_alloc_switches[] = {
"rsbcst",
"sbct",
"smbcs",
+ "sbmbcs",
+ "sbmbct",
NULL
};
@@ -120,6 +123,7 @@ static char *plusM_other_switches[] = {
static char *pluss_val_switches[] = {
"bt",
"ct",
+ "wt",
"ss",
NULL
};
@@ -131,6 +135,18 @@ static char *plush_val_switches[] = {
NULL
};
+/* +r arguments with values */
+static char *plusr_val_switches[] = {
+ "g",
+ NULL
+};
+
+/* +z arguments with values */
+static char *plusz_val_switches[] = {
+ "dbbl",
+ NULL
+};
+
/*
* Define sleep(seconds) in terms of Sleep() on Windows.
@@ -302,7 +318,7 @@ free_env_val(char *value)
}
/*
- * Add the arcitecture suffix to the program name if needed,
+ * Add the architecture suffix to the program name if needed,
* except on Windows, where we insert it just before ".DLL".
*/
static char*
@@ -381,6 +397,7 @@ int main(int argc, char **argv)
int print_args_exit = 0;
int print_qouted_cmd_exit = 0;
erts_cpu_info_t *cpuinfo = NULL;
+ char* emu_name;
#ifdef __WIN32__
this_module_handle = module;
@@ -553,7 +570,8 @@ int main(int argc, char **argv)
usage("+MYm");
}
emu = add_extra_suffixes(emu, emu_type);
- sprintf(tmpStr, "%s" DIRSEP "%s" BINARY_EXT, bindir, 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! */
@@ -564,12 +582,12 @@ int main(int argc, char **argv)
s = get_env("PATH");
if (!s) {
- sprintf(tmpStr, "%s" PATHSEP "%s" DIRSEP "bin", bindir, rootdir);
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s" PATHSEP "%s" DIRSEP "bin", bindir, rootdir);
} else if (strstr(s, bindir) == NULL) {
- sprintf(tmpStr, "%s" PATHSEP "%s" DIRSEP "bin" PATHSEP "%s", bindir,
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s" PATHSEP "%s" DIRSEP "bin" PATHSEP "%s", bindir,
rootdir, s);
} else {
- sprintf(tmpStr, "%s", s);
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s", s);
}
free_env_val(s);
set_env("PATH", tmpStr);
@@ -669,6 +687,9 @@ int main(int argc, char **argv)
verbose = 1;
} else if (strcmp(argv[i], "-emu_args_exit") == 0) {
print_args_exit = 1;
+ } else if (strcmp(argv[i], "-emu_name_exit") == 0) {
+ printf("%s\n", emu_name);
+ exit(0);
} else if (strcmp(argv[i], "-emu_qouted_cmd_exit") == 0) {
print_qouted_cmd_exit = 1;
} else if (strcmp(argv[i], "-env") == 0) { /* -env VARNAME VARVALUE */
@@ -707,7 +728,7 @@ int main(int argc, char **argv)
error("-man not supported on Windows");
#else
argv[i] = "man";
- sprintf(tmpStr, "%s/man", rootdir);
+ erts_snprintf(tmpStr, sizeof(tmpStr), "%s/man", rootdir);
set_env("MANPATH", tmpStr);
execvp("man", argv+i);
error("Could not execute the 'man' command.");
@@ -872,6 +893,21 @@ int main(int argc, char **argv)
i++;
}
break;
+ case 'r':
+ if (!is_one_of_strings(&argv[i][2],
+ plusr_val_switches))
+ goto the_default;
+ else {
+ if (i+1 >= argc
+ || argv[i+1][0] == '-'
+ || argv[i+1][0] == '+')
+ usage(argv[i]);
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ }
+ break;
case 's':
if (!is_one_of_strings(&argv[i][2],
pluss_val_switches))
@@ -887,6 +923,20 @@ int main(int argc, char **argv)
i++;
}
break;
+ case 'z':
+ if (!is_one_of_strings(&argv[i][2], plusz_val_switches)) {
+ goto the_default;
+ } else {
+ if (i+1 >= argc
+ || argv[i+1][0] == '-'
+ || argv[i+1][0] == '+')
+ usage(argv[i]);
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ }
+ break;
default:
the_default:
argv[i][0] = '-'; /* Change +option to -option. */
@@ -1069,11 +1119,12 @@ usage_aux(void)
"[-hybrid] "
#endif
"[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] "
- "[-args_file FILENAME] "
- "[+A THREADS] [+a SIZE] [+B[c|d|i]] [+c] [+h HEAP_SIZE_OPTION] [+K BOOLEAN] "
+ "[-args_file FILENAME] [+A THREADS] [+a SIZE] [+B[c|d|i]] [+c] "
+ "[+h HEAP_SIZE_OPTION] [+K BOOLEAN] "
"[+l] [+M<SUBSWITCH> <ARGUMENT>] [+P MAX_PROCS] [+R COMPAT_REL] "
- "[+r] [+s SCHEDULER_OPTION] [+S NO_SCHEDULERS:NO_SCHEDULERS_ONLINE] [+T LEVEL] [+V] [+v] [+W<i|w>] "
- "[args ...]\n");
+ "[+r] [+rg READER_GROUPS_LIMIT] [+s SCHEDULER_OPTION] "
+ "[+S NO_SCHEDULERS:NO_SCHEDULERS_ONLINE] [+T LEVEL] [+V] [+v] "
+ "[+W<i|w>] [+z MISC_OPTION] [args ...]\n");
exit(1);
}
@@ -1122,10 +1173,10 @@ start_epmd(char *epmd)
if (!epmd) {
epmd = epmd_cmd;
#ifdef __WIN32__
- sprintf(epmd_cmd, "%s" DIRSEP "epmd", bindir);
+ erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "%s" DIRSEP "epmd", bindir);
arg1 = "-daemon";
#else
- sprintf(epmd_cmd, "%s" DIRSEP "epmd -daemon", bindir);
+ erts_snprintf(epmd_cmd, sizeof(epmd_cmd), "%s" DIRSEP "epmd -daemon", bindir);
#endif
}
#ifdef __WIN32__
@@ -1201,7 +1252,7 @@ void error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "erlexec: %s\n", sbuf);
exit(1);
@@ -1281,14 +1332,14 @@ static void get_start_erl_data(char *file)
if (env)
reldir = strsave(env);
else {
- sprintf(tmpbuffer, "%s/releases", rootdir);
+ erts_snprintf(tmpbuffer, sizeof(tmpbuffer), "%s/releases", rootdir);
reldir = strsave(tmpbuffer);
}
free_env_val(env);
if (file == NULL)
- sprintf(start_erl_data, "%s/start_erl.data", reldir);
+ erts_snprintf(start_erl_data, sizeof(start_erl_data), "%s/start_erl.data", reldir);
else
- sprintf(start_erl_data, "%s", file);
+ erts_snprintf(start_erl_data, sizeof(start_erl_data), "%s", file);
fp = _open(start_erl_data, _O_RDONLY );
if( fp == -1 )
error( "open failed on %s",start_erl_data );
@@ -1318,16 +1369,16 @@ static void get_start_erl_data(char *file)
}
bindir = emalloc(512);
- sprintf(bindir,"%s/erts-%s/bin",rootdir,tmpbuffer);
+ erts_snprintf(bindir,512,"%s/erts-%s/bin",rootdir,tmpbuffer);
/* BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin */
tprogname = progname;
progname = emalloc(strlen(tprogname) + 20);
- sprintf(progname,"%s -start_erl",tprogname);
+ erts_snprintf(progname,strlen(tprogname) + 20,"%s -start_erl",tprogname);
boot_script = emalloc(512);
config_script = emalloc(512);
- sprintf(boot_script, "%s/%s/start", reldir, otpstring);
- sprintf(config_script, "%s/%s/sys", reldir, otpstring);
+ erts_snprintf(boot_script, 512, "%s/%s/start", reldir, otpstring);
+ erts_snprintf(config_script, 512, "%s/%s/sys", reldir, otpstring);
}
@@ -1335,7 +1386,7 @@ static void get_start_erl_data(char *file)
static char *replace_filename(char *path, char *new_base)
{
int plen = strlen(path);
- char *res = malloc((plen+strlen(new_base)+1)*sizeof(char));
+ char *res = emalloc((plen+strlen(new_base)+1)*sizeof(char));
char *p;
strcpy(res,path);
@@ -1350,7 +1401,7 @@ static char *path_massage(char *long_path)
{
char *p;
- p = malloc(MAX_PATH+1);
+ p = emalloc(MAX_PATH+1);
strcpy(p, long_path);
GetShortPathName(p, p, MAX_PATH);
return p;
@@ -1486,7 +1537,8 @@ get_parameters(int argc, char** argv)
/* Determine bindir from absolute path to executable */
char *p;
char buffer[PATH_MAX];
- strcpy(buffer, argv[0]);
+ strncpy(buffer, argv[0], sizeof(buffer));
+ buffer[sizeof(buffer)-1] = '\0';
for (p = buffer+strlen(buffer)-1 ; p >= buffer && *p != '/'; --p)
;
@@ -1499,7 +1551,8 @@ get_parameters(int argc, char** argv)
/* Determine rootdir from absolute path to bindir */
char *p;
char buffer[PATH_MAX];
- strcpy(buffer, bindir);
+ strncpy(buffer, bindir, sizeof(buffer));
+ buffer[sizeof(buffer)-1] = '\0';
for (p = buffer+strlen(buffer)-1; p >= buffer && *p != '/'; --p)
;
@@ -1925,6 +1978,11 @@ initial_argv_massage(int *argc, char ***argv)
*/
vix = 0;
+
+ av = build_args_from_env("ERL_" OTP_SYSTEM_VERSION "_FLAGS");
+ if (av)
+ avv[vix++].argv = av;
+
av = build_args_from_env("ERL_AFLAGS");
if (av)
avv[vix++].argv = av;
@@ -1939,10 +1997,6 @@ initial_argv_massage(int *argc, char ***argv)
if (av)
avv[vix++].argv = av;
- av = build_args_from_env("ERL_" OTP_SYSTEM_VERSION "_FLAGS");
- if (av)
- avv[vix++].argv = av;
-
av = build_args_from_env("ERL_ZFLAGS");
if (av)
avv[vix++].argv = av;
diff --git a/erts/etc/common/escript.c b/erts/etc/common/escript.c
index 1bc5eb7651..6ed79c91e3 100644
--- a/erts/etc/common/escript.c
+++ b/erts/etc/common/escript.c
@@ -151,6 +151,9 @@ find_prog(char *origpath)
char relpath[PMAX];
char abspath[PMAX];
+ if (strlen(origpath) >= sizeof(relpath))
+ error("Path too long");
+
strcpy(relpath, origpath);
if (strstr(relpath, DIRSEPSTR) == NULL) {
@@ -180,19 +183,21 @@ find_prog(char *origpath)
end = strstr(beg, PATHSEPSTR);
if (end != NULL) {
sz = end - beg;
- strncpy(dir, beg, sz);
- dir[sz] = '\0';
} else {
sz = strlen(beg);
- strcpy(dir, beg);
look_for_sep = FALSE;
}
+ if (sz >= sizeof(dir)) {
+ beg = end + 1;
+ continue;
+ }
+ strncpy(dir, beg, sz);
+ dir[sz] = '\0';
beg = end + 1;
#ifdef __WIN32__
- strcpy(wildcard, dir);
- strcat(wildcard, DIRSEPSTR);
- strcat(wildcard, relpath); /* basename */
+ erts_snprintf(wildcard, sizeof(wildcard), "%s" DIRSEPSTR "%s",
+ dir, relpath /* basename */);
dir_handle = FindFirstFile(wildcard, &find_data);
if (dir_handle == INVALID_HANDLE_VALUE) {
/* Try next directory in path */
@@ -217,9 +222,8 @@ find_prog(char *origpath)
if (strcmp(origpath, dirp->d_name) == 0) {
/* Wow we found the executable. */
- strcpy(relpath, dir);
- strcat(relpath, DIRSEPSTR);
- strcat(relpath, dirp->d_name);
+ erts_snprintf(relpath, sizeof(relpath), "%s" DIRSEPSTR "%s",
+ dir, dirp->d_name);
closedir(dp);
look_for_sep = FALSE;
break;
@@ -291,7 +295,7 @@ append_shebang_args(char* scriptname)
/* Find end of arg */
end = beg;
- while (end && end[0] != ' ') {
+ while (end && end < (linebuf+LINEBUFSZ-1) && end[0] != ' ') {
if (end[0] == '\n') {
newline = TRUE;
end[0]= '\0';
@@ -335,13 +339,16 @@ main(int argc, char** argv)
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
* the array, to allow easy addition of commands in the beginning.
*/
- eargv_size = argc*4+1000;
+ eargv_size = argc*4+1000+LINEBUFSZ/2;
eargv_base = (char **) emalloc(eargv_size*sizeof(char*));
eargv = eargv_base;
eargc = 0;
@@ -387,7 +394,8 @@ main(int argc, char** argv)
if (argc <= 1) {
error("Missing filename\n");
}
- strcpy(scriptname, argv[1]);
+ strncpy(scriptname, argv[1], sizeof(scriptname));
+ scriptname[sizeof(scriptname)-1] = '\0';
argc--;
argv++;
} else {
@@ -395,16 +403,17 @@ main(int argc, char** argv)
int len;
#endif
absname = find_prog(argv[0]);
- strcpy(scriptname, absname);
- efree(absname);
#ifdef __WIN32__
- len = strlen(scriptname);
- if (len >= 4 && _stricmp(scriptname+len-4, ".exe") == 0) {
- scriptname[len-4] = '\0';
+ len = strlen(absname);
+ if (len >= 4 && _stricmp(absname+len-4, ".exe") == 0) {
+ absname[len-4] = '\0';
}
#endif
- strcat(scriptname, ".escript");
+ erts_snprintf(scriptname, sizeof(scriptname), "%s.escript",
+ absname);
+ efree(absname);
+
}
/*
@@ -455,7 +464,7 @@ main(int argc, char** argv)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[PMAX];
char* dst;
dst = sbuf;
@@ -584,7 +593,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "escript: %s\n", sbuf);
exit(1);
@@ -619,6 +628,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index 4f738947b7..7a5746e630 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* 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
@@ -375,7 +375,8 @@ main(int argc, char **argv)
_setmode(erlin_fd,_O_BINARY);
_setmode(erlout_fd,_O_BINARY);
#endif
- strcpy(program_name, argv[0]);
+ strncpy(program_name, argv[0], sizeof(program_name));
+ program_name[sizeof(program_name)-1] = '\0';
notify_ack(erlout_fd);
cmd[0] = '\0';
do_terminate(message_loop(erlin_fd,erlout_fd));
@@ -726,12 +727,16 @@ static int
heart_cmd_reply(int fd, char *s)
{
struct msg m;
- int len = strlen(s) + 1; /* Include \0 */
+ int len = strlen(s);
- /* FIXME if s >= MSG_BODY_SIZE error */
+ /* if s >= MSG_BODY_SIZE, return a write
+ * failure immediately.
+ */
+ if (len >= sizeof(m.fill))
+ return -1;
m.op = HEART_CMD;
- m.len = htons(len + 2); /* Include Op */
+ m.len = htons(len + 1); /* Include Op */
strcpy((char*)m.fill, s);
return write_message(fd, &m);
diff --git a/erts/etc/common/inet_gethost.c b/erts/etc/common/inet_gethost.c
index ff16ee02c4..77bfd5e2bc 100644
--- a/erts/etc/common/inet_gethost.c
+++ b/erts/etc/common/inet_gethost.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
+ *
* 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 online 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.
- *
+ *
* %CopyrightEnd%
*/
/*
@@ -52,20 +52,21 @@
# include "config.h"
#endif
+#include "erl_printf.h"
+
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
+#include <ws2tcpip.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
/* These are not used even if they would exist which they should not */
-#undef HAVE_GETADDRINFO
#undef HAVE_GETIPNODEBYNAME
#undef HAVE_GETHOSTBYNAME2
-#undef HAVE_GETNAMEINFO
#undef HAVE_GETIPNODEBYADDR
#else /* Unix */
@@ -1296,7 +1297,7 @@ static int read_request(AddrByte **buff, size_t *buff_size)
}
if (siz > *buff_size) {
- if (buff_size == 0) {
+ if (*buff_size == 0) {
*buff = ALLOC((*buff_size = siz));
} else {
*buff = REALLOC(*buff, (*buff_size = siz));
@@ -1759,7 +1760,7 @@ static int worker_loop(void)
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
- hints.ai_flags = (AI_CANONNAME|AI_V4MAPPED|AI_ADDRCONFIG);
+ hints.ai_flags = AI_CANONNAME;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET6;
DEBUGF(5, ("Starting getaddrinfo(%s, ...)", data));
@@ -2552,7 +2553,7 @@ static void debugf(char *format, ...)
sprintf(buff,"%s[%d] (DEBUG):",program_name,(int) getpid());
#endif
ptr = buff + strlen(buff);
- vsprintf(ptr,format,ap);
+ erts_vsnprintf(ptr,sizeof(buff)-strlen(buff)-2,format,ap);
strcat(ptr,"\r\n");
#ifdef WIN32
if (debug_console_allocated != INVALID_HANDLE_VALUE) {
@@ -2574,7 +2575,7 @@ static void warning(char *format, ...)
va_start(ap,format);
sprintf(buff,"%s[%d]: WARNING:",program_name, (int) getpid());
ptr = buff + strlen(buff);
- vsprintf(ptr,format,ap);
+ erts_vsnprintf(ptr,sizeof(buff)-strlen(buff)-2,format,ap);
strcat(ptr,"\r\n");
#ifdef WIN32
{
@@ -2596,7 +2597,7 @@ static void fatal(char *format, ...)
va_start(ap,format);
sprintf(buff,"%s[%d]: FATAL ERROR:",program_name, (int) getpid());
ptr = buff + strlen(buff);
- vsprintf(ptr,format,ap);
+ erts_vsnprintf(ptr,sizeof(buff)-strlen(buff)-2,format,ap);
strcat(ptr,"\r\n");
#ifdef WIN32
{
diff --git a/erts/etc/common/typer.c b/erts/etc/common/typer.c
index c2567cb8b4..c95959d52d 100644
--- a/erts/etc/common/typer.c
+++ b/erts/etc/common/typer.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2009. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2011. All Rights Reserved.
*
* 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
@@ -175,7 +175,7 @@ main(int argc, char** argv)
static void
push_words(char* src)
{
- char sbuf[1024];
+ char sbuf[MAXPATHLEN];
char* dst;
dst = sbuf;
@@ -307,7 +307,7 @@ error(char* format, ...)
va_list ap;
va_start(ap, format);
- vsprintf(sbuf, format, ap);
+ erts_vsnprintf(sbuf, sizeof(sbuf), format, ap);
va_end(ap);
fprintf(stderr, "typer: %s\n", sbuf);
exit(1);
@@ -336,6 +336,9 @@ get_default_emulator(char* progname)
char sbuf[MAXPATHLEN];
char* s;
+ if (strlen(progname) >= sizeof(sbuf))
+ return ERL_NAME;
+
strcpy(sbuf, progname);
for (s = sbuf+strlen(sbuf); s >= sbuf; s--) {
if (IS_DIRSEP(*s)) {
diff --git a/erts/etc/unix/Install.src b/erts/etc/unix/Install.src
index 83f9690782..8f40c43874 100644
--- a/erts/etc/unix/Install.src
+++ b/erts/etc/unix/Install.src
@@ -89,8 +89,12 @@ cp -p $ERL_ROOT/erts-%I_VSN%/bin/erl .
cp -p $ERL_ROOT/erts-%I_VSN%/bin/erlc .
cp -p $ERL_ROOT/erts-%I_VSN%/bin/dialyzer .
cp -p $ERL_ROOT/erts-%I_VSN%/bin/typer .
+cp -p $ERL_ROOT/erts-%I_VSN%/bin/ct_run .
cp -p $ERL_ROOT/erts-%I_VSN%/bin/escript .
+# Remove in R16B
+ln -s ct_run run_test
+
#
# Set a soft link to epmd
# This should not be done for an embedded system!
diff --git a/erts/etc/unix/cerl.src b/erts/etc/unix/cerl.src
index f81ef6b0fe..0b2d6512ea 100644
--- a/erts/etc/unix/cerl.src
+++ b/erts/etc/unix/cerl.src
@@ -1,20 +1,20 @@
#!/bin/sh
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2003-2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2003-2011. All Rights Reserved.
+#
# 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 online 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.
-#
+#
# %CopyrightEnd%
#
#
@@ -62,12 +62,21 @@ cxargs_add() {
done
}
+eeargs=
+eeargs_add() {
+ while [ $# -gt 0 ]; do
+ cargs="$cargs $1"
+ eeargs="$eeargs $1"
+ shift
+ done
+}
+
core=
GDB=
GDBBP=
+GDBARGS=
TYPE=
-EMU_TYPE=
debug=
run_valgrind=no
@@ -126,34 +135,37 @@ while [ $# -gt 0 ]; do
;;
"-smp")
shift
- cargs="$cargs -smp"
- EMU_TYPE=.smp
+ if [ $# -le 0 ]; then
+ eeargs_add -smp
+ else
+ case $1 in
+ disable)
+ shift
+ eeargs_add -smpdisable
+ ;;
+ enable)
+ shift
+ eeargs_add -smp
+ ;;
+ *)
+ eeargs_add -smp
+ esac
+ fi
+ ;;
+ "-smpdisable")
+ shift
+ eeargs_add -smpdisable
;;
"-lcnt")
shift
cargs="$cargs -lcnt"
TYPE=.lcnt
;;
- "-frag")
- shift
- cargs="$cargs -frag"
- EMU_TYPE=.frag
- ;;
- "-smp_frag")
- shift
- cargs="$cargs -smp_frag"
- EMU_TYPE=.smp_frag
- ;;
"-gprof")
shift
cargs="$cargs -gprof"
TYPE=.gprof
;;
- "-hybrid")
- shift
- cargs="$cargs -hybrid"
- EMU_TYPE=.hybrid
- ;;
"-debug")
shift
cargs="$cargs -debug"
@@ -179,11 +191,6 @@ while [ $# -gt 0 ]; do
# shift
# GDB=xxgdb
# ;;
- "-shared")
- shift
- cargs="$cargs -shared"
- TYPE=.shared
- ;;
"-purify")
shift
cargs="$cargs -purify"
@@ -221,23 +228,38 @@ PATH=$BINDIR:$ROOTDIR/bin:$PATH
EXEC=$BINDIR/erlexec
PROGNAME="$PROGNAME $cargs"
-EMU=$EMU$TYPE$EMU_TYPE
+EMU="$EMU$TYPE"
+EMU_NAME=`$EXEC -emu_name_exit $eeargs`
+
if [ $run_valgrind != yes ]; then
xargs="$xargs -pz $PRELOADED --"
fi
if [ "x$GDB" = "x" ]; then
if [ $run_valgrind = yes ]; then
+ valversion=`valgrind --version`
+ valmajor=`echo $valversion | sed 's,[a-z]*\-\([0-9]*\).*,\1,'`
+ valminor=`echo $valversion | sed 's,[a-z]*\-[0-9]*.\([0-9]*\).*,\1,'`
emu_xargs=`echo $xargs | sed "s|+|-|g"`
- if [ "x$VALGRIND_LOG_DIR" = "x" ]; then
- valgrind_log=
- else
- valgrind_log="--log-file=$VALGRIND_LOG_DIR/$VALGRIND_LOGFILE_PREFIX$VALGRIND_LOGFILE_INFIX$EMU.log"
- fi
if [ "x$VALGRIND_LOG_XML" = "x" ]; then
valgrind_xml=
+ log_file_prefix="--log-file="
else
export VALGRIND_LOG_XML
valgrind_xml="--xml=yes"
+ if [ $valmajor -gt 2 -a $valminor -gt 4 ]; then
+ log_file_prefix="--xml-file="
+ else
+ log_file_prefix="--log-file="
+ fi
+ fi
+ if [ "x$VALGRIND_LOG_DIR" = "x" ]; then
+ valgrind_log=
+ else
+ if [ $valmajor -gt 2 -a $valminor -gt 4 ]; then
+ valgrind_log="$log_file_prefix$VALGRIND_LOG_DIR/$VALGRIND_LOGFILE_PREFIX$VALGRIND_LOGFILE_INFIX$EMU_NAME.log.$$"
+ else
+ valgrind_log="$log_file_prefix$VALGRIND_LOG_DIR/$VALGRIND_LOGFILE_PREFIX$VALGRIND_LOGFILE_INFIX$EMU_NAME.log"
+ fi
fi
if [ "x$VALGRIND_MISC_FLAGS" = "x" ]; then
valgrind_misc_flags=
@@ -249,9 +271,9 @@ if [ "x$GDB" = "x" ]; then
early_beam_args=`echo $beam_args | sed "s|^\(.*-progname\).*$|\1|g"`
late_beam_args=`echo $beam_args | sed "s|^$pre_beam_args.*\(-- -home.*\)$|\1|g"`
- exec valgrind $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU $emu_xargs $early_beam_args "$PROGNAME" $late_beam_args -pz $PRELOADED
+ exec valgrind $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU_NAME $emu_xargs $early_beam_args "$PROGNAME" $late_beam_args -pz $PRELOADED
else
- exec $EXEC $xargs ${1+"$@"}
+ exec $EXEC $eeargs $xargs ${1+"$@"}
fi
else
if [ "x$EMACS" = "x" ]; then
@@ -277,9 +299,14 @@ else
;;
esac
+ # Set annotation level for gdb in emacs 22 and higher.
+ emacs_major=`$EMACS --version | head -1 | sed 's,^[^0-9]*\([0-9]*\).*,\1,g'`
+ if [ '!' -z "$emacs_major" -a $emacs_major -gt 21 ]; then
+ GDBARGS="--annotate=3 "
+ fi
gdbcmd="$gdbcmd $GDBBP \
(insert-string \"source $ROOTDIR/erts/etc/unix/etp-commands\") \
(comint-send-input)"
# Fire up gdb in emacs...
- exec $EMACS --eval "(progn (gdb \"gdb $EMU\") $gdbcmd)"
+ exec $EMACS --eval "(progn (gdb \"gdb $GDBARGS$EMU_NAME\") $gdbcmd)"
fi
diff --git a/erts/etc/unix/format_man_pages b/erts/etc/unix/format_man_pages
index 2c4f6eee4f..93dcdcd8fa 100644
--- a/erts/etc/unix/format_man_pages
+++ b/erts/etc/unix/format_man_pages
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
+# Copyright Ericsson AB 1996-2010. All Rights Reserved.
#
# 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
@@ -59,34 +59,21 @@ esac
# Create the 'cat' directories (probably not needed)
#
-cd $ERL_ROOT
+cd $ERL_ROOT/man
-if [ ! -d man/cat1 ]
-then
- mkdir man/cat1
-fi
+for d in 0 1 2 3 4 5 6 7 8 9
+do
+ if [ ! -d cat$d ]
+ then
+ mkdir cat$d
+ fi
-if [ ! -d man/cat3 ]
-then
- mkdir man/cat3
-fi
-
-if [ ! -d man/cat4 ]
-then
- mkdir man/cat4
-fi
-
-if [ ! -d man/cat6 ]
-then
- mkdir man/cat6
-fi
+done
#
# Cleanup old formatting
#
-cd $ERL_ROOT/man
-
rm -f whatis windex
# Remove old cat files
diff --git a/erts/etc/unix/run_erl.c b/erts/etc/unix/run_erl.c
index 4bb148df98..8db8e09bee 100644
--- a/erts/etc/unix/run_erl.c
+++ b/erts/etc/unix/run_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* 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
@@ -75,6 +75,9 @@
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
+#if defined(__sun) && defined(__SVR4)
+# include <stropts.h>
+#endif
#include "run_erl.h"
#include "safe_string.h" /* sn_printf, strn_cpy, strn_cat, etc */
@@ -218,6 +221,8 @@ int main(int argc, char **argv)
char *p, *ptyslave=NULL;
int i = 1;
int off_argv;
+ int calculated_pipename = 0;
+ int highest_pipe_num = 0;
program_name = argv[0];
@@ -295,10 +300,10 @@ int main(int argc, char **argv)
if(*pipename && pipename[strlen(pipename)-1] == '/') {
/* The user wishes us to find a unique pipe name in the specified */
/* directory */
- int highest_pipe_num = 0;
DIR *dirp;
struct dirent *direntp;
+ calculated_pipename = 1;
dirp = opendir(pipename);
if(!dirp) {
ERRNO_ERR1(LOG_ERR,"Can't access pipe directory '%s'.", pipename);
@@ -319,28 +324,37 @@ int main(int argc, char **argv)
PIPE_STUBNAME, highest_pipe_num+1);
} /* if */
- /* write FIFO - is read FIFO for `to_erl' program */
- strn_cpy(fifo1, sizeof(fifo1), pipename);
- strn_cat(fifo1, sizeof(fifo1), ".r");
- if (create_fifo(fifo1, PERM) < 0) {
- ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for writing.", fifo1);
- exit(1);
- }
-
- /* read FIFO - is write FIFO for `to_erl' program */
- strn_cpy(fifo2, sizeof(fifo2), pipename);
- strn_cat(fifo2, sizeof(fifo2), ".w");
-
- /* Check that nobody is running run_erl already */
- if ((fd = open (fifo2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
- /* Open as client succeeded -- run_erl is already running! */
- fprintf(stderr, "Erlang already running on pipe %s.\n", pipename);
- close(fd);
- exit(1);
- }
- if (create_fifo(fifo2, PERM) < 0) {
- ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.", fifo2);
- exit(1);
+ for(;;) {
+ /* write FIFO - is read FIFO for `to_erl' program */
+ strn_cpy(fifo1, sizeof(fifo1), pipename);
+ strn_cat(fifo1, sizeof(fifo1), ".r");
+ if (create_fifo(fifo1, PERM) < 0) {
+ ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for writing.", fifo1);
+ exit(1);
+ }
+
+ /* read FIFO - is write FIFO for `to_erl' program */
+ strn_cpy(fifo2, sizeof(fifo2), pipename);
+ strn_cat(fifo2, sizeof(fifo2), ".w");
+
+ /* Check that nobody is running run_erl already */
+ if ((fd = open (fifo2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
+ /* Open as client succeeded -- run_erl is already running! */
+ close(fd);
+ if (calculated_pipename) {
+ ++highest_pipe_num;
+ strn_catf(pipename, sizeof(pipename), "%s.%d",
+ PIPE_STUBNAME, highest_pipe_num+1);
+ continue;
+ }
+ fprintf(stderr, "Erlang already running on pipe %s.\n", pipename);
+ exit(1);
+ }
+ if (create_fifo(fifo2, PERM) < 0) {
+ ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.", fifo2);
+ exit(1);
+ }
+ break;
}
/*
@@ -864,8 +878,12 @@ static int open_pty_master(char **ptyslave)
/* Use the posix_openpt if working, as this guarantees creation of the
slave device properly. */
-#ifdef HAVE_WORKING_POSIX_OPENPT
+#if defined(HAVE_WORKING_POSIX_OPENPT) || (defined(__sun) && defined(__SVR4))
+# ifdef HAVE_WORKING_POSIX_OPENPT
if ((mfd = posix_openpt(O_RDWR)) >= 0) {
+# elif defined(__sun) && defined(__SVR4)
+ if ((mfd = open("/dev/ptmx", O_RDWR)) >= 0) {
+# endif
if ((*ptyslave = ptsname(mfd)) != NULL &&
grantpt(mfd) == 0 &&
unlockpt(mfd) == 0) {
@@ -973,16 +991,53 @@ static int open_pty_master(char **ptyslave)
static int open_pty_slave(char *name)
{
int sfd;
-#ifdef DEBUG
struct termios tty_rmode;
-#endif
if ((sfd = open(name, O_RDWR, 0)) < 0) {
return -1;
}
+#if defined(__sun) && defined(__SVR4)
+ /* Load the necessary STREAMS modules for Solaris */
+ if ((ioctl(sfd, I_FIND, "ldterm")) < 0) {
+ ERROR0(LOG_ERR, "Failed to find ldterm STREAMS module");
+ return -1;
+ }
+ if (ioctl(sfd, I_PUSH, "ptem") < 0) {
+ ERROR0(LOG_ERR, "Failed to push ptem STREAMS module");
+ return -1;
+ }
+ if (ioctl(sfd, I_PUSH, "ldterm") < 0) {
+ ERROR0(LOG_ERR, "Failed to push ldterm STREAMS module");
+ return -1;
+ }
+ if (ioctl(sfd, I_PUSH, "ttcompat") < 0) {
+ ERROR0(LOG_ERR, "Failed to push ttcompat STREAMS module");
+ return -1;
+ }
+#endif
+
+ if (getenv("RUN_ERL_DISABLE_FLOWCNTRL")) {
+ if (tcgetattr(sfd, &tty_rmode) < 0) {
+ fprintf(stderr, "Cannot get terminal's current mode\n");
+ exit(-1);
+ }
+
+ tty_rmode.c_iflag &= ~IXOFF;
+ if (tcsetattr(sfd, TCSANOW, &tty_rmode) < 0) {
+ fprintf(stderr, "Cannot disable terminal's flow control on input\n");
+ exit(-1);
+ }
+
+ tty_rmode.c_iflag &= ~IXON;
+ if (tcsetattr(sfd, TCSANOW, &tty_rmode) < 0) {
+ fprintf(stderr, "Cannot disable terminal's flow control on output\n");
+ exit(-1);
+ }
+ }
+
#ifdef DEBUG
- if (tcgetattr(sfd, &tty_rmode) , 0) {
+ if (tcgetattr(sfd, &tty_rmode) < 0) {
fprintf(stderr, "Cannot get terminals current mode\n");
exit(-1);
}
diff --git a/erts/etc/unix/to_erl.c b/erts/etc/unix/to_erl.c
index 886b301997..11fa3ff4cc 100644
--- a/erts/etc/unix/to_erl.c
+++ b/erts/etc/unix/to_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2011. All Rights Reserved.
*
* 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
@@ -125,7 +125,7 @@ static void usage(char *pname)
int main(int argc, char **argv)
{
char FIFO1[FILENAME_MAX], FIFO2[FILENAME_MAX];
- int i, len, wfd, rfd, result = 0;
+ int i, len, wfd, rfd;
fd_set readfds;
char buf[BUFSIZ];
char pipename[FILENAME_MAX];
@@ -367,7 +367,6 @@ int main(int argc, char **argv)
}
else {
fprintf(stderr, "Error in select.\n");
- result = -1;
break;
}
}
@@ -398,7 +397,6 @@ int main(int argc, char **argv)
close(wfd);
if (len < 0) {
fprintf(stderr, "Error in reading from stdin.\n");
- result = -1;
} else {
fprintf(stderr, "[EOF]\n\r");
}
@@ -420,7 +418,6 @@ int main(int argc, char **argv)
fprintf(stderr, "Error in writing to FIFO.\n");
close(rfd);
close(wfd);
- result = -1;
break;
}
STATUS("\" OK\r\n");
@@ -447,7 +444,6 @@ int main(int argc, char **argv)
close(wfd);
if (len < 0) {
fprintf(stderr, "Error in reading from FIFO.\n");
- result = -1;
} else
fprintf(stderr, "[End]\n\r");
break;
@@ -456,7 +452,6 @@ int main(int argc, char **argv)
if ((len=version_handshake(buf,len,wfd)) < 0) {
close(rfd);
close(wfd);
- result = -1;
break;
}
if (protocol_ver >= 1) {
@@ -475,7 +470,6 @@ int main(int argc, char **argv)
fprintf(stderr, "Error in writing to terminal.\n");
close(rfd);
close(wfd);
- result = -1;
break;
}
STATUS("\" OK\r\n");
diff --git a/erts/etc/win32/Install.c b/erts/etc/win32/Install.c
index 4a559cd8a2..d680b67dd6 100644
--- a/erts/etc/win32/Install.c
+++ b/erts/etc/win32/Install.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2003-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2003-2011. All Rights Reserved.
+ *
* 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 online 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.
- *
+ *
* %CopyrightEnd%
*/
/*
@@ -45,8 +45,8 @@ int main(int argc, char **argv)
InitSection *ini_section;
HANDLE module = GetModuleHandle(NULL);
char *binaries[] = { "erl.exe", "werl.exe", "erlc.exe",
- "dialyzer.exe", "typer.exe",
- "escript.exe", NULL };
+ "dialyzer.exe", "typer.exe",
+ "escript.exe", "ct_run.exe", NULL };
char *scripts[] = { "start_clean.boot", "start_sasl.boot", NULL };
char fromname[MAX_PATH];
char toname[MAX_PATH];
@@ -172,6 +172,20 @@ int main(int argc, char **argv)
}
}
+ // Remove in R16B
+ sprintf(fromname,"%s\\%s",bin_dir,"ct_run.exe");
+ sprintf(toname,"%s\\%s",bin_dir,"run_test.exe");
+ if (GetFileAttributes(fromname) == 0xFFFFFFFF) {
+ fprintf(stderr,"Could not find file %s\n",
+ fromname);
+ exit(1);
+ }
+ if (!CopyFile(fromname,toname,FALSE)) {
+ fprintf(stderr,"Could not copy file %s to %s\n",
+ fromname,toname);
+ fprintf(stderr,"Continuing installation anyway...\n");
+ }
+
for (i = 0; scripts[i] != NULL; ++i) {
sprintf(fromname,"%s\\%s",release_dir,scripts[i]);
sprintf(toname,"%s\\%s",bin_dir,scripts[i]);
@@ -199,6 +213,9 @@ int main(int argc, char **argv)
fprintf(stderr,"Cannot continue installation, bailing out.\n");
exit(1);
}
+
+ /* OBS!!! If the format of the init file is changed, do not forget
+ to update release_handler:write_ini_file(...) */
ini_file = create_init_file();
ini_section = create_init_section("erlang");
add_init_section(ini_file,ini_section);
diff --git a/erts/etc/win32/cygwin_tools/vc/ld.sh b/erts/etc/win32/cygwin_tools/vc/ld.sh
index ac39bf871c..406c63ffee 100755
--- a/erts/etc/win32/cygwin_tools/vc/ld.sh
+++ b/erts/etc/win32/cygwin_tools/vc/ld.sh
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2009. All Rights Reserved.
+# Copyright Ericsson AB 2002-2010. All Rights Reserved.
#
# 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
@@ -53,7 +53,7 @@ while test -n "$1" ; do
STDLIB_FORCED=true;
STDLIB=LIBCMTD.LIB;;
-lsocket)
- DEFAULT_LIBRARIES="$DEFAULT_LIBRARIES WS2_32.LIB";;
+ DEFAULT_LIBRARIES="$DEFAULT_LIBRARIES WS2_32.LIB IPHLPAPI.LIB";;
-l*)
y=`echo $x | sed 's,^-l\(.*\),\1,g'`;
MPATH=`cygpath -m $y`;
@@ -158,7 +158,7 @@ else
fi
p=$$
-CMD="$linktype -nologo -incremental:no $CMD $STDLIB $DEFAULT_LIBRARIES"
+CMD="$linktype -nologo -incremental:no -largeaddressaware $CMD $STDLIB $DEFAULT_LIBRARIES"
if [ "X$LD_SH_DEBUG_LOG" != "X" ]; then
echo ld.sh "$SAVE" >>$LD_SH_DEBUG_LOG
echo link.exe $CMD >>$LD_SH_DEBUG_LOG
@@ -167,6 +167,10 @@ eval link.exe "$CMD" >/tmp/link.exe.${p}.1 2>/tmp/link.exe.${p}.2
RES=$?
CMANIFEST=`cygpath $MANIFEST`
if [ "$RES" = "0" -a -f "$CMANIFEST" ]; then
+ # Add stuff to manifest to turn off "virtualization"
+ sed -n -i '1h;1!H;${;g;s,<trustInfo.*</trustInfo>.,,g;p;}' $CMANIFEST
+ sed -i "s/<\/assembly>/ <ms_asmv2:trustInfo xmlns:ms_asmv2=\"urn:schemas-microsoft-com:asm.v2\">\n <ms_asmv2:security>\n <ms_asmv2:requestedPrivileges>\n <ms_asmv2:requestedExecutionLevel level=\"AsInvoker\" uiAccess=\"false\"\/>\n <\/ms_asmv2:requestedPrivileges>\n <\/ms_asmv2:security>\n <\/ms_asmv2:trustInfo>\n<\/assembly>/" $CMANIFEST
+
eval mt.exe -nologo -manifest "$MANIFEST" -outputresource:"$OUTPUTRES" >>/tmp/link.exe.${p}.1 2>>/tmp/link.exe.${p}.2
RES=$?
if [ "$RES" != "0" ]; then
diff --git a/erts/etc/win32/cygwin_tools/vc/rc.sh b/erts/etc/win32/cygwin_tools/vc/rc.sh
index 6a6921c49e..054c672e64 100755
--- a/erts/etc/win32/cygwin_tools/vc/rc.sh
+++ b/erts/etc/win32/cygwin_tools/vc/rc.sh
@@ -2,20 +2,20 @@
# set -x
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2002-2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2002-2010. All Rights Reserved.
+#
# 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 online 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.
-#
+#
# %CopyrightEnd%
#
# Save the command line for debug outputs
@@ -80,7 +80,7 @@ if [ "X$RC_SH_DEBUG_LOG" != "X" ]; then
fi
eval $RCC "$CMD" >/tmp/rc.exe.${p}.1 2>/tmp/rc.exe.${p}.2
RES=$?
-tail +2 /tmp/rc.exe.${p}.2 >&2
+tail -n +2 /tmp/rc.exe.${p}.2 >&2
cat /tmp/rc.exe.${p}.1
rm -f /tmp/rc.exe.${p}.2 /tmp/rc.exe.${p}.1
exit $RES
diff --git a/erts/etc/win32/erlsrv/erlsrv_interactive.c b/erts/etc/win32/erlsrv/erlsrv_interactive.c
index 13e029b364..736eabac79 100644
--- a/erts/etc/win32/erlsrv/erlsrv_interactive.c
+++ b/erts/etc/win32/erlsrv/erlsrv_interactive.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* 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
@@ -135,7 +135,12 @@ void print_last_error(void){
fprintf(stderr,"Error: %s",mes);
LocalFree(mes);
}
-
+
+static int get_last_error(void)
+{
+ return (last_error) ? last_error : GetLastError();
+}
+
static BOOL install_service(void){
SC_HANDLE scm;
SC_HANDLE service;
@@ -508,7 +513,7 @@ int do_usage(char *arg0){
"\t[{-sn[ame] | -n[ame]} [<nodename>]]\n"
"\t[-d[ebugtype] [{new|reuse|console}]]\n"
"\t[-ar[gs] [<limited erl arguments>]]\n\n"
- "%s {start | stop | disable | enable} <servicename>\n\n"
+ "%s {start | start_disabled | stop | disable | enable} <servicename>\n\n"
"%s remove <servicename>\n\n"
"%s rename <servicename> <servicename>\n\n"
"%s list [<servicename>]\n\n"
@@ -561,6 +566,45 @@ int do_manage(int argc,char **argv){
return 0;
}
}
+ if(!_stricmp(action,"start_disabled")){
+ if(!enable_service()){
+ fprintf(stderr,"%s: Failed to enable service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ return 1;
+ }
+ if(!start_service() && get_last_error() != ERROR_SERVICE_ALREADY_RUNNING){
+ fprintf(stderr,"%s: Failed to start service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ goto failure_starting;
+ }
+
+ if(!wait_service_trans(SERVICE_STOPPED, SERVICE_START_PENDING,
+ SERVICE_RUNNING, 60)){
+ fprintf(stderr,"%s: Failed to start service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ goto failure_starting;
+ }
+
+ if(!disable_service()){
+ fprintf(stderr,"%s: Failed to disable service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ return 1;
+ }
+ printf("%s: Service %s started.\n",
+ argv[0],service_name);
+ return 0;
+ failure_starting:
+ if(!disable_service()){
+ fprintf(stderr,"%s: Failed to disable service %s.\n",
+ argv[0],service_name);
+ print_last_error();
+ }
+ return 1;
+ }
if(!_stricmp(action,"stop")){
if(!stop_service()){
fprintf(stderr,"%s: Failed to stop service %s.\n",
@@ -841,6 +885,7 @@ int do_add_or_set(int argc, char **argv){
argv[0], service_name);
return 0;
}
+
int do_rename(int argc, char **argv){
RegEntry *current = empty_reg_tab();
RegEntry *dummy = empty_reg_tab();
@@ -1129,35 +1174,131 @@ void read_arguments(int *pargc, char ***pargv){
*pargc = argc;
*pargv = argv;
}
+
+/* Create a free-for-all ACL to set on the semaphore */
+PACL get_acl(PSECURITY_DESCRIPTOR secdescp)
+{
+ DWORD acl_length = 0;
+ PSID auth_users_sidp = NULL;
+ PACL aclp = NULL;
+ SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
+
+ if(!InitializeSecurityDescriptor(secdescp, SECURITY_DESCRIPTOR_REVISION)) {
+ return NULL;
+ }
+
+ if(!AllocateAndInitializeSid(&ntauth,
+ 1,
+ SECURITY_AUTHENTICATED_USER_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &auth_users_sidp)) {
+ return NULL;
+ }
+
+ acl_length = sizeof(ACL) +
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
+ GetLengthSid(auth_users_sidp);
+
+ if((aclp = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, acl_length)) == NULL) {
+ FreeSid(auth_users_sidp);
+ return NULL;
+ }
+
+ if(!InitializeAcl(aclp, acl_length, ACL_REVISION)) {
+ FreeSid(auth_users_sidp);
+ HeapFree(GetProcessHeap(), 0, aclp);
+ return NULL;
+ }
+
+ if(!AddAccessAllowedAce(aclp, ACL_REVISION, SEMAPHORE_ALL_ACCESS, auth_users_sidp)) {
+ FreeSid(auth_users_sidp);
+ HeapFree(GetProcessHeap(), 0, aclp);
+ return NULL;
+ }
+
+ if(!SetSecurityDescriptorDacl(secdescp, TRUE, aclp, FALSE)) {
+ FreeSid(auth_users_sidp);
+ HeapFree(GetProcessHeap(), 0, aclp);
+ return NULL;
+ }
+ return aclp;
+}
+
+static HANDLE lock_semaphore = NULL;
+
+int take_lock(void) {
+ SECURITY_ATTRIBUTES attr;
+ PACL aclp;
+ SECURITY_DESCRIPTOR secdesc;
+
+ if ((aclp = get_acl(&secdesc)) == NULL) {
+ return -1;
+ }
+
+ memset(&attr,0,sizeof(attr));
+ attr.nLength = sizeof(attr);
+ attr.lpSecurityDescriptor = &secdesc;
+ attr.bInheritHandle = FALSE;
+
+ if ((lock_semaphore = CreateSemaphore(&attr, 1, 1, ERLSRV_INTERACTIVE_GLOBAL_SEMAPHORE)) == NULL) {
+ return -1;
+ }
+
+ if (WaitForSingleObject(lock_semaphore,INFINITE) != WAIT_OBJECT_0) {
+ return -1;
+ }
+
+ HeapFree(GetProcessHeap(), 0, aclp);
+ return 0;
+}
+
+void release_lock(void) {
+ ReleaseSemaphore(lock_semaphore,1,NULL);
+}
+
int interactive_main(int argc, char **argv){
char *action = argv[1];
-
+ int res;
+
+ if (take_lock() != 0) {
+ fprintf(stderr,"%s: unable to acquire global lock (%s).\n",argv[0],
+ ERLSRV_INTERACTIVE_GLOBAL_SEMAPHORE);
+ return 1;
+ }
+
if(!_stricmp(action,"readargs")){
- read_arguments(&argc,&argv);
- action = argv[1];
+ read_arguments(&argc,&argv);
+ action = argv[1];
}
if(!_stricmp(action,"set") || !_stricmp(action,"add"))
- return do_add_or_set(argc,argv);
- if(!_stricmp(action,"rename"))
- return do_rename(argc,argv);
- if(!_stricmp(action,"remove"))
- return do_remove(argc,argv);
- if(!_stricmp(action,"list"))
- return do_list(argc,argv);
- if(!_stricmp(action,"start") ||
- !_stricmp(action,"stop") ||
- !_stricmp(action,"enable") ||
- !_stricmp(action,"disable"))
- return do_manage(argc,argv);
- if(_stricmp(action,"?") &&
- _stricmp(action,"/?") &&
- _stricmp(action,"-?") &&
- *action != 'h' &&
- *action != 'H')
+ res = do_add_or_set(argc,argv);
+ else if(!_stricmp(action,"rename"))
+ res = do_rename(argc,argv);
+ else if(!_stricmp(action,"remove"))
+ res = do_remove(argc,argv);
+ else if(!_stricmp(action,"list"))
+ res = do_list(argc,argv);
+ else if(!_stricmp(action,"start") ||
+ !_stricmp(action,"start_disabled") ||
+ !_stricmp(action,"stop") ||
+ !_stricmp(action,"enable") ||
+ !_stricmp(action,"disable"))
+ res = do_manage(argc,argv);
+ else if(_stricmp(action,"?") &&
+ _stricmp(action,"/?") &&
+ _stricmp(action,"-?") &&
+ *action != 'h' &&
+ *action != 'H') {
fprintf(stderr,"%s: action %s not implemented.\n",argv[0],action);
- do_usage(argv[0]);
- return 1;
+ do_usage(argv[0]);
+ res = 1;
+ } else {
+ do_usage(argv[0]);
+ res = 0;
+ }
+ release_lock();
+ return res;
}
diff --git a/erts/etc/win32/erlsrv/erlsrv_interactive.h b/erts/etc/win32/erlsrv/erlsrv_interactive.h
index deacf81899..23e69e508d 100644
--- a/erts/etc/win32/erlsrv/erlsrv_interactive.h
+++ b/erts/etc/win32/erlsrv/erlsrv_interactive.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* 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
@@ -19,6 +19,8 @@
#ifndef _ERLSRV_INTERACTIVE_H
#define _ERLSRV_INTERACTIVE_H
+#define ERLSRV_INTERACTIVE_GLOBAL_SEMAPHORE "{468d6954-e355-415f-968f-d257cb0feef4}"
+
int interactive_main(int argc, char **argv);
#endif /* _ERLSRV_INTERACTIVE_H */
diff --git a/erts/etc/win32/erlsrv/erlsrv_service.c b/erts/etc/win32/erlsrv/erlsrv_service.c
index a58ee862c5..242e2905a9 100644
--- a/erts/etc/win32/erlsrv/erlsrv_service.c
+++ b/erts/etc/win32/erlsrv/erlsrv_service.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* 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
@@ -523,7 +523,7 @@ static BOOL start_a_service(ServerInfo *srvi){
srvi->keys[WorkDir].data.bytes : NULL,
&start,
&(srvi->info))){
- sprintf(errbuff,"Could not start erlang service"
+ sprintf(errbuff,"Could not start erlang service "
"with commandline \"%s\".",
service_name,
execbuff
@@ -924,7 +924,7 @@ static VOID WINAPI service_main_loop(DWORD argc, char **argv){
} else {
DWORD ecode = NO_ERROR;
if(success_wait == NO_SUCCESS_WAIT){
- log_warning("Erlang machine volountarily stopped. "
+ log_warning("Erlang machine voluntarily stopped. "
"The service is not restarted as OnFail "
"is set to ignore.");
} else {
diff --git a/erts/etc/win32/nsis/Makefile b/erts/etc/win32/nsis/Makefile
index ebb3ad9a96..ae2343b420 100644
--- a/erts/etc/win32/nsis/Makefile
+++ b/erts/etc/win32/nsis/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2009. All Rights Reserved.
+# Copyright Ericsson AB 2003-2011. All Rights Reserved.
#
# 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
@@ -45,6 +45,7 @@ WTARGET_DIR=$(shell (cygpath -d $(TARGET_DIR) 2>/dev/null || cygpath -d $(TARGET
REDIST_FILE=$(shell (sh ./find_redist.sh || echo ""))
REDIST_DLL_VERSION=$(shell (sh ./dll_version_helper.sh || echo ""))
+REDIST_DLL_NAME=$(shell (sh ./dll_version_helper.sh -n || echo ""))
release_spec:
@NSIS_VER=`makensis /hdrinfo | head -1 | awk '{print $$2}'`; \
@@ -73,6 +74,7 @@ release_spec:
cp $(REDIST_FILE) $(RELEASE_PATH)/vcredist_x86.exe;\
echo '!define HAVE_REDIST_FILE 1' >> $(VERSION_HEADER); \
echo '!define REDIST_DLL_VERSION "$(REDIST_DLL_VERSION)"' >> $(VERSION_HEADER);\
+ echo '!define REDIST_DLL_NAME "$(REDIST_DLL_NAME)"' >> $(VERSION_HEADER);\
fi;\
if [ -f $(RELEASE_PATH)/docs/doc/index.html ];\
then \
diff --git a/erts/etc/win32/nsis/dll_version_helper.sh b/erts/etc/win32/nsis/dll_version_helper.sh
index e0047dea8b..eecd4a72b5 100755
--- a/erts/etc/win32/nsis/dll_version_helper.sh
+++ b/erts/etc/win32/nsis/dll_version_helper.sh
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2007-2009. All Rights Reserved.
+# Copyright Ericsson AB 2007-2011. All Rights Reserved.
#
# 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
@@ -26,6 +26,7 @@
# exit 0
cat > hello.c <<EOF
+#include <windows.h>
#include <stdio.h>
int main(void)
@@ -35,15 +36,81 @@ int main(void)
}
EOF
-cl /MD hello.c > /dev/null 2>&1
+cl /MD hello.c > /dev/null 2>&1
if [ '!' -f hello.exe.manifest ]; then
- echo "This compiler does not generate manifest files - OK if using mingw" >&2
- exit 0
+ # Gah - VC 2010 changes the way it handles DLL's and manifests... Again...
+ # need another way of getting the version
+ DLLNAME=`dumpbin.exe /imports hello.exe | egrep MSVCR.*dll`
+ DLLNAME=`echo $DLLNAME`
+ cat > helper.c <<EOF
+#include <windows.h>
+#include <stdio.h>
+
+#define REQ_MODULE "$DLLNAME"
+
+int main(void)
+{
+ DWORD dummy;
+ DWORD versize;
+ int i,n;
+ unsigned char *versinfo;
+ char buff[100];
+
+ char *vs_verinfo;
+ unsigned int vs_ver_size;
+
+ struct LANGANDCODEPAGE {
+ WORD language;
+ WORD codepage;
+ } *translate;
+
+ unsigned int tr_size;
+
+ if (!(versize = GetFileVersionInfoSize(REQ_MODULE,&dummy))) {
+ fprintf(stderr,"No version info size in %s!\n",REQ_MODULE);
+ exit(1);
+ }
+ versinfo=malloc(versize);
+ if (!GetFileVersionInfo(REQ_MODULE,dummy,versize,versinfo)) {
+ fprintf(stderr,"No version info in %s!\n",REQ_MODULE);
+ exit(2);
+ }
+ if (!VerQueryValue(versinfo,"\\\\VarFileInfo\\\\Translation",&translate,&tr_size)) {
+ fprintf(stderr,"No translation info in %s!\n",REQ_MODULE);
+ exit(3);
+ }
+ n = tr_size/sizeof(translate);
+ for(i=0; i < n; ++i) {
+ sprintf(buff,"\\\\StringFileInfo\\\\%04x%04x\\\\FileVersion",
+ translate[i].language,translate[i].codepage);
+ if (VerQueryValue(versinfo,buff,&vs_verinfo,&vs_ver_size)) {
+ printf("%s\n",(char *) vs_verinfo);
+ return 0;
+ }
+ }
+ fprintf(stderr,"Failed to find file version of %s\n",REQ_MODULE);
+ return 0;
+}
+EOF
+ cl /MD helper.c version.lib > /dev/null 2>&1
+ if [ '!' -f helper.exe ]; then
+ echo "Failed to build helper program." >&2
+ exit 1
+ fi
+ NAME=$DLLNAME
+ VERSION=`./helper`
+else
+ VERSION=`grep '<assemblyIdentity' hello.exe.manifest | sed 's,.*version=.\([0-9\.]*\).*,\1,g' | grep -v '<'`
+ NAME=`grep '<assemblyIdentity' hello.exe.manifest | sed 's,.*name=.[A-Za-z\.]*\([0-9]*\).*,msvcr\1.dll,g' | grep -v '<'`
+fi
+#rm -f hello.c hello.obj hello.exe hello.exe.manifest helper.c helper.obj helper.exe helper.exe.manifest
+if [ "$1" = "-n" ]; then
+ ASKEDFOR=$NAME
+else
+ ASKEDFOR=$VERSION
fi
-VERSION=`grep '<assemblyIdentity' hello.exe.manifest | sed 's,.*version=.\([0-9\.]*\).*,\1,g' | grep -v '<'`
-rm -f hello.c hello.obj hello.exe hello.exe.manifest
-if [ -z "$VERSION" ]; then
+if [ -z "$ASKEDFOR" ]; then
exit 1
fi
-echo $VERSION
+echo $ASKEDFOR
exit 0
diff --git a/erts/etc/win32/nsis/erlang20.nsi b/erts/etc/win32/nsis/erlang20.nsi
index 43e5d91604..941e8e6f5d 100644
--- a/erts/etc/win32/nsis/erlang20.nsi
+++ b/erts/etc/win32/nsis/erlang20.nsi
@@ -311,23 +311,23 @@ FunctionEnd
Function .onInit
SectionGetFlags 0 $MYTEMP
-; MessageBox MB_YESNO "Found $SYSDIR\msvcr80.dll" IDYES FoundLbl
- IfFileExists $SYSDIR\msvcr80.dll MaybeFoundInSystemLbl
+ ;MessageBox MB_YESNO "Found $SYSDIR\${REDIST_DLL_NAME}" IDYES FoundLbl
+ IfFileExists $SYSDIR\${REDIST_DLL_NAME} MaybeFoundInSystemLbl
SearchSxsLbl:
FindFirst $0 $1 $WINDIR\WinSxS\x86*
LoopLbl:
StrCmp $1 "" NotFoundLbl
- IfFileExists $WINDIR\WinSxS\$1\msvcr80.dll MaybeFoundInSxsLbl
+ IfFileExists $WINDIR\WinSxS\$1\${REDIST_DLL_NAME} MaybeFoundInSxsLbl
FindNext $0 $1
Goto LoopLbl
MaybeFoundInSxsLbl:
- GetDllVersion $WINDIR\WinSxS\$1\msvcr80.dll $R0 $R1
+ GetDllVersion $WINDIR\WinSxS\$1\${REDIST_DLL_NAME} $R0 $R1
Call DllVersionGoodEnough
FindNext $0 $1
IntCmp 2 $R0 LoopLbl
Goto FoundLbl
MaybeFoundInSystemLbl:
- GetDllVersion $SYSDIR\msvcr80.dll $R0 $R1
+ GetDllVersion $SYSDIR\${REDIST_DLL_NAME} $R0 $R1
Call DllVersionGoodEnough
IntCmp 2 $R0 SearchSxSLbl
FoundLbl:
diff --git a/erts/etc/win32/nsis/find_redist.sh b/erts/etc/win32/nsis/find_redist.sh
index c5572839c5..bc4260ecba 100755
--- a/erts/etc/win32/nsis/find_redist.sh
+++ b/erts/etc/win32/nsis/find_redist.sh
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2007-2009. All Rights Reserved.
+# Copyright Ericsson AB 2007-2011. All Rights Reserved.
#
# 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
@@ -107,16 +107,81 @@ for x in cl bin vc; do
fi
BPATH="$NBPATH"
done
-#echo $BPATH
-for x in sdk v2.0 bootstrapper packages vcredist_x86 vcredist_x86.exe; do
- #echo "x=$x"
- #echo "BPATH=$BPATH"
- NBPATH=`add_path_element $x "$BPATH"`
- if [ "$NBPATH" = "$BPATH" ]; then
- echo "Failed to locate vcredist_x86.exe because directory structure was unexpected" >&2
- exit 3
+BPATH_LIST=$BPATH
+
+# rc.exe is in the Microsoft SDK directory of VS2008
+RCPATH=`lookup_prog_in_path rc`
+fail=false
+if [ '!' -z "$RCPATH" ]; then
+ BPATH=$RCPATH
+ allow_fail=false
+ for x in rc bin @ANY v6.0A v7.0A v7.1; do
+ if [ $x = @ANY ]; then
+ allow_fail=true
+ else
+ NBPATH=`remove_path_element $x "$BPATH"`
+ if [ $allow_fail = false -a "$NBPATH" = "$BPATH" ]; then
+ fail=true
+ break;
+ fi
+ BPATH="$NBPATH"
+ fi
+ done
+ if [ $fail = false ]; then
+ BPATH_LIST="$BPATH_LIST $BPATH"
+ fi
+fi
+
+# Frantic search through two roots with different
+# version directories. We want to be very specific about the
+# directory structures as we wouldnt want to find the wrong
+# redistributables...
+
+#echo $BPATH_LIST
+for BP in $BPATH_LIST; do
+ for verdir in "sdk v2.0" "sdk v3.5" "v6.0A" "v7.0" "v7.0A" "v7.1"; do
+ BPATH=$BP
+ fail=false
+ allow_fail=false
+ for x in $verdir @ANY bootstrapper packages vcredist_x86 Redist VC @ALL vcredist_x86.exe; do
+ #echo "x=$x"
+ #echo "BPATH=$BPATH"
+ #echo "allow_fail=$allow_fail"
+ if [ $x = @ANY ]; then
+ allow_fail=true
+ elif [ $x = @ALL ]; then
+ allow_fail=false
+ else
+ NBPATH=`add_path_element $x "$BPATH"`
+ if [ $allow_fail = false -a "$NBPATH" = "$BPATH" ]; then
+ fail=true
+ break;
+ fi
+ BPATH="$NBPATH"
+ fi
+ done
+ if [ $fail = false ]; then
+ break;
+ fi
+ done
+ if [ $fail = false ]; then
+ echo $BPATH
+ exit 0
fi
- BPATH="$NBPATH"
done
-echo $BPATH
-exit 0 \ No newline at end of file
+
+# shortcut for locating vcredist_x86.exe is to put it into $ERL_TOP
+if [ -f $ERL_TOP/vcredist_x86.exe ]; then
+ echo $ERL_TOP/vcredist_x86.exe
+ exit 0
+fi
+
+# or $ERL_TOP/.. to share across multiple builds
+if [ -f $ERL_TOP/../vcredist_x86.exe ]; then
+ echo $ERL_TOP/../vcredist_x86.exe
+ exit 0
+fi
+
+echo "Failed to locate vcredist_x86.exe because directory structure was unexpected" >&2
+exit 3
+
diff --git a/erts/etc/win32/start_erl.c b/erts/etc/win32/start_erl.c
index dcf8c8b281..28c8e55bd3 100644
--- a/erts/etc/win32/start_erl.c
+++ b/erts/etc/win32/start_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2011. All Rights Reserved.
*
* 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
@@ -44,6 +44,8 @@ char *progname;
#endif
#define RELEASE_SUBDIR "\\releases"
+#define ERTS_SUBDIR_PREFIX "\\erts-"
+#define BIN_SUBDIR "\\bin"
#define REGISTRY_BASE "Software\\Ericsson\\Erlang\\"
#define DEFAULT_DATAFILE "start_erl.data"
@@ -101,7 +103,8 @@ void exit_help(char *err)
printf("Usage:\n%s\n"
" [<erlang options>] ++\n"
" [-data <datafile>]\n"
- " [-reldir <releasedir>]\n"
+ " {-rootdir <erlang root directory> | \n"
+ " -reldir <releasedir>}\n"
" [-bootflags <bootflagsfile>]\n"
" [-noconfig]\n", progname);
@@ -177,8 +180,9 @@ void split_commandline(void)
*/
char * unquote_optionarg(char *str, char **strp)
{
- char *newstr = (char *)malloc(strlen(str)+1); /* This one is realloc:ed later */
- int i=0, inquote=0;
+ char *newstr = (char *)malloc(strlen(str)+1); /* This one is
+ realloc:ed later */
+ int i = 0, inquote = 0;
assert(newstr);
assert(str);
@@ -223,8 +227,8 @@ char * unquote_optionarg(char *str, char **strp)
/*
- * Parses MyCommandLine and tries to fill in all the required option variables
- * (one way or another).
+ * Parses MyCommandLine and tries to fill in all the required option
+ * variables (in one way or another).
*/
void parse_commandline(void)
{
@@ -237,6 +241,11 @@ void parse_commandline(void)
*cmdline++;
if( strnicmp(cmdline, "data", 4) == 0) {
DataFileName = unquote_optionarg(cmdline+4, &cmdline);
+ } else if( strnicmp(cmdline, "rootdir", 7) == 0) {
+ RootDir = unquote_optionarg(cmdline+7, &cmdline);
+#ifdef _DEBUG
+ fprintf(stderr, "RootDir: '%s'\n", RootDir);
+#endif
} else if( strnicmp(cmdline, "reldir", 6) == 0) {
RelDir = unquote_optionarg(cmdline+6, &cmdline);
#ifdef _DEBUG
@@ -266,8 +275,8 @@ void parse_commandline(void)
* Read the data file specified and get the version and release number
* from it.
*
- * This function also construct the correct RegistryKey from the version information
- * retrieved.
+ * This function also construct the correct RegistryKey from the version
+ * information retrieved.
*/
void read_datafile(void)
{
@@ -325,88 +334,6 @@ void read_datafile(void)
/*
- * Read the registry keys we need
- */
-void read_registry_keys(void)
-{
- HKEY hReg;
- ULONG lLen;
-
- /* Create the RegistryKey name */
- RegistryKey = (char *) malloc(strlen(REGISTRY_BASE) +
- strlen(Version) + 1);
- assert(RegistryKey);
- sprintf(RegistryKey, REGISTRY_BASE "%s", Version);
-
- /* We always need to find BinDir */
- if( (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- RegistryKey,
- 0,
- KEY_READ,
- &hReg)) != ERROR_SUCCESS ) {
- exit_help("Could not open registry key.");
- }
-
- /* First query size of data */
- if( (RegQueryValueEx(hReg,
- "Bindir",
- NULL,
- NULL,
- NULL,
- &lLen)) != ERROR_SUCCESS) {
- exit_help("Failed to query BinDir of release.\n");
- }
-
- /* Allocate enough space */
- BinDir = (char *)malloc(lLen+1);
- assert(BinDir);
- /* Retrieve the value */
- if( (RegQueryValueEx(hReg,
- "Bindir",
- NULL,
- NULL,
- (unsigned char *) BinDir,
- &lLen)) != ERROR_SUCCESS) {
- exit_help("Failed to query BinDir of release (2).\n");
- }
-
-#ifdef _DEBUG
- fprintf(stderr, "Bindir: '%s'\n", BinDir);
-#endif
-
- /* We also need the rootdir, in case we need to build RelDir later */
-
- /* First query size of data */
- if( (RegQueryValueEx(hReg,
- "Rootdir",
- NULL,
- NULL,
- NULL,
- &lLen)) != ERROR_SUCCESS) {
- exit_help("Failed to query RootDir of release.\n");
- }
-
- /* Allocate enough space */
- RootDir = (char *) malloc(lLen+1);
- assert(RootDir);
- /* Retrieve the value */
- if( (RegQueryValueEx(hReg,
- "Rootdir",
- NULL,
- NULL,
- (unsigned char *) RootDir,
- &lLen)) != ERROR_SUCCESS) {
- exit_help("Failed to query RootDir of release (2).\n");
- }
-
-#ifdef _DEBUG
- fprintf(stderr, "Rootdir: '%s'\n", RootDir);
-#endif
-
- RegCloseKey(hReg);
-}
-
-/*
* Read the bootflags. This file contains extra command line options to erl.exe
*/
void read_bootflags(void)
@@ -424,7 +351,8 @@ void read_bootflags(void)
exit_help("Need -reldir when -bootflags "
"filename has relative path.");
} else {
- newname = (char *)malloc(strlen(BootFlagsFile)+strlen(RelDir)+strlen(Release)+3);
+ newname = (char *)malloc(strlen(BootFlagsFile)+
+ strlen(RelDir)+strlen(Release)+3);
assert(newname);
sprintf(newname, "%s\\%s\\%s", RelDir, Release, BootFlagsFile);
free(BootFlagsFile);
@@ -436,8 +364,6 @@ void read_bootflags(void)
fprintf(stderr, "BootFlagsFile: '%s'\n", BootFlagsFile);
#endif
-
-
if( (fp=fopen(BootFlagsFile, "rb")) == NULL) {
exit_help("Could not open BootFlags file.");
}
@@ -605,32 +531,49 @@ void complete_options(void)
sz = nsz;
}
if (RelDir == NULL) {
- if(DataFileName){
- /* Needs to be absolute for this to work, but we
- can try... */
- read_datafile();
- read_registry_keys();
- } else {
- /* Impossible to find all data... */
- exit_help("Need either Release directory or an absolute "
- "datafile name.");
- }
- /* Ok, construct our own RelDir from RootDir */
- RelDir = (char *) malloc(strlen(RootDir)+strlen(RELEASE_SUBDIR)+1);
- assert(RelDir);
- sprintf(RelDir, "%s" RELEASE_SUBDIR, RootDir);
+ if (!RootDir) {
+ /* Impossible to find all data... */
+ exit_help("Need either Root directory nor Release directory.");
+ }
+ /* Ok, construct our own RelDir from RootDir */
+ RelDir = (char *) malloc(strlen(RootDir)+strlen(RELEASE_SUBDIR)+1);
+ assert(RelDir);
+ sprintf(RelDir, "%s" RELEASE_SUBDIR, RootDir);
+ read_datafile();
} else {
read_datafile();
- read_registry_keys();
}
} else {
read_datafile();
- read_registry_keys();
}
+ if( !RootDir ) {
+ /* Try to construct RootDir from RelDir */
+ char *p;
+ RootDir = malloc(strlen(RelDir)+1);
+ strcpy(RootDir,RelDir);
+ p = RootDir+strlen(RootDir)-1;
+ if (p >= RootDir && (*p == '/' || *p == '\\'))
+ --p;
+ while (p >= RootDir && *p != '/' && *p != '\\')
+ --p;
+ if (p <= RootDir) { /* Empty RootDir is also an error */
+ exit_help("Cannot determine Root directory from "
+ "Release directory.");
+ }
+ *p = '\0';
+ }
+
+
+ BinDir = (char *) malloc(strlen(RootDir)+strlen(ERTS_SUBDIR_PREFIX)+
+ strlen(Version)+strlen(BIN_SUBDIR)+1);
+ assert(BinDir);
+ sprintf(BinDir, "%s" ERTS_SUBDIR_PREFIX "%s" BIN_SUBDIR, RootDir, Version);
+
read_bootflags();
#ifdef _DEBUG
fprintf(stderr, "RelDir: '%s'\n", RelDir);
+ fprintf(stderr, "BinDir: '%s'\n", BinDir);
#endif
}