aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/src/prog
diff options
context:
space:
mode:
Diffstat (limited to 'lib/erl_interface/src/prog')
-rw-r--r--lib/erl_interface/src/prog/ei_fake_prog.c303
-rw-r--r--lib/erl_interface/src/prog/erl_call.c906
-rw-r--r--lib/erl_interface/src/prog/erl_fake_prog.c250
-rw-r--r--lib/erl_interface/src/prog/erl_start.c735
-rw-r--r--lib/erl_interface/src/prog/erl_start.h46
5 files changed, 2240 insertions, 0 deletions
diff --git a/lib/erl_interface/src/prog/ei_fake_prog.c b/lib/erl_interface/src/prog/ei_fake_prog.c
new file mode 100644
index 0000000000..68eb537211
--- /dev/null
+++ b/lib/erl_interface/src/prog/ei_fake_prog.c
@@ -0,0 +1,303 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. 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%
+ */
+
+/***************************************************************************
+ *
+ * This is a fake program that contains all functions, variables and
+ * defined symbols mentioned in the manual. We compile this file to see
+ * that the header files and created library is complete.
+ *
+ * You can't run this program, it is for compiling and linking only.
+ *
+ ***************************************************************************/
+
+/* This is a link and header file test. Including "ei.h" and linking
+ with libei.a should be enough */
+
+/* Use most of
+ * CFLAGS="-I../include -g -O2
+ * -ansi -pedantic
+ * -Wall
+ * -Wshadow
+ * -Wstrict-prototypes
+ * -Wmissing-prototypes
+ * -Wmissing-declarations
+ * -Wnested-externs
+ * -Winline
+ * -Werror"
+ */
+
+/* An exception from using eidef.h, use config.h directly */
+#include "config.h"
+
+#if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP)
+#include <gmp.h>
+#endif /* HAVE_GMP_H && HAVE_LIBGMP */
+
+/* #include <netdb.h> now included by ei.h */
+#include "ei.h"
+
+#ifdef VXWORKS
+int ei_fake_prog_main(void)
+#else
+int main(void)
+#endif
+{
+ ErlConnect conp;
+ Erl_IpAddr thisipaddr = (Erl_IpAddr)0;
+ FILE *fp = (FILE *)0;
+ char* charp = "foo";
+ double *doublep = NULL;
+ double doublex = 0.0;
+ ei_cnode xec;
+ ei_reg *ei_regp = NULL;
+ ei_term eterm;
+ ei_x_buff eix;
+ erlang_big *bigp = NULL;
+ erlang_fun efun;
+ erlang_msg *msgp = NULL;
+ erlang_msg emsg;
+ erlang_pid *pidp = NULL;
+ erlang_pid epid;
+ erlang_port eport;
+ erlang_ref eref;
+ erlang_trace etrace;
+ int *intp = NULL;
+ int intx = 0;
+ long *longp = NULL;
+ long longx = 0;
+ short creation = 0;
+ struct ei_reg_stat *ei_reg_statp = NULL;
+ struct ei_reg_tabstat *ei_reg_tabstatp = NULL;
+ struct hostent *hostp = NULL;
+ unsigned char * ucharp = (unsigned char *)"foo";
+ unsigned long *ulongp = NULL;
+ unsigned long ulongx = 0;
+ void *voidp = NULL;
+#ifndef VXWORKS
+ EI_LONGLONG *longlongp = (EI_LONGLONG*)NULL;
+ EI_LONGLONG longlongx = 0;
+ EI_ULONGLONG *ulonglongp = (EI_ULONGLONG*)NULL;
+ EI_ULONGLONG ulonglongx = 0;
+#endif
+
+ intx = erl_errno;
+
+ ei_connect_init(&xec, charp, charp, creation);
+ ei_connect_xinit (&xec, charp, charp, charp, thisipaddr, charp, creation);
+
+ ei_connect(&xec, charp);
+ ei_xconnect (&xec, thisipaddr, charp);
+
+ ei_receive(intx, ucharp, intx);
+ ei_receive_msg(intx, &emsg, &eix);
+ ei_xreceive_msg(intx, &emsg, &eix);
+
+ ei_send(intx, &epid, charp, intx);
+ ei_reg_send(&xec, intx, charp, charp, intx);
+
+ ei_rpc(&xec, intx, charp, charp, charp, intx, &eix);
+ ei_rpc_to(&xec, intx, charp, charp, charp, intx);
+ ei_rpc_from(&xec, intx, intx, &emsg, &eix);
+
+ ei_publish(&xec, intx);
+ ei_accept(&xec, intx, &conp);
+ ei_unpublish(&xec);
+
+ ei_thisnodename(&xec);
+ ei_thishostname(&xec);
+ ei_thisalivename(&xec);
+
+ ei_self(&xec);
+
+ ei_gethostbyname(charp);
+ ei_gethostbyaddr(charp, intx, intx);
+ ei_gethostbyname_r(charp, hostp, charp, intx, intp);
+ ei_gethostbyaddr_r(charp, intx, intx, hostp, charp, intx, intp);
+
+ ei_encode_version(charp, intp);
+ ei_x_encode_version(&eix);
+ ei_encode_long(charp, intp, longx);
+ ei_x_encode_long(&eix, longx);
+ ei_encode_ulong(charp, intp, ulongx);
+ ei_x_encode_ulong(&eix, ulongx);
+ ei_encode_double(charp, intp, doublex);
+ ei_x_encode_double(&eix, doublex);
+ ei_encode_boolean(charp, intp, intx);
+ ei_x_encode_boolean(&eix, intx);
+ ei_encode_char(charp, intp, 'a');
+ ei_x_encode_char(&eix, 'a');
+ ei_encode_string(charp, intp, charp);
+ ei_encode_string_len(charp, intp, charp, intx);
+ ei_x_encode_string(&eix, charp);
+ ei_x_encode_string_len(&eix, charp, intx);
+ ei_encode_atom(charp, intp, charp);
+ ei_encode_atom_len(charp, intp, charp, intx);
+ ei_x_encode_atom(&eix, charp);
+ ei_x_encode_atom_len(&eix, charp, intx);
+ ei_encode_binary(charp, intp, (void *)0, longx);
+ ei_x_encode_binary(&eix, (void*)0, intx);
+ ei_encode_pid(charp, intp, &epid);
+ ei_x_encode_pid(&eix, &epid);
+ ei_encode_fun(charp, intp, &efun);
+ ei_x_encode_fun(&eix, &efun);
+ ei_encode_port(charp, intp, &eport);
+ ei_x_encode_port(&eix, &eport);
+ ei_encode_ref(charp, intp, &eref);
+ ei_x_encode_ref(&eix, &eref);
+ ei_encode_trace(charp, intp, &etrace);
+ ei_x_encode_trace(&eix, &etrace);
+ ei_encode_tuple_header(charp, intp, intx);
+ ei_x_encode_tuple_header(&eix, longx);
+ ei_encode_list_header(charp, intp, intx);
+ ei_x_encode_list_header(&eix, longx);
+/* #define ei_encode_empty_list(buf,i) ei_encode_list_header(buf,i,0) */
+ ei_x_encode_empty_list(&eix);
+
+ ei_get_type(charp, intp, intp, intp);
+ ei_get_type_internal(charp, intp, intp, intp);
+
+ ei_decode_version(charp, intp, intp);
+ ei_decode_long(charp, intp, longp);
+ ei_decode_ulong(charp, intp, ulongp);
+ ei_decode_double(charp, intp, doublep);
+ ei_decode_boolean(charp, intp, intp);
+ ei_decode_char(charp, intp, charp);
+ ei_decode_string(charp, intp, charp);
+ ei_decode_atom(charp, intp, charp);
+ ei_decode_binary(charp, intp, (void *)0, longp);
+ ei_decode_fun(charp, intp, &efun);
+ free_fun(&efun);
+ ei_decode_pid(charp, intp, &epid);
+ ei_decode_port(charp, intp, &eport);
+ ei_decode_ref(charp, intp, &eref);
+ ei_decode_trace(charp, intp, &etrace);
+ ei_decode_tuple_header(charp, intp, intp);
+ ei_decode_list_header(charp, intp, intp);
+
+ ei_decode_ei_term(charp, intp, &eterm);
+
+ ei_print_term(fp, charp, intp);
+ ei_s_print_term(&charp, charp, intp);
+
+ ei_x_format(&eix, charp);
+ ei_x_format_wo_ver(&eix, charp);
+
+ ei_x_new(&eix);
+ ei_x_new_with_version(&eix);
+ ei_x_free(&eix);
+ ei_x_append(&eix, &eix);
+ ei_x_append_buf(&eix, charp, intx);
+ ei_skip_term(charp, intp);
+
+ ei_reg_open(intx);
+ ei_reg_resize(ei_regp, intx);
+ ei_reg_close(ei_regp);
+
+ ei_reg_setival(ei_regp, charp, longx);
+ ei_reg_setfval(ei_regp, charp, doublex);
+ ei_reg_setsval(ei_regp, charp, charp);
+ ei_reg_setpval(ei_regp, charp, voidp, intx);
+
+ ei_reg_setval(ei_regp, charp, intx);
+
+ ei_reg_getival(ei_regp, charp);
+ ei_reg_getfval(ei_regp, charp);
+ ei_reg_getsval(ei_regp, charp);
+ ei_reg_getpval(ei_regp, charp, intp);
+
+ ei_reg_getval(ei_regp, charp, intx);
+
+ ei_reg_markdirty(ei_regp, charp);
+
+ ei_reg_delete(ei_regp, charp);
+
+ ei_reg_stat(ei_regp, charp, ei_reg_statp);
+
+ ei_reg_tabstat(ei_regp, ei_reg_tabstatp);
+
+ ei_reg_dump(intx, ei_regp, charp, intx);
+ ei_reg_restore(intx, ei_regp, charp);
+ ei_reg_purge(ei_regp);
+
+#if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP)
+ {
+ mpz_t obj;
+ ei_decode_bignum(charp, intp, obj);
+ ei_encode_bignum(charp, intp, obj);
+ ei_x_encode_bignum(&eix, obj);
+ }
+#endif /* HAVE_GMP_H && HAVE_LIBGMP */
+
+#ifndef VXWORKS
+
+ ei_decode_longlong(charp, intp, longlongp);
+ ei_decode_ulonglong(charp, intp, ulonglongp);
+ ei_encode_longlong(charp, intp, longlongx);
+ ei_encode_ulonglong(charp, intp, ulonglongx);
+ ei_x_encode_longlong(&eix, longlongx);
+ ei_x_encode_ulonglong(&eix, ulonglongx);
+
+#endif
+
+#ifdef USE_EI_UNDOCUMENTED
+
+ ei_decode_intlist(charp, intp, longp, intp);
+
+ ei_receive_encoded(intx, &charp, intp, msgp, intp);
+ ei_send_encoded(intx, pidp, charp, intx);
+ ei_send_reg_encoded(intx, pidp, charp, charp, intx);
+
+ ei_decode_big(charp, intp, bigp);
+ ei_big_comp(bigp, bigp);
+ ei_big_to_double(bigp, doublep);
+ ei_small_to_big(intx, bigp);
+ ei_alloc_big(intx);
+ ei_free_big(bigp);
+
+#endif /* USE_EI_UNDOCUMENTED */
+
+ return
+ BUFSIZ +
+ EAGAIN +
+ EHOSTUNREACH +
+ EIO +
+ EI_BIN +
+ EI_DELET +
+ EI_DIRTY +
+ EI_FLT +
+ EI_FORCE +
+ EI_INT +
+ EI_NOPURGE +
+ EI_STR +
+ EMSGSIZE +
+ ENOMEM +
+ ERL_ERROR +
+ ERL_EXIT +
+ ERL_LINK +
+ ERL_MSG +
+ ERL_NO_TIMEOUT +
+ ERL_REG_SEND +
+ ERL_SEND +
+ ERL_TICK +
+ ERL_TIMEOUT +
+ ERL_UNLINK +
+ ETIMEDOUT +
+ MAXATOMLEN;
+}
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
new file mode 100644
index 0000000000..f0d638324d
--- /dev/null
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -0,0 +1,906 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1996-2009. 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%
+ *
+
+ */
+/*
+ * Function: Makes it possible to send and receive Erlang
+ * messages from the (Unix) command line.
+ * Note: We don't free any memory at all since we only
+ * live for a short while.
+ *
+ */
+
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <direct.h>
+#include <windows.h>
+#include <winbase.h>
+
+#elif VXWORKS
+
+#include <stdio.h>
+#include <string.h>
+#include <vxWorks.h>
+#include <hostLib.h>
+#include <selectLib.h>
+#include <ifLib.h>
+#include <sockLib.h>
+#include <taskLib.h>
+#include <inetLib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <time.h>
+
+#else /* unix */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <netdb.h>
+#include <sys/times.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "ei.h"
+#include "ei_resolve.h"
+#include "erl_start.h" /* FIXME remove dependency */
+
+#ifdef __WIN32__
+static void initWinSock(void);
+#endif
+
+/*
+ * Some nice global variables
+ * (I don't think "nice" is the right word actually... -gordon)
+ */
+/* FIXME problem for threaded ? */
+
+struct call_flags {
+ int startp;
+ int cookiep;
+ int modp;
+ int evalp;
+ int randomp;
+ int use_long_name; /* indicates if -name was used, else -sname or -n */
+ int debugp;
+ int verbosep;
+ int haltp;
+ char *cookie;
+ char *node;
+ char *hidden;
+ char *apply;
+ char *script;
+};
+
+static void usage_arg(const char *progname, const char *switchname);
+static void usage_error(const char *progname, const char *switchname);
+static void usage(const char *progname);
+static int get_module(char **mbuf, char **mname);
+static struct hostent* get_hostent(char *host);
+static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags);
+static int read_stdin(char **buf);
+static void split_apply_string(char *str, char **mod,
+ char **fun, char **args);
+
+
+/***************************************************************************
+ *
+ * XXXXX
+ *
+ ***************************************************************************/
+
+/* FIXME isn't VxWorks to handle arguments differently? */
+/* FIXME check errors from malloc */
+
+#if !defined(VXWORKS)
+int main(int argc, char *argv[])
+#else
+int erl_call(int argc, char **argv)
+#endif
+{
+ int i = 1,fd,creation;
+ struct hostent *hp;
+ char host_name[EI_MAXHOSTNAMELEN+1];
+ char nodename[MAXNODELEN+1];
+ char *p = NULL;
+ char *ct = NULL; /* temporary used when truncating nodename */
+ int modsize = 0;
+ char *host = NULL;
+ char *module = NULL;
+ char *modname = NULL;
+ struct call_flags flags = {0}; /* Default 0 and NULL in all fields */
+ char* progname = argv[0];
+ ei_cnode ec;
+
+ /* Get the command line options */
+ while (i < argc) {
+ if (argv[i][0] != '-') {
+ usage_error(progname, argv[i]);
+ }
+
+ if (strcmp(argv[i], "-sname") == 0) { /* -sname NAME */
+ if (i+1 >= argc) {
+ usage_arg(progname, "-sname ");
+ }
+
+ flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
+ strcpy(flags.node, argv[i+1]);
+ i++;
+ flags.use_long_name = 0;
+ } else if (strcmp(argv[i], "-name") == 0) { /* -name NAME */
+ if (i+1 >= argc) {
+ usage_arg(progname, "-name ");
+ }
+
+ flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
+ strcpy(flags.node, argv[i+1]);
+ i++;
+ flags.use_long_name = 1;
+ } else {
+ if (strlen(argv[i]) != 2) {
+ usage_error(progname, argv[i]);
+ }
+
+ switch (argv[i][1]) {
+ case 's':
+ flags.startp = 1;
+ break;
+ case 'q':
+ flags.haltp = 1;
+ break;
+ case 'v':
+ flags.verbosep = 1;
+ break;
+ case 'd':
+ flags.debugp = 1;
+ break;
+ case 'r':
+ flags.randomp = 1;
+ break;
+ case 'e':
+ flags.evalp = 1;
+ break;
+ case 'm':
+ flags.modp = 1;
+ break;
+ case 'c':
+ if (i+1 >= argc) {
+ usage_arg(progname, "-c ");
+ }
+ flags.cookiep = 1;
+ flags.cookie = (char *) malloc(strlen(argv[i+1]) + 1);
+ strcpy(flags.cookie, argv[i+1]);
+ i++;
+ break;
+ case 'n':
+ if (i+1 >= argc) {
+ usage_arg(progname, "-n ");
+ }
+ flags.node = (char *) malloc(strlen(argv[i+1]) + 1);
+ strcpy(flags.node, argv[i+1]);
+ flags.use_long_name = 1;
+ i++;
+ break;
+ case 'h':
+ if (i+1 >= argc) {
+ usage_arg(progname, "-h ");
+ }
+ flags.hidden = (char *) malloc(strlen(argv[i+1]) + 1);
+ strcpy(flags.hidden, argv[i+1]);
+ i++;
+ break;
+ case 'x':
+ if (i+1 >= argc) {
+ usage_arg(progname, "-x ");
+ }
+ flags.script = (char *) malloc(strlen(argv[i+1]) + 1);
+ strcpy(flags.script, argv[i+1]);
+ i++;
+ break;
+ case 'a':
+ if (i+1 >= argc) {
+ usage_arg(progname, "-a ");
+ }
+ flags.apply = (char *) malloc(strlen(argv[i+1]) + 1);
+ strcpy(flags.apply, argv[i+1]);
+ i++;
+ break;
+ case '?':
+ usage(progname);
+ default:
+ usage_error(progname, argv[i]);
+ }
+ }
+ i++;
+
+ } /* while */
+
+
+ /*
+ * Can't have them both !
+ */
+ if (flags.modp && flags.evalp) {
+ usage(progname);
+ }
+
+ /*
+ * Read an Erlang module from stdin.
+ */
+ if (flags.modp) {
+ modsize = get_module(&module, &modname);
+ }
+
+ if (flags.verbosep || flags.debugp) {
+ fprintf(stderr,"erl_call: "
+ "node = %s\nCookie = %s\n"
+ "flags = %s %s %s\n"
+ "module: name = %s , size = %d\n"
+ "apply = %s\n",
+ (flags.node ? flags.node : ""),
+ (flags.cookie ? flags.cookie : ""),
+ (flags.startp ? "startp" : ""),
+ (flags.verbosep ? "verbosep" : ""),
+ (flags.debugp ? "debugp" : ""),
+ (modname ? modname : ""), modsize,
+ (flags.apply ? flags.apply : "" ));
+ }
+
+ /*
+ * What we, at least, requires !
+ */
+ if (flags.node == NULL) {
+ usage(progname);
+ }
+
+ if (!flags.cookiep) {
+ flags.cookie = NULL;
+ }
+
+ /* FIXME decide how many bits etc or leave to connect_xinit? */
+ creation = (time(NULL) % 3) + 1; /* "random" */
+
+ if (flags.hidden == NULL) {
+ /* As default we are c17@gethostname */
+ i = flags.randomp ? (time(NULL) % 997) : 17;
+ /* FIXME allocates to small !!! */
+ flags.hidden = (char *) malloc(3 + 2 ); /* c17 or cXYZ */
+#if defined(VXWORKS)
+ sprintf(flags.hidden, "c%d",
+ i < 0 ? (int) taskIdSelf() : i);
+#else
+ sprintf(flags.hidden, "c%d",
+ i < 0 ? (int) getpid() : i);
+#endif
+ }
+ {
+ /* A name for our hidden node was specified */
+ char h_hostname[EI_MAXHOSTNAMELEN+1];
+ char h_nodename[MAXNODELEN+1];
+ char *h_alivename=flags.hidden;
+ struct in_addr h_ipadr;
+ char* ct;
+
+#ifdef __WIN32__
+ /*
+ * FIXME Extremly ugly, but needed to get ei_gethostbyname() below
+ * to work.
+ */
+ initWinSock();
+#endif
+
+ gethostname(h_hostname, EI_MAXHOSTNAMELEN);
+ if ((hp = ei_gethostbyname(h_hostname)) == 0) {
+ fprintf(stderr,"erl_call: can't resolve hostname %s\n", h_hostname);
+ exit(1);
+ }
+ /* If shortnames cut of the name at first '.' */
+ if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {
+ *ct = '\0';
+ }
+ strcpy(h_hostname, hp->h_name);
+ memcpy(&h_ipadr.s_addr, *hp->h_addr_list, sizeof(struct in_addr));
+ sprintf(h_nodename, "%s@%s", h_alivename, h_hostname);
+
+ if (ei_connect_xinit(&ec, h_hostname, h_alivename, h_nodename,
+ (Erl_IpAddr)&h_ipadr, flags.cookie,
+ (short) creation) < 0) {
+ fprintf(stderr,"erl_call: can't create C node %s; %d\n",
+ h_nodename, erl_errno);
+ exit(1);
+ }
+
+ }
+ if ((p = strchr((const char *)flags.node, (int) '@')) == 0) {
+ strcpy(host_name, ei_thishostname(&ec));
+ host = host_name;
+ } else {
+ *p = 0;
+ host = p+1;
+ }
+
+ /*
+ * Expand name to a real name (may be ip-address)
+ */
+ /* FIXME better error string */
+ if ((hp = get_hostent(host)) == 0) {
+ fprintf(stderr,"erl_call: can't get_hostent(%s)\n", host);
+ exit(1);
+ }
+ /* If shortnames cut of the name at first '.' */
+ if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) {
+ *ct = '\0';
+ }
+ strcpy(host_name, hp->h_name);
+ sprintf(nodename, "%s@%s", flags.node, host_name);
+
+ /*
+ * Try to connect. Start an Erlang system if the
+ * start option is on and no system is running.
+ */
+ if (flags.startp && !flags.haltp) {
+ fd = do_connect(&ec, nodename, &flags);
+ } else if ((fd = ei_connect(&ec, nodename)) < 0) {
+ /* We failed to connect ourself */
+ /* FIXME do we really know we failed because of node not up? */
+ if (flags.haltp) {
+ exit(0);
+ } else {
+ fprintf(stderr,"erl_call: failed to connect to node %s\n",
+ nodename);
+ exit(1);
+ }
+ }
+
+ /* If we are connected and the halt switch is set */
+ if (fd && flags.haltp) {
+ int i = 0;
+ char *p;
+ ei_x_buff reply;
+
+ ei_encode_empty_list(NULL, &i);
+
+ p = (char *)malloc(i);
+ i = 0; /* Reset */
+
+ ei_encode_empty_list(p, &i);
+
+ ei_x_new_with_version(&reply);
+
+ /* FIXME if fails we want to exit != 0 ? */
+ ei_rpc(&ec, fd, "erlang", "halt", p, i, &reply);
+ free(p);
+ ei_x_free(&reply);
+ exit(0);
+ }
+
+ if (flags.verbosep) {
+ fprintf(stderr,"erl_call: we are now connected to node \"%s\"\n",
+ nodename);
+ }
+
+ /*
+ * Compile the module read from stdin.
+ */
+ if (flags.modp && (modname != NULL)) {
+ char fname[256];
+
+ strcpy(fname, modname);
+ strcat(fname, ".erl");
+
+ /*
+ * ei_format("[~s,~w]", fname, erl_mk_binary(module, modsize));
+ */
+
+ {
+ int i = 0;
+ char *p;
+ ei_x_buff reply;
+
+ ei_encode_list_header(NULL, &i, 2);
+ ei_encode_string(NULL, &i, fname);
+ ei_encode_binary(NULL, &i, module, modsize);
+ ei_encode_empty_list(NULL, &i);
+
+ p = (char *)malloc(i);
+ i = 0; /* Reset */
+
+ ei_encode_list_header(p, &i, 2);
+ ei_encode_string(p, &i, fname);
+ ei_encode_binary(p, &i, module, modsize);
+ ei_encode_empty_list(p, &i);
+
+ ei_x_new_with_version(&reply);
+
+ if (ei_rpc(&ec, fd, "file", "write_file", p, i, &reply) < 0) {
+ free(p);
+ ei_x_free(&reply);
+ fprintf(stderr,"erl_call: can't write to source file %s\n",
+ fname);
+ exit(1);
+ }
+ free(p);
+ ei_x_free(&reply);
+ }
+
+ /* Compile AND load file on other node */
+
+ {
+ int i = 0;
+ char *p;
+ ei_x_buff reply;
+
+ ei_encode_list_header(NULL, &i, 2);
+ ei_encode_atom(NULL, &i, fname);
+ ei_encode_empty_list(NULL, &i);
+ ei_encode_empty_list(NULL, &i);
+
+ p = (char *)malloc(i);
+ i = 0; /* Reset */
+
+ ei_encode_list_header(p, &i, 2);
+ ei_encode_atom(p, &i, fname);
+ ei_encode_empty_list(p, &i);
+ ei_encode_empty_list(p, &i);
+
+ ei_x_new_with_version(&reply);
+
+ /* erl_format("[~a,[]]", modname) */
+
+ if (ei_rpc(&ec, fd, "c", "c", p, i, &reply) < 0) {
+ free(p);
+ ei_x_free(&reply);
+ fprintf(stderr,"erl_call: can't compile file %s\n", fname);
+ }
+ free(p);
+ /* FIXME complete this code
+ FIXME print out error message as term
+ if (!erl_match(erl_format("{ok,_}"), reply)) {
+ fprintf(stderr,"erl_call: compiler errors\n");
+ }
+ */
+ ei_x_free(&reply);
+ }
+
+ }
+ /*
+ * Eval the Erlang functions read from stdin/
+ */
+ if (flags.evalp) {
+ char *evalbuf;
+ int len;
+
+ len = read_stdin(&evalbuf);
+ {
+ int i = 0;
+ char *p;
+ ei_x_buff reply;
+
+ ei_encode_list_header(NULL, &i, 1);
+ ei_encode_binary(NULL, &i, evalbuf, len);
+ ei_encode_empty_list(NULL, &i);
+
+ p = (char *)malloc(i);
+ i = 0; /* Reset */
+
+ ei_encode_list_header(p, &i, 1);
+ ei_encode_binary(p, &i, evalbuf, len);
+ ei_encode_empty_list(p, &i);
+
+ ei_x_new_with_version(&reply);
+
+ /* erl_format("[~w]", erl_mk_binary(evalbuf,len))) */
+
+ if (ei_rpc(&ec, fd, "lib", "eval_str", p, i, &reply) < 0) {
+ fprintf(stderr,"erl_call: evaluating input failed: %s\n",
+ evalbuf);
+ free(p);
+ free(evalbuf); /* Allocated in read_stdin() */
+ ei_x_free(&reply);
+ exit(1);
+ }
+ i = 0;
+ ei_print_term(stdout,reply.buff,&i);
+ free(p);
+ free(evalbuf); /* Allocated in read_stdin() */
+ ei_x_free(&reply);
+ }
+ }
+ /*
+ * Any Erlang call to be made ?
+ */
+ if (flags.apply != NULL) {
+ char *mod,*fun,*args;
+ ei_x_buff e, reply;
+
+ split_apply_string(flags.apply, &mod, &fun, &args);
+ if (flags.verbosep) {
+ fprintf(stderr,"erl_call: module = %s, function = %s, args = %s\n",
+ mod, fun, args);
+ }
+
+ ei_x_new(&e); /* No version to ei_rpc() */
+
+ if (ei_x_format_wo_ver(&e, args) < 0) {
+ /* FIXME no error message and why -1 ? */
+ exit(-1);
+ }
+
+ ei_x_new_with_version(&reply);
+
+ if (ei_rpc(&ec, fd, mod, fun, e.buff, e.index, &reply) < 0) {
+ /* FIXME no error message and why -1 ? */
+ ei_x_free(&e);
+ ei_x_free(&reply);
+ exit(-1);
+ } else {
+ int i = 0;
+ ei_print_term(stdout,reply.buff,&i);
+ ei_x_free(&e);
+ ei_x_free(&reply);
+ }
+ }
+
+ return(0);
+}
+
+
+/***************************************************************************
+ *
+ * XXXXX
+ *
+ ***************************************************************************/
+
+/*
+ * Get host entry (by address or name)
+ */
+/* FIXME: will fail on names like '2fun4you'. */
+static struct hostent* get_hostent(char *host)
+{
+ if (isdigit((int)*host)) {
+ struct in_addr ip_addr;
+ int b1, b2, b3, b4;
+ long addr;
+
+ /* FIXME: Use inet_aton() (or inet_pton() and get v6 for free). */
+ if (sscanf(host, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4) {
+ return NULL;
+ }
+ addr = inet_addr(host);
+ ip_addr.s_addr = htonl(addr);
+
+ return ei_gethostbyaddr((char *)&ip_addr,sizeof(struct in_addr), AF_INET);
+ }
+
+ return ei_gethostbyname(host);
+} /* get_hostent */
+
+
+
+
+/*
+ * This function does only return on success.
+ */
+static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags)
+{
+ int fd;
+ int start_flags;
+ int r;
+
+ start_flags = ERL_START_ENODE |
+ (flags->use_long_name? ERL_START_LONG : 0) |
+ (flags->verbosep? ERL_START_VERBOSE : 0) |
+ (flags->debugp? ERL_START_DEBUG : 0);
+
+ if ((fd = ei_connect(ec, nodename)) >= 0) {
+ /* success */
+ if (flags->verbosep) {
+ fprintf(stderr,"erl_call: now connected to node %s\n", nodename);
+ }
+ } else {
+ char alive[EI_MAXALIVELEN+1];
+ char *hostname;
+ struct hostent *h;
+ char *cookieargs[3];
+ char **args;
+
+ cookieargs[0] = "-setcookie";
+ cookieargs[1] = flags->cookie;
+ cookieargs[2] = NULL;
+
+ args = (flags->cookie) ? cookieargs : NULL;
+
+ if (!(hostname = strrchr(nodename,'@'))) {
+ return ERL_BADARG;
+ }
+ strncpy(alive,nodename,hostname-nodename);
+ alive[hostname-nodename] = 0x0;
+ hostname++;
+
+ h = ei_gethostbyname(hostname);
+
+
+ if ((r=erl_start_sys(ec,alive,(Erl_IpAddr)(h->h_addr_list[0]),
+ start_flags,flags->script,args)) < 0) {
+ fprintf(stderr,"erl_call: unable to start node, error = %d\n", r);
+ exit(1);
+ }
+
+ if ((fd=ei_connect(ec, nodename)) >= 0) {
+ /* success */
+ if (flags->verbosep) {
+ fprintf(stderr,"erl_call: now connected to node \"%s\"\n",
+ nodename);
+ }
+ } else {
+ /* (failure) */
+ switch (fd) {
+ case ERL_NO_DAEMON:
+ fprintf(stderr,"erl_call: no epmd running\n");
+ exit(1);
+ case ERL_CONNECT_FAIL:
+ fprintf(stderr,"erl_call: connect failed\n");
+ exit(1);
+ case ERL_NO_PORT:
+ fprintf(stderr,"erl_call: node is not running\n");
+ exit(1);
+ case ERL_TIMEOUT:
+ fprintf(stderr,"erl_call: connect timed out\n");
+ exit(1);
+ default:
+ fprintf(stderr,"erl_call: error during connect\n");
+ exit(1);
+ }
+ }
+ }
+
+ return fd;
+} /* do_connect */
+
+#define SKIP_SPACE(s) while(isspace((int)*(s))) (s)++
+#define EAT(s) while (!isspace((int)*(s)) && (*(s) != '\0')) (s)++
+
+static void split_apply_string(char *str,
+ char **mod,
+ char **fun,
+ char **args)
+{
+ char *begin=str;
+ char *start="start";
+ char *empty_list="[]";
+ int len;
+
+ SKIP_SPACE(str);
+ if (*str == '\0') {
+ fprintf(stderr,"erl_call: wrong format of apply string (1)\n");
+ exit(1);
+ }
+
+ EAT(str);
+ len = str-begin;
+ *mod = (char *) calloc(len + 1, sizeof(char));
+ memcpy(*mod, begin, len);
+
+ SKIP_SPACE(str);
+ if (*str == '\0') {
+ *fun = (char *) calloc(strlen(start)+1, sizeof(char));
+ strcpy(*fun, start);
+ *args = (char *) calloc(strlen(empty_list)+1, sizeof(char));
+ strcpy(*args, empty_list);
+ return;
+ }
+ begin = str;
+ EAT(str);
+ len = str-begin;
+ *fun = (char *) calloc(len + 1, sizeof(char));
+ memcpy(*fun, begin, len);
+
+ SKIP_SPACE(str);
+ if (*str == '\0') {
+ *args = (char *) calloc(strlen(empty_list)+1, sizeof(char));
+ strcpy(*args, empty_list);
+ return;
+ }
+
+ *args = (char *) calloc(strlen(str) + 1, sizeof(char));
+ strcpy(*args, str);
+
+ return;
+
+} /* split_apply_string */
+
+
+/*
+ * Read from stdin until EOF is reached.
+ * Allocate the buffer needed.
+ */
+static int read_stdin(char **buf)
+{
+ int bsize = BUFSIZ;
+ int len = 0;
+ int i;
+ char *tmp = (char *) malloc(bsize);
+
+ while (1) {
+ if ((i = read(0, &tmp[len], bsize-len)) < 0) {
+ fprintf(stderr,"erl_call: can't read stdin, errno = %d", errno);
+ exit(1);
+ } else if (i == 0) {
+ break;
+ } else {
+ len += i;
+ if ((len+50) > bsize) {
+ bsize = len * 2;
+ tmp = (char *) realloc(tmp, bsize);
+ } else {
+ continue;
+ }
+ }
+ } /* while */
+ *buf = tmp;
+ return len;
+
+} /* read_stdin */
+
+/*
+ * Get the module from stdin.
+ */
+static int get_module(char **mbuf, char **mname)
+{
+ char *tmp;
+ int len,i;
+
+ len = read_stdin(mbuf);
+ /*
+ * Now, get the module name.
+ */
+ if ((tmp = strstr(*mbuf, "-module(")) != NULL) {
+ char *start;
+ tmp += strlen("-module(");
+ while ((*tmp) == ' ') tmp++; /* eat space */
+ start = tmp;
+ while (1) {
+ if (isalnum((int)*tmp) || (*tmp == '_')) {
+ tmp++;
+ continue;
+ } else {
+ break;
+ }
+ } /* while */
+ i = tmp - start;
+ *mname = (char *) calloc(i+1, sizeof(char));
+ memcpy(*mname, start, i);
+ }
+ free(mbuf); /* Allocated in read_stdin() */
+
+ return len;
+
+} /* get_module */
+
+
+/***************************************************************************
+ *
+ * Different error reporting functions that output usage
+ *
+ ***************************************************************************/
+
+static void usage_noexit(const char *progname) {
+ fprintf(stderr,"\nUsage: %s [-[demqrsv]] [-c Cookie] [-h HiddenName] \n", progname);
+ fprintf(stderr," [-x ErlScript] [-a [Mod [Fun [Args]]]]\n");
+ fprintf(stderr," (-n Node | -sname Node | -name Node)\n\n");
+#ifdef __WIN32__
+ fprintf(stderr," where: -a apply(Mod,Fun,Args) (e.g -a \"erlang length [[a,b,c]]\"\n");
+#else
+ fprintf(stderr," where: -a apply(Mod,Fun,Args) (e.g -a 'erlang length [[a,b,c]]'\n");
+#endif
+ fprintf(stderr," -c cookie string; by default read from ~/.erlang.cookie\n");
+ fprintf(stderr," -d direct Erlang output to ~/.erl_call.out.<Nodename>\n");
+ fprintf(stderr," -e evaluate contents of standard input (e.g echo \"X=1,Y=2,{X,Y}.\"|erl_call -e ...)\n");
+ fprintf(stderr," -h specify a name for the erl_call client node\n");
+ fprintf(stderr," -m read and compile Erlang module from stdin\n");
+ fprintf(stderr," -n name of Erlang node, same as -name\n");
+ fprintf(stderr," -name name of Erlang node, expanded to a fully qualified\n");
+ fprintf(stderr," -sname name of Erlang node, short form will be used\n");
+ fprintf(stderr," -q halt the Erlang node (overrides the -s switch)\n");
+ fprintf(stderr," -r use a random name for the erl_call client node\n");
+ fprintf(stderr," -s start a new Erlang node if necessary\n");
+ fprintf(stderr," -v verbose mode, i.e print some information on stderr\n");
+ fprintf(stderr," -x use specified erl start script, default is erl\n");
+}
+
+static void usage_arg(const char *progname, const char *switchname) {
+ fprintf(stderr, "Missing argument(s) for \'%s\'.\n", switchname);
+ usage_noexit(progname);
+ exit(1);
+}
+
+static void usage_error(const char *progname, const char *switchname) {
+ fprintf(stderr, "Illegal argument \'%s\'.\n", switchname);
+ usage_noexit(progname);
+ exit(1);
+}
+
+static void usage(const char *progname) {
+ usage_noexit(progname);
+ exit(0);
+}
+
+
+/***************************************************************************
+ *
+ * OS specific functions
+ *
+ ***************************************************************************/
+
+#ifdef __WIN32__
+/*
+ * FIXME This should not be here. This is a quick fix to make erl_call
+ * work at all on Windows NT.
+ */
+static void initWinSock(void)
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+ static int initialized;
+
+ wVersionRequested = MAKEWORD(1, 1);
+ if (!initialized) {
+ initialized = 1;
+ err = WSAStartup(wVersionRequested, &wsaData);
+
+ if (err != 0) {
+ fprintf(stderr,"erl_call: "
+ "Can't initialize windows sockets: %d\n", err);
+ }
+
+ if ( LOBYTE( wsaData.wVersion ) != 1 ||
+ HIBYTE( wsaData.wVersion ) != 1 ) {
+ fprintf(stderr,"erl_call: This version of "
+ "windows sockets not supported\n");
+ WSACleanup();
+ }
+ }
+}
+#endif
diff --git a/lib/erl_interface/src/prog/erl_fake_prog.c b/lib/erl_interface/src/prog/erl_fake_prog.c
new file mode 100644
index 0000000000..a2b49a0ed9
--- /dev/null
+++ b/lib/erl_interface/src/prog/erl_fake_prog.c
@@ -0,0 +1,250 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. 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%
+ */
+
+/***************************************************************************
+ *
+ * This is a fake program that contains all functions, variables and
+ * defined symbols mentioned in the manual. We compile this file to see
+ * that the header files and created library is complete.
+ *
+ * You can't run this program, it is for compiling and linking only.
+ *
+ ***************************************************************************/
+
+/* Use most of
+ * CFLAGS="-I../include -g -O2
+ * -ansi -pedantic
+ * -Wall
+ * -Wshadow
+ * -Wstrict-prototypes
+ * -Wmissing-prototypes
+ * -Wmissing-declarations
+ * -Wnested-externs
+ * -Winline
+ * -Werror"
+ */
+
+/* #include <netdb.h> now included by ei.h */
+#include "erl_interface.h"
+
+#ifdef VXWORKS
+int erl_fake_prog_main(void)
+#else
+int main(void)
+#endif
+{
+ ei_x_buff eix;
+ int index = 0;
+ ETERM **etermpp = NULL, *etermp = NULL;
+ char *charp = NULL;
+ unsigned char uchar, **ucharpp = NULL, *ucharp = NULL;
+ void *voidp = NULL;
+ Erl_Heap *erl_heapp = NULL;
+ int intx = 0;
+ int *intp = NULL;
+ unsigned int uintx, *uintp;
+ unsigned long *ulongp = NULL;
+ long longx = 0;
+ double doublex = 0.0;
+ short shortx = 42;
+ FILE *filep = NULL;
+ Erl_IpAddr erl_ipaddr = NULL;
+ ErlMessage *erlmessagep = NULL;
+ ErlConnect *erlconnectp = NULL;
+ struct hostent *hostp = NULL;
+ struct in_addr *inaddrp = NULL;
+
+ /* Converion to erl_interface format is in liberl_interface */
+
+ intx = erl_errno;
+
+ ei_encode_term(charp, &index, voidp);
+ ei_x_encode_term(&eix, voidp);
+ ei_decode_term(charp, &index, voidp);
+
+ erl_init(voidp, longx);
+ erl_connect_init(intx, charp,shortx);
+ erl_connect_xinit(charp,charp,charp,erl_ipaddr,charp,shortx);
+ erl_connect(charp);
+ erl_xconnect(erl_ipaddr,charp);
+ erl_close_connection(intx);
+ erl_receive(intx, ucharp, intx);
+ erl_receive_msg(intx, ucharp, intx, erlmessagep);
+ erl_xreceive_msg(intx, ucharpp, intp, erlmessagep);
+ erl_send(intx, etermp, etermp);
+ erl_reg_send(intx, charp, etermp);
+ erl_rpc(intx,charp,charp,etermp);
+ erl_rpc_to(intx,charp,charp,etermp);
+ erl_rpc_from(intx,intx,erlmessagep);
+
+ erl_publish(intx);
+ erl_accept(intx,erlconnectp);
+
+ erl_thiscookie();
+ erl_thisnodename();
+ erl_thishostname();
+ erl_thisalivename();
+ erl_thiscreation();
+ erl_unpublish(charp);
+ erl_err_msg(charp);
+ erl_err_quit(charp);
+ erl_err_ret(charp);
+ erl_err_sys(charp);
+
+ erl_cons(etermp,etermp);
+ erl_copy_term(etermp);
+ erl_element(intx,etermp);
+
+ erl_hd(etermp);
+ erl_iolist_to_binary(etermp);
+ erl_iolist_to_string(etermp);
+ erl_iolist_length(etermp);
+ erl_length(etermp);
+ erl_mk_atom(charp);
+ erl_mk_binary(charp,intx);
+ erl_mk_empty_list();
+ erl_mk_estring(charp, intx);
+ erl_mk_float(doublex);
+ erl_mk_int(intx);
+ erl_mk_list(etermpp,intx);
+ erl_mk_pid(charp,uintx,uintx,uchar);
+ erl_mk_port(charp,uintx,uchar);
+ erl_mk_ref(charp,uintx,uchar);
+ erl_mk_long_ref(charp,uintx,uintx,uintx,uchar);
+ erl_mk_string(charp);
+ erl_mk_tuple(etermpp,intx);
+ erl_mk_uint(uintx);
+ erl_mk_var(charp);
+ erl_print_term(filep,etermp);
+ /* erl_sprint_term(charp,etermp); */
+ erl_size(etermp);
+ erl_tl(etermp);
+ erl_var_content(etermp, charp);
+
+ erl_format(charp);
+ erl_match(etermp, etermp);
+
+ erl_global_names(intx, intp);
+ erl_global_register(intx, charp, etermp);
+ erl_global_unregister(intx, charp);
+ erl_global_whereis(intx, charp, charp);
+
+ erl_init_malloc(erl_heapp,longx);
+ erl_alloc_eterm(uchar);
+ erl_eterm_release();
+ erl_eterm_statistics(ulongp,ulongp);
+ erl_free_array(etermpp,intx);
+ erl_free_term(etermp);
+ erl_free_compound(etermp);
+ erl_malloc(longx);
+ erl_free(voidp);
+
+ erl_compare_ext(ucharp, ucharp);
+ erl_decode(ucharp);
+ erl_decode_buf(ucharpp);
+ erl_encode(etermp,ucharp);
+ erl_encode_buf(etermp,ucharpp);
+ erl_ext_size(ucharp);
+ erl_ext_type(ucharp);
+ erl_peek_ext(ucharp,intx);
+ erl_term_len(etermp);
+
+ erl_gethostbyname(charp);
+ erl_gethostbyaddr(charp, intx, intx);
+ erl_gethostbyname_r(charp, hostp, charp, intx, intp);
+ erl_gethostbyaddr_r(charp, intx, intx, hostp, charp, intx, intp);
+
+ erl_init_resolve();
+ erl_distversion(intx);
+
+ erl_epmd_connect(inaddrp);
+ erl_epmd_port(inaddrp, charp, intp);
+
+ charp = ERL_ATOM_PTR(etermp);
+ intx = ERL_ATOM_SIZE(etermp);
+ ucharp = ERL_BIN_PTR(etermp);
+ intx = ERL_BIN_SIZE(etermp);
+ etermp = ERL_CONS_HEAD(etermp);
+ etermp = ERL_CONS_TAIL(etermp);
+ intx = ERL_COUNT(etermp);
+ doublex= ERL_FLOAT_VALUE(etermp);
+ uintx = ERL_INT_UVALUE(etermp);
+ intx = ERL_INT_VALUE(etermp);
+ intx = ERL_IS_ATOM(etermp);
+ intx = ERL_IS_BINARY(etermp);
+ intx = ERL_IS_CONS(etermp);
+ intx = ERL_IS_EMPTY_LIST(etermp);
+ intx = ERL_IS_FLOAT(etermp);
+ intx = ERL_IS_INTEGER(etermp);
+ intx = ERL_IS_LIST(etermp);
+ intx = ERL_IS_PID(etermp);
+ intx = ERL_IS_PORT(etermp);
+ intx = ERL_IS_REF(etermp);
+ intx = ERL_IS_TUPLE(etermp);
+ intx = ERL_IS_UNSIGNED_INTEGER(etermp);
+ uchar = ERL_PID_CREATION(etermp);
+ charp = ERL_PID_NODE(etermp);
+ uintx = ERL_PID_NUMBER(etermp);
+ uintx = ERL_PID_SERIAL(etermp);
+ uchar = ERL_PORT_CREATION(etermp);
+ charp = ERL_PORT_NODE(etermp);
+ uintx = ERL_PORT_NUMBER(etermp);
+ uchar = ERL_REF_CREATION(etermp);
+ intx = ERL_REF_LEN(etermp);
+ charp = ERL_REF_NODE(etermp);
+ uintx = ERL_REF_NUMBER(etermp);
+ uintp = ERL_REF_NUMBERS(etermp);
+ etermp = ERL_TUPLE_ELEMENT(etermp,intx);
+ intx = ERL_TUPLE_SIZE(etermp);
+
+ return
+ BUFSIZ +
+ EAGAIN +
+ EHOSTUNREACH +
+ EINVAL +
+ EIO +
+ EMSGSIZE +
+ ENOMEM +
+ ERL_ATOM +
+ ERL_BINARY +
+ ERL_ERROR +
+ ERL_EXIT +
+ ERL_FLOAT +
+ ERL_INTEGER +
+ ERL_LINK +
+ ERL_LIST +
+ ERL_MSG +
+ ERL_NO_TIMEOUT +
+ ERL_PID +
+ ERL_PORT +
+ ERL_REF +
+ ERL_REG_SEND +
+ ERL_SEND +
+ ERL_SMALL_BIG +
+ ERL_TICK +
+ ERL_TIMEOUT +
+ ERL_TUPLE +
+ ERL_UNLINK +
+ ERL_U_INTEGER +
+ ERL_U_SMALL_BIG +
+ ERL_VARIABLE +
+ ETIMEDOUT +
+ MAXNODELEN +
+ MAXREGLEN;
+}
diff --git a/lib/erl_interface/src/prog/erl_start.c b/lib/erl_interface/src/prog/erl_start.c
new file mode 100644
index 0000000000..a53aab9ac7
--- /dev/null
+++ b/lib/erl_interface/src/prog/erl_start.c
@@ -0,0 +1,735 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1997-2009. 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%
+ *
+
+ */
+
+/* An exception from using eidef.h, use config.h directly */
+#include "config.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+
+#elif VXWORKS
+#include <stdio.h>
+#include <string.h>
+#include <vxWorks.h>
+#include <hostLib.h>
+#include <selectLib.h>
+#include <ifLib.h>
+#include <sockLib.h>
+#include <taskLib.h>
+#include <inetLib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <symLib.h>
+#include <sysSymTbl.h>
+#include <sysLib.h>
+#include <tickLib.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include <a_out.h>
+
+/* #include "netdb.h" */
+#else /* other unix */
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#endif
+
+#include "ei.h"
+#include "ei_resolve.h"
+#include "erl_start.h"
+
+/* FIXME is this a case a vfork can be used? */
+#if !HAVE_WORKING_VFORK
+# define vfork fork
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+#ifndef RSH
+#define RSH "/usr/bin/rsh"
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+typedef int SocklenType;
+#else
+typedef socklen_t SocklenType;
+#endif
+
+/* FIXME check errors from malloc */
+
+static struct in_addr *get_addr(const char *hostname, struct in_addr *oaddr);
+
+static int wait_for_erlang(int sockd, int magic, struct timeval *timeout);
+#if defined(VXWORKS) || defined(__WIN32__)
+static int unique_id(void);
+static unsigned long spawn_erlang_epmd(ei_cnode *ec,
+ char *alive,
+ Erl_IpAddr adr,
+ int flags,
+ char *erl_or_epmd,
+ char *args[],
+ int port,
+ int is_erlang);
+#else
+static int exec_erlang(ei_cnode *ec, char *alive, Erl_IpAddr adr, int flags,
+ char *erl, char *args[],int port);
+#endif
+/* Start an Erlang node. return value 0 indicates that node was
+ * started successfully, negative values indicate error.
+ *
+ * node - the name of the remote node to start (alivename@hostname).
+ * flags - turn on or off certain options. See erl_start.h for a list.
+ * erl - is the name of the erl script to call. If NULL, the default
+ * name "erl" will be used.
+ * args - a NULL-terminated list of strings containing
+ * additional arguments to be sent to the remote Erlang node. These
+ * strings are simply appended to the end of the command line, so any
+ * quoting of special characters, etc must be done by the caller.
+ * There may be some conflicts between some of these arguments and the
+ * default arguments hard-coded into this function, so be careful.
+ */
+int erl_start_sys(ei_cnode *ec, char *alive, Erl_IpAddr adr, int flags,
+ char *erl, char *args[])
+{
+ struct timeval timeout;
+ struct sockaddr_in addr;
+ SocklenType namelen;
+ int port;
+ int sockd = 0;
+ int one = 1;
+#if defined(VXWORKS) || defined(__WIN32__)
+ unsigned long pid = 0;
+#else
+ int pid = 0;
+#endif
+ int r = 0;
+
+ if (((sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0) ||
+ (setsockopt(sockd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0)) {
+ r = ERL_SYS_ERROR;
+ goto done;
+ }
+
+ memset(&addr,0,sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = 0;
+
+ if (bind(sockd,(struct sockaddr *)&addr,sizeof(addr))<0) {
+ return ERL_SYS_ERROR;
+ }
+ namelen = sizeof(addr);
+ if (getsockname(sockd,(struct sockaddr *)&addr,&namelen)<0) {
+ return ERL_SYS_ERROR;
+ }
+ port = ntohs(addr.sin_port);
+
+ listen(sockd,5);
+
+#if defined(VXWORKS) || defined(__WIN32__)
+ if((pid = spawn_erlang_epmd(ec,alive,adr,flags,erl,args,port,1))
+ == 0)
+ return ERL_SYS_ERROR;
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 10; /* ignoring ERL_START_TIME */
+ if((r = wait_for_erlang(sockd,unique_id(),&timeout))
+ == ERL_TIMEOUT) {
+#if defined(VXWORKS)
+ taskDelete((int) pid);
+ if(taskIdVerify((int) pid) != ERROR)
+ taskDeleteForce((int) pid);
+#else /* Windows */
+ /* Well, this is not a nice way to do it, and it does not
+ always kill the emulator, but the alternatives are few.*/
+ TerminateProcess((HANDLE) pid,1);
+#endif /* defined(VXWORKS) */
+ }
+#else /* Unix */
+ switch ((pid = fork())) {
+ case -1:
+ r = ERL_SYS_ERROR;
+ break;
+
+ case 0:
+ /* child - start the erlang node */
+ exec_erlang(ec, alive, adr, flags, erl, args, port);
+
+ /* error if reached - parent reports back to caller after timeout
+ so we just exit here */
+ exit(1);
+ break;
+
+ default:
+
+ /* parent - waits for response from Erlang node */
+ /* child pid used here as magic number */
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 10; /* ignoring ERL_START_TIME */
+ if ((r = wait_for_erlang(sockd,pid,&timeout)) == ERL_TIMEOUT) {
+ /* kill child if no response */
+ kill(pid,SIGINT);
+ sleep(1);
+ if (waitpid(pid,NULL,WNOHANG) != pid) {
+ /* no luck - try harder */
+ kill(pid,SIGKILL);
+ sleep(1);
+ waitpid(pid,NULL,WNOHANG);
+ }
+ }
+
+ }
+#endif /* defined(VXWORKS) || defined(__WIN32__) */
+
+done:
+#if defined(__WIN32__)
+ if (sockd) closesocket(sockd);
+#else
+ if (sockd) close(sockd);
+#endif
+ return r;
+} /* erl_start_sys() */
+
+#if defined(VXWORKS) || defined(__WIN32__)
+#if defined(VXWORKS)
+#define DEF_ERL_COMMAND ""
+#define DEF_EPMD_COMMAND ""
+#define ERLANG_SYM "start_erl"
+#define EPMD_SYM "start_epmd"
+#define ERL_REPLY_FMT "-s erl_reply reply %s %d %d"
+#else
+#define DEF_ERL_COMMAND "erl"
+#define DEF_EPMD_COMMAND "epmd"
+#define ERL_REPLY_FMT "-s erl_reply reply \"%s\" \"%d\" \"%d\""
+#endif
+#define ERL_NAME_FMT "-noinput -name %s"
+#define ERL_SNAME_FMT "-noinput -sname %s"
+
+#define IP_ADDR_CHARS 15
+#define FORMATTED_INT_LEN 10
+
+static int unique_id(void){
+#if defined(VXWORKS)
+ return taskIdSelf();
+#else
+ return (int) GetCurrentThreadId();
+#endif
+}
+
+static int enquote_args(char **oargs, char ***qargs){
+ char **args;
+ int len;
+ int i;
+ int qwhole;
+ int extra;
+ char *ptr;
+ char *ptr2;
+
+ if(oargs == NULL){
+ *qargs = malloc(sizeof(char *));
+ **qargs = NULL;
+ return 0;
+ };
+
+ for(len=0;oargs[len] != NULL; ++len)
+ ;
+ args = malloc(sizeof(char *) * (len + 1));
+
+ for(i = 0; i < len; ++i){
+ qwhole = strchr(oargs[i],' ') != NULL;
+ extra = qwhole * 2;
+ for(ptr = oargs[i]; *ptr != '\0'; ++ptr)
+ extra += (*ptr == '"');
+ args[i] = malloc(strlen(oargs[i]) +
+ extra +
+ 1);
+ ptr2 = args[i];
+ if(qwhole)
+ *(ptr2++) = '"';
+ for(ptr = oargs[i]; *ptr != '\0'; ++ptr){
+ if(*ptr == '"')
+ *(ptr2++) = '\\';
+ *(ptr2++) = *ptr;
+ }
+ if(qwhole)
+ *(ptr2++) = '"';
+ *ptr2 = '\0';
+ }
+ args[len] = NULL;
+ *qargs = args;
+ return len;
+}
+
+static void free_args(char **args){
+ char **ptr = args;
+ while(*ptr != NULL)
+ free(*(ptr++));
+ free(args);
+}
+
+#if defined(VXWORKS)
+static FUNCPTR lookup_function(char *symname){
+ char *value;
+ SYM_TYPE type;
+ if(symFindByName(sysSymTbl,
+ symname,
+ &value,
+ &type) == ERROR /*|| type != N_TEXT*/)
+ return NULL;
+ return (FUNCPTR) value;
+}
+#endif /* defined(VXWORKS) */
+
+/* In NT and VxWorks, we cannot fork(), Erlang and Epmd gets
+ spawned by this function instead. */
+
+static unsigned long spawn_erlang_epmd(ei_cnode *ec,
+ char *alive,
+ Erl_IpAddr adr,
+ int flags,
+ char *erl_or_epmd,
+ char *args[],
+ int port,
+ int is_erlang)
+{
+#if defined(VXWORKS)
+ FUNCPTR erlfunc;
+#else /* Windows */
+ STARTUPINFO sinfo;
+ SECURITY_ATTRIBUTES sa;
+ PROCESS_INFORMATION pinfo;
+#endif
+ char *cmdbuf;
+ int cmdlen;
+ char *ptr;
+ int i;
+ int num_args;
+ char *name_format;
+ struct in_addr myaddr;
+ struct in_addr *hisaddr = (struct in_addr *)adr;
+ char iaddrbuf[IP_ADDR_CHARS + 1];
+ int ret;
+
+ if(is_erlang){
+ get_addr(ei_thishostname(ec), &myaddr);
+#if defined(VXWORKS)
+ inet_ntoa_b(myaddr, iaddrbuf);
+#else /* Windows */
+ if((ptr = inet_ntoa(myaddr)) == NULL)
+ return 0;
+ else
+ strcpy(iaddrbuf,ptr);
+#endif
+ }
+ if ((flags & ERL_START_REMOTE) ||
+ (is_erlang && (hisaddr->s_addr != myaddr.s_addr))) {
+ return 0;
+ } else {
+ num_args = enquote_args(args, &args);
+ for(cmdlen = i = 0; args[i] != NULL; ++i)
+ cmdlen += strlen(args[i]) + 1;
+#if !defined(VXWORKS)
+ /* On VxWorks, we dont actually run a command,
+ we call start_erl() */
+ if(!erl_or_epmd)
+#endif
+ erl_or_epmd = (is_erlang) ? DEF_ERL_COMMAND :
+ DEF_EPMD_COMMAND;
+ if(is_erlang){
+ name_format = (flags & ERL_START_LONG) ? ERL_NAME_FMT :
+ ERL_SNAME_FMT;
+ cmdlen +=
+ strlen(erl_or_epmd) + (*erl_or_epmd != '\0') +
+ strlen(name_format) + 1 + strlen(alive) +
+ strlen(ERL_REPLY_FMT) + 1 + strlen(iaddrbuf) +
+ 2 * FORMATTED_INT_LEN +
+ 1;
+ ptr = cmdbuf = malloc(cmdlen);
+ if(*erl_or_epmd != '\0')
+ ptr += sprintf(ptr,"%s ",erl_or_epmd);
+ ptr += sprintf(ptr, name_format,
+ alive);
+ ptr += sprintf(ptr, " " ERL_REPLY_FMT,
+ iaddrbuf, port, unique_id());
+ } else { /* epmd */
+ cmdlen += strlen(erl_or_epmd) + (*erl_or_epmd != '\0') + 1;
+ ptr = cmdbuf = malloc(cmdlen);
+ if(*erl_or_epmd != '\0')
+ ptr += sprintf(ptr,"%s ",erl_or_epmd);
+ else
+ *(ptr++) = '\0';
+ }
+ for(i= 0; args[i] != NULL; ++i){
+ *(ptr++) = ' ';
+ strcpy(ptr,args[i]);
+ ptr += strlen(args[i]);
+ }
+ free_args(args);
+ if (flags & ERL_START_VERBOSE) {
+ fprintf(stderr,"erl_call: commands are %s\n",cmdbuf);
+ }
+ /* OK, one single command line... */
+#if defined(VXWORKS)
+ erlfunc = lookup_function((is_erlang) ? ERLANG_SYM :
+ EPMD_SYM);
+ if(erlfunc == NULL){
+ if (flags & ERL_START_VERBOSE) {
+ fprintf(stderr,"erl_call: failed to find symbol %s\n",
+ (is_erlang) ? ERLANG_SYM : EPMD_SYM);
+ }
+ ret = 0;
+ } else {
+ /* Just call it, it spawns itself... */
+ ret = (unsigned long)
+ (*erlfunc)((int) cmdbuf,0,0,0,0,0,0,0,0,0);
+ if(ret == (unsigned long) ERROR)
+ ret = 0;
+ }
+#else /* Windows */
+ /* Hmmm, hidden or unhidden window??? */
+ memset(&sinfo,0,sizeof(sinfo));
+ sinfo.cb = sizeof(STARTUPINFO);
+ sinfo.dwFlags = STARTF_USESHOWWINDOW /*|
+ STARTF_USESTDHANDLES*/;
+ sinfo.wShowWindow = SW_HIDE; /* Hidden! */
+ sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ sinfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ sinfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = /*TRUE*/ FALSE;
+ if(!CreateProcess(
+ NULL,
+ cmdbuf,
+ &sa,
+ NULL,
+ /*TRUE*/ FALSE,
+ 0 | CREATE_NEW_CONSOLE,
+ NULL,
+ NULL,
+ &sinfo,
+ &pinfo))
+ ret = 0;
+ else
+ ret = (unsigned long) pinfo.hProcess;
+#endif
+ free(cmdbuf);
+ return ret;
+ }
+ /* NOTREACHED */
+}
+#else /* Unix */
+
+/* call this from the child process to start an erlang system. This
+ * function just builds the erlang command line and then calls it.
+ *
+ * node - the nodename for the new node
+ * flags - various options that can be set (see erl_start.h)
+ * erl - name of the erlang executable, or NULL for default ("erl")
+ * args - additional arguments to pass to erlang executable
+ * port - the port number where we wait for acknowledgment from the enode
+ *
+ * we have a potential problem if args conflicts with any of the
+ * arguments we use here.
+ */
+static int exec_erlang(ei_cnode *ec,
+ char *alive,
+ Erl_IpAddr adr,
+ int flags,
+ char *erl,
+ char *args[],
+ int port)
+{
+#if !defined(__WIN32__) && !defined(VXWORKS)
+ int fd,len,l,i;
+ char **s;
+ char *argv[4];
+ char argbuf[BUFSIZ];
+ struct in_addr myaddr;
+ struct in_addr *hisaddr = (struct in_addr *)adr;
+
+ get_addr(ei_thishostname(ec), &myaddr);
+
+ /* on this host? */
+ /* compare ip addresses, unless forced by flag setting to use rsh */
+ if ((flags & ERL_START_REMOTE) || (hisaddr->s_addr != myaddr.s_addr)) {
+ argv[0] = RSH;
+ len = strlen(inet_ntoa(*hisaddr));
+ argv[1] = malloc(len+1);
+ strcpy(argv[1],inet_ntoa(*hisaddr));
+ }
+ else {
+ /* Yes - use sh to start local Erlang */
+ argv[0] = "sh";
+ argv[1] = "-c";
+ }
+ argv[2] = argbuf;
+ argv[3] = NULL;
+
+ len = 0;
+ *argbuf=(char)0;
+
+ sprintf(argbuf,"exec %s ", (erl? erl: "erl"));
+ len = strlen(argbuf);
+
+ /* *must* be noinput or node (seems to) hang... */
+ /* long or short names? */
+ sprintf(&argbuf[len], "-noinput %s %s ",
+ ((flags & ERL_START_LONG) ? "-name" : "-sname"),
+ alive);
+ len = strlen(argbuf);
+
+ /* now make the new node report back when it's ready */
+ /* add: myip, myport and replymsg */
+ sprintf(&argbuf[len],
+ "-s erl_reply reply %s %d %d ",
+ inet_ntoa(myaddr),port,(int)getpid());
+#ifdef DEBUG
+ fprintf(stderr,"erl_call: debug %s\n",&argbuf[len]);
+#endif
+ len = strlen(argbuf);
+
+ /* additional arguments to be passed to the other system */
+ /* make sure that they will fit first */
+ for (l=0, s = args; s && *s; s++) l+= strlen(*s) + 1;
+
+ if (len + l + 1 > BUFSIZ) return ERL_BADARG;
+ else {
+ for (s = args; s && *s; s++) {
+ strcat(argbuf," ");
+ strcat(argbuf,*s);
+ }
+ len += l + 1;
+ }
+
+ if (flags & ERL_START_VERBOSE) {
+ fprintf(stderr,"erl_call: %s %s %s\n",argv[0],argv[1],argv[2]);
+ }
+
+ /* close all descriptors in child */
+ for (i=0; i<64; i++) close(i);
+
+ /* debug output to file? */
+ if (flags & ERL_START_DEBUG) {
+ char debugfile[MAXPATHLEN+1];
+ char *home=getenv("HOME");
+ sprintf(debugfile,"%s/%s.%s",home,ERL_START_LOGFILE,alive);
+ if ((fd=open(debugfile, O_WRONLY | O_CREAT | O_APPEND, 0644)) >= 0) {
+ time_t t = time(NULL);
+ dup2(fd,1);
+ dup2(fd,2);
+ fprintf(stderr,"\n\n===== Log started ======\n%s \n",ctime(&t));
+ fprintf(stderr,"erl_call: %s %s %s\n",argv[0],argv[1],argv[2]);
+ }
+ }
+
+ /* start the system */
+ execvp(argv[0], argv);
+
+ if (flags & ERL_START_DEBUG) {
+ fprintf(stderr,"erl_call: exec failed: (%d) %s %s %s\n",
+ errno,argv[0],argv[1],argv[2]);
+ }
+
+#endif
+ /* (hopefully) NOT REACHED */
+ return ERL_SYS_ERROR;
+} /* exec_erlang() */
+
+#endif /* defined(VXWORKS) || defined(WINDOWS) */
+
+#if defined(__WIN32__)
+static void gettimeofday(struct timeval *now,void *dummy){
+ SYSTEMTIME systime;
+ FILETIME ft;
+ DWORD x;
+ GetSystemTime(&systime);
+ SystemTimeToFileTime(&systime,&ft);
+ x = ft.dwLowDateTime / 10;
+ now->tv_sec = x / 1000000;
+ now->tv_usec = x % 1000000;
+}
+
+#elif defined(VXWORKS)
+static void gettimeofday(struct timeval *now, void *dummy){
+ int rate = sysClkRateGet(); /* Ticks per second */
+ unsigned long ctick = tickGet();
+ now->tv_sec = ctick / rate; /* secs since reboot */
+ now->tv_usec = ((ctick - (now->tv_sec * rate))*1000000)/rate;
+}
+#endif
+
+
+/* wait for the remote system to reply */
+/*
+ * sockd - an open socket where we expect a connection from the e-node
+ * magic - sign on message the e-node must provide for verification
+ * timeout - how long to wait before returning failure
+ *
+ * OBS: the socket is blocking, and there is a potential deadlock if we
+ * get an accept but the peer sends no data (and does not close).
+ * in normal cases the timeout will work ok however, i.e. either we
+ * never get any connection, or we get connection then close().
+ */
+static int wait_for_erlang(int sockd, int magic, struct timeval *timeout)
+{
+ struct timeval to;
+ struct timeval stop_time;
+ struct timeval now;
+ fd_set rdset;
+ int fd;
+ int n,i;
+ char buf[16];
+ struct sockaddr_in peer;
+ SocklenType len = (SocklenType) sizeof(peer);
+
+ /* determine when we should exit this function */
+ gettimeofday(&now,NULL);
+ stop_time.tv_sec = now.tv_sec + timeout->tv_sec;
+ stop_time.tv_usec = now.tv_usec + timeout->tv_usec;
+ while (stop_time.tv_usec > 1000000) {
+ stop_time.tv_sec++;
+ stop_time.tv_usec -= 1000000;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr,"erl_call: debug time is %ld.%06ld, "
+ "will timeout at %ld.%06ld\n",
+ now.tv_sec,now.tv_usec,stop_time.tv_sec,stop_time.tv_usec);
+#endif
+
+ while (1) {
+ FD_ZERO(&rdset);
+ FD_SET(sockd,&rdset);
+
+ /* adjust the timeout to (stoptime - now) */
+ gettimeofday(&now,NULL);
+ to.tv_sec = stop_time.tv_sec - now.tv_sec;
+ to.tv_usec = stop_time.tv_usec - now.tv_usec;
+ while ((to.tv_usec <= 0) && (to.tv_sec >= 0)) {
+ to.tv_usec += 1000000;
+ to.tv_sec--;
+ }
+ if (to.tv_sec < 0) return ERL_TIMEOUT;
+
+#ifdef DEBUG
+ fprintf(stderr,"erl_call: debug remaining to timeout: %ld.%06ld\n",
+ to.tv_sec,to.tv_usec);
+#endif
+ switch ((i = select(sockd+1,&rdset,NULL,NULL,&to))) {
+ case -1:
+ return ERL_SYS_ERROR;
+ break;
+
+ case 0: /* timeout */
+#ifdef DEBUG
+ gettimeofday(&now,NULL);
+ fprintf(stderr,"erl_call: debug timed out at %ld.%06ld\n",
+ now.tv_sec,now.tv_usec);
+#endif
+ return ERL_TIMEOUT;
+ break;
+
+ default: /* ready descriptors */
+#ifdef DEBUG
+ gettimeofday(&now,NULL);
+ fprintf(stderr,"erl_call: debug got select at %ld.%06ld\n",
+ now.tv_sec,now.tv_usec);
+#endif
+ if (FD_ISSET(sockd,&rdset)) {
+ if ((fd = accept(sockd,(struct sockaddr *)&peer,&len)) < 0)
+ return ERL_SYS_ERROR;
+
+ /* now get sign-on message and terminate it */
+#if defined(__WIN32__)
+ if ((n=recv(fd,buf,16,0)) >= 0) buf[n]=0x0;
+ closesocket(fd);
+#else
+ if ((n=read(fd,buf,16)) >= 0) buf[n]=0x0;
+ close(fd);
+#endif
+#ifdef DEBUG
+ fprintf(stderr,"erl_call: debug got %d, expected %d\n",
+ atoi(buf),magic);
+#endif
+
+ if (atoi(buf) == magic) return 0; /* success */
+ } /* if FD_SET */
+ } /* switch */
+ } /* while */
+
+ /* unreached? */
+ return ERL_SYS_ERROR;
+} /* wait_for_erlang() */
+
+
+static struct in_addr *get_addr(const char *hostname, struct in_addr *oaddr)
+{
+ struct hostent *hp;
+
+#if !defined (__WIN32__)
+ char buf[1024];
+ struct hostent host;
+ int herror;
+
+ hp = ei_gethostbyname_r(hostname,&host,buf,1024,&herror);
+#else
+ hp = ei_gethostbyname(hostname);
+#endif
+
+ if (hp) {
+ memmove(oaddr,hp->h_addr_list[0],sizeof(*oaddr));
+ return oaddr;
+ }
+ return NULL;
+}
diff --git a/lib/erl_interface/src/prog/erl_start.h b/lib/erl_interface/src/prog/erl_start.h
new file mode 100644
index 0000000000..05f34864a7
--- /dev/null
+++ b/lib/erl_interface/src/prog/erl_start.h
@@ -0,0 +1,46 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1997-2009. 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%
+ *
+
+ */
+#ifndef _ERL_START_H
+#define _ERL_START_H
+
+#define ERL_START_MSG "gurka" /* make something up */
+#define ERL_START_TIME 10000 /* wait this long (ms) */
+#define ERL_START_LOGFILE ".erl_start.out" /* basename of logfile */
+
+/* flags used by erl_connect and erl_xconnect */
+#define ERL_START_ENODE 0x0001
+#define ERL_START_EPMD 0x0002
+#define ERL_START_LONG 0x0004
+#define ERL_START_COOKIE 0x0008
+#define ERL_START_DEBUG 0x0010
+#define ERL_START_VERBOSE 0x0020
+#define ERL_START_REMOTE 0x0040
+
+/* error return values */
+#define ERL_S_TIMEOUT -51 /* a timeout occurred */
+#define ERL_BADARG -52 /* an argument contained an incorrect value */
+#define ERL_SYS_ERROR -99 /* a system error occurred (check errno) */
+
+/* start an erlang system */
+int erl_start_sys(ei_cnode *ec, char *alive, Erl_IpAddr addr, int flags,
+ char *erl, char *add_args[]);
+
+#endif /* _ERL_START_H */