aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/sys/ose/erts.sig3
-rw-r--r--erts/etc/common/Makefile.in64
-rw-r--r--erts/etc/common/run_erl_common.c38
-rw-r--r--erts/etc/common/run_erl_common.h4
-rw-r--r--erts/etc/common/to_erl_common.c128
-rw-r--r--erts/etc/ose/run_erl.c637
-rw-r--r--erts/etc/ose/run_erl.h (renamed from erts/etc/ose/to_erl.c)21
-rw-r--r--erts/etc/ose/run_erl_main.c77
8 files changed, 921 insertions, 51 deletions
diff --git a/erts/emulator/sys/ose/erts.sig b/erts/emulator/sys/ose/erts.sig
index 95c12652f2..78b883ee6c 100644
--- a/erts/emulator/sys/ose/erts.sig
+++ b/erts/emulator/sys/ose/erts.sig
@@ -11,4 +11,7 @@
#define ERTS_SIGNAL_OSE_DRV_ATTACH ERTS_OSE_SIGNAL_BASE+3
#define ERTS_SIGNAL_OSE_DRV_HUNT ERTS_OSE_SIGNAL_BASE+4
+#define ERTS_SIGNAL_RUN_ERL_SETUP ERTS_OSE_SIGNAL_BASE+100
+#define ERTS_SIGNAL_RUN_ERL_DAEMON ERTS_OSE_SIGNAL_BASE+101
+
#endif
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index f5df53ec01..5be0942952 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -86,6 +86,16 @@ OSEETC = ../ose
WINETC = ../win32
ifeq ($(TARGET), win32)
+ETC = $(WINETC)
+else
+ifeq ($(findstring ose,$(TARGET)),ose)
+ETC = $(OSEETC)
+else
+ETC = $(UXETC)
+endif
+endif
+
+ifeq ($(TARGET), win32)
ERLEXEC = erlexec.dll
else
ERLEXEC = erlexec
@@ -172,7 +182,7 @@ ENTRY_OBJ=
ERLSRV_OBJECTS=
MC_OUTPUTS=
INET_GETHOST =
-INSTALL_EMBEDDED_PROGS =
+INSTALL_EMBEDDED_PROGS = $(BINDIR)/run_erl_lm
INSTALL_EMBEDDED_DATA =
INSTALL_TOP = Install
INSTALL_TOP_BIN =
@@ -183,7 +193,7 @@ INSTALL_LIBS =
INSTALL_OBJS =
INSTALL_INCLUDES =
TEXTFILES = Install erl.src
-INSTALL_PROGS =
+INSTALL_PROGS = $(INSTALL_EMBEDDED_PROGS)
else # UNIX (!win32 && !ose)
ENTRY_LDFLAGS=
ENTRY_OBJ=
@@ -193,11 +203,11 @@ INET_GETHOST = $(BINDIR)/inet_gethost@EXEEXT@
INSTALL_EMBEDDED_PROGS += $(BINDIR)/typer@EXEEXT@ $(BINDIR)/dialyzer@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_EMBEDDED_DATA = $(UXETC)/start.src $(UXETC)/start_erl.src
INSTALL_TOP = Install
INSTALL_TOP_BIN =
-INSTALL_MISC = ../unix/format_man_pages ../unix/makewhatis
-INSTALL_SRC = ../unix/setuid_socket_wrap.c #delivered as an example
+INSTALL_MISC = $(UXETC)/format_man_pages $(UXETC)/makewhatis
+INSTALL_SRC = $(UXETC)/setuid_socket_wrap.c #delivered as an example
ERLEXECDIR = .
INSTALL_LIBS =
INSTALL_OBJS =
@@ -403,24 +413,24 @@ $(BINDIR)/inet_gethost@EXEEXT@: $(OBJDIR)/inet_gethost.o $(ENTRY_OBJ) $(ERTS_LIB
# run_erl
$(BINDIR)/run_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(OBJDIR)/run_erl_common.o
$(V_LD) $(LDFLAGS) -o $@ $^ $(LIBS)
-$(OBJDIR)/run_erl.o: ../unix/run_erl.c ../common/run_erl_common.h $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c ../unix/run_erl.c
+$(OBJDIR)/run_erl.o: $(ETC)/run_erl.c ../common/run_erl_common.h $(RC_GENERATED)
+ $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(ETC)/run_erl.c
$(OBJDIR)/run_erl_common.o: ../common/run_erl_common.c ../common/run_erl_common.h $(RC_GENERATED)
$(V_CC) $(CFLAGS) -o $@ -c $<
# to_erl
$(BINDIR)/to_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/to_erl.o $(OBJDIR)/to_erl_common.o
$(V_LD) $(LDFLAGS) -o $@ $^
-$(OBJDIR)/to_erl.o: ../unix/to_erl.c ../common/safe_string.h $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c ../unix/to_erl.c
+$(OBJDIR)/to_erl.o: $(ETC)/to_erl.c ../common/safe_string.h $(RC_GENERATED)
+ $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(ETC)/to_erl.c
$(OBJDIR)/to_erl_common.o: ../common/to_erl_common.c ../common/to_erl_common.h $(RC_GENERATED)
$(V_CC) $(CFLAGS) -o $@ -c $<
# dyn_erl
$(BINDIR)/dyn_erl: $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o
$(V_LD) $(LDFLAGS) -o $@ $(OBJDIR)/safe_string.o $(OBJDIR)/dyn_erl.o
-$(OBJDIR)/dyn_erl.o: ../unix/dyn_erl.c $(RC_GENERATED)
- $(V_CC) $(CFLAGS) -o $@ -c ../unix/dyn_erl.c
+$(OBJDIR)/dyn_erl.o: $(UXETC)/dyn_erl.c $(RC_GENERATED)
+ $(V_CC) $(CFLAGS) -o $@ -c $(UXETC)/dyn_erl.c
$(OBJDIR)/safe_string.o: ../common/safe_string.c $(RC_GENERATED)
$(V_CC) $(CFLAGS) -o $@ -c ../common/safe_string.c
@@ -464,18 +474,42 @@ $(OBJDIR)/ct_run.o: ct_run.c $(RC_GENERATED)
-Install: ../unix/Install.src ../../vsn.mk $(TARGET)/Makefile
+Install: $(UXETC)/Install.src ../../vsn.mk $(TARGET)/Makefile
$(vsn_verbose)sed -e 's;%I_VSN%;$(VSN);' \
-e 's;%EMULATOR%;$(EMULATOR);' \
-e 's;%EMULATOR_NUMBER%;$(EMULATOR_NUMBER);' \
-e 's;%I_SYSTEM_VSN%;$(SYSTEM_VSN);' \
- ../unix/Install.src > Install
+ $(UXETC)/Install.src > Install
-erl.src: ../unix/erl.src.src ../../vsn.mk $(TARGET)/Makefile
+erl.src: $(UXETC)/erl.src.src ../../vsn.mk $(TARGET)/Makefile
$(vsn_verbose)sed -e 's;%EMULATOR%;$(EMULATOR);' \
-e 's;%EMULATOR_NUMBER%;$(EMULATOR_NUMBER);' \
-e 's;%VSN%;$(VSN);' \
- ../unix/erl.src.src > erl.src
+ $(UXETC)/erl.src.src > erl.src
+
+#---------------------------------------------------------
+# OSE specific targets
+#---------------------------------------------------------
+ifeq ($(findstring ose,$(TARGET)),ose)
+$(OBJDIR)/ose_confd.o: $(OSE_CONFD)
+ $(V_CC) $(CFLAGS) -o $@ -c $<
+$(OBJDIR)/crt0_lm.o: $(CRT0_LM)
+ $(V_CC) $(CFLAGS) -o $@ -c $<
+OSE_LM_OBJS += $(OBJDIR)/ose_confd.o $(OBJDIR)/crt0_lm.o
+
+$(BINDIR)/run_erl_lm: $(OBJDIR)/run_erl_main.o $(OBJDIR)/safe_string.o $(OBJDIR)/run_erl.o $(OBJDIR)/run_erl_common.o $(OBJDIR)/to_erl_common.o $(OSE_LM_OBJS)
+ $(call build-ose-load-module, $@, $^, $(LIBS), $(LMCONF))
+
+
+$(OBJDIR)/run_erl_main.o: $(OSEETC)/run_erl_main.c $(OSEETC)/run_erl.h ../common/to_erl_common.h $(RC_GENERATED)
+ $(V_CC) $(CFLAGS) -I ../common/ -o $@ -c $(OSEETC)/run_erl_main.c
+
+endif
+
+#---------------------------------------------------------
+# End of ose specific targets.
+#---------------------------------------------------------
+
# ----------------------------------------------------
# Release Target
diff --git a/erts/etc/common/run_erl_common.c b/erts/etc/common/run_erl_common.c
index dc899c5349..bf55056090 100644
--- a/erts/etc/common/run_erl_common.c
+++ b/erts/etc/common/run_erl_common.c
@@ -36,6 +36,10 @@
# include <syslog.h>
#endif
+#ifdef __OSE__
+# include "ramlog.h"
+#endif
+
#include "run_erl_common.h"
#include "safe_string.h"
@@ -57,7 +61,9 @@
#define PIPE_STUBLEN strlen(PIPE_STUBNAME)
#define PERM (S_IWUSR | S_IRUSR | S_IWOTH | S_IROTH | S_IWGRP | S_IRGRP)
-#if !defined(O_SYNC)
+/* OSE has defined O_SYNC but it is not recognized by open */
+#if !defined(O_SYNC) || defined(__OSE__)
+#undef O_SYNC
#define O_SYNC 0
#define USE_FSYNC 1
#endif
@@ -81,8 +87,6 @@ static char log_alive_format[ALIVE_BUFFSIZ+1];
static int run_daemon = 0;
static unsigned protocol_ver = RUN_ERL_LO_VER; /* assume lowest to begin with */
-int erts_run_erl_log_alive_minutes = DEFAULT_LOG_ALIVE_MINUTES;
-
/*
* Current log number and log fd
*/
@@ -94,7 +98,11 @@ static int lfd=0;
* getenv_int:
*/
static char *getenv_int(const char *name) {
+#ifdef __OSE__
+ return get_env(get_bid(current_process()),name);
+#else
return getenv(name);
+#endif
}
/*
@@ -189,9 +197,7 @@ static int open_log(int log_num, int flags)
/* Create or continue on the current log file */
sn_printf(buf, sizeof(buf), "%s/%s%d", log_dir, LOG_STUBNAME, log_num);
- do {
- lfd = open(buf, flags, LOG_PERM);
- } while (lfd < 0 && errno == EINTR);
+ lfd = sf_open(buf, flags, LOG_PERM);
if(lfd <0){
ERRNO_ERR1(LOG_ERR,"Can't open log file '%s'.", buf);
@@ -307,7 +313,11 @@ void erts_run_erl_log_status(const char *format,...)
return;
now = time(NULL);
fprintf(stdstatus, "run_erl [%d] %s",
+#ifdef __OSE__
+ (int)current_process(),
+#else
(int)getpid(),
+#endif
ctime(&now));
va_start(args, format);
vfprintf(stdstatus, format, args);
@@ -331,10 +341,22 @@ void erts_run_erl_log_error(int priority, int line, const char *format, ...)
}
else
#endif
+#ifdef __OSE__
+ if (RUN_DAEMON) {
+ char *buff = malloc(sizeof(char)*1024);
+ vsnprintf(buff,1024,format, args);
+ ramlog_printf(buff);
+ }
+ else
+#endif
{
time_t now = time(NULL);
fprintf(stderr, "run_erl:%d [%d] %s", line,
+#ifdef __OSE__
+ (int)current_process(),
+#else
(int)getpid(),
+#endif
ctime(&now));
vfprintf(stderr, format, args);
}
@@ -544,10 +566,12 @@ int erts_run_erl_open_fifo(char *pipename,char *w_pipename,char *r_pipename) {
PIPE_STUBNAME, highest_pipe_num+1);
continue;
}
- fprintf(stderr, "Erlang already running on pipe %s.\n", pipename);
+ ERROR1(LOG_ERR, "Erlang already running on pipe %s.\n", pipename);
+ unlink(w_pipename);
return 1;
}
if (create_fifo(r_pipename, PERM) < 0) {
+ unlink(w_pipename);
ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.",
r_pipename);
return 1;
diff --git a/erts/etc/common/run_erl_common.h b/erts/etc/common/run_erl_common.h
index dca1af93f2..3b763ad927 100644
--- a/erts/etc/common/run_erl_common.h
+++ b/erts/etc/common/run_erl_common.h
@@ -51,8 +51,12 @@ int erts_run_erl_write_all(int fd, const char* buf, int len);
char *simple_basename(char *path);
#ifndef LOG_ERR
+#ifdef __OSE__
+#define LOG_ERR 0
+#else
#define LOG_ERR NULL
#endif
+#endif
#define ERROR0(Prio,Format) erts_run_erl_log_error(Prio,__LINE__,Format"\n")
#define ERROR1(Prio,Format,A1) erts_run_erl_log_error(Prio,__LINE__,Format"\n",A1)
diff --git a/erts/etc/common/to_erl_common.c b/erts/etc/common/to_erl_common.c
index 4c38877277..1b2f27fa04 100644
--- a/erts/etc/common/to_erl_common.c
+++ b/erts/etc/common/to_erl_common.c
@@ -49,10 +49,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <termios.h>
#include <dirent.h>
-#include <signal.h>
#include <errno.h>
+
+#ifdef __OSE__
+#include <aio.h>
+#include "ose.h"
+#include "efs.h"
+#include "ose_spi/fm.sig"
+#else /* __UNIX__ */
+#include <termios.h>
+#include <signal.h>
+#endif
+
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
@@ -78,7 +87,11 @@
#define noDEBUG
+#ifdef __OSE__
+#define PIPE_DIR "/pipe/"
+#else
#define PIPE_DIR "/tmp/"
+#endif
#define PIPE_STUBNAME "erlang.pipe"
#define PIPE_STUBLEN strlen(PIPE_STUBNAME)
@@ -92,14 +105,38 @@
#define FILENAME_MAX 250
#endif
-static struct termios tty_smode, tty_rmode;
static int tty_eof = 0;
-static int recv_sig = 0;
static int protocol_ver = RUN_ERL_LO_VER; /* assume lowest to begin with */
static int write_all(int fd, const char* buf, int len);
-static int window_size_seq(char* buf, size_t bufsz);
static int version_handshake(char* buf, int len, int wfd);
+
+
+#ifdef __OSE__
+
+#define SET_AIO(REQ,FD,SIZE,BUFF) \
+ /* Make sure to clean data structure of previous request */ \
+ memset(&(REQ),0,sizeof(REQ)); \
+ (REQ).aio_fildes = FD; \
+ (REQ).aio_offset = FM_POSITION_CURRENT; \
+ (REQ).aio_nbytes = SIZE; \
+ (REQ).aio_buf = BUFF; \
+ (REQ).aio_sigevent.sigev_notify = SIGEV_NONE
+
+#define READ_AIO(REQ,FD,SIZE,BUFF) \
+ SET_AIO(REQ,FD,SIZE,BUFF); \
+ if (aio_read(&(REQ)) != 0) \
+ fprintf(stderr,"aio_read of child_read_req(%d) failed\n",FD)
+
+union SIGNAL {
+ SIGSELECT signo;
+ struct FmReadPtr fm_read_ptr;
+};
+
+#else /* __UNIX__ */
+static int recv_sig = 0;
+static struct termios tty_smode, tty_rmode;
+static int window_size_seq(char* buf, size_t bufsz);
#ifdef DEBUG
static void show_terminal_settings(struct termios *);
#endif
@@ -115,6 +152,7 @@ static void handle_sigwinch(int sig)
{
recv_sig = SIGWINCH;
}
+#endif
static void usage(char *pname)
{
@@ -126,13 +164,22 @@ int to_erl(int argc, char **argv)
{
char FIFO1[FILENAME_MAX], FIFO2[FILENAME_MAX];
int i, len, wfd, rfd;
- fd_set readfds;
- char buf[BUFSIZ];
char pipename[FILENAME_MAX];
int pipeIx = 1;
int force_lock = 0;
int got_some = 0;
+#ifdef __OSE__
+ struct aiocb stdin_read_req, pipe_read_req;
+ FmHandle stdin_fh, pipe_fh;
+ char *stdin_buf, *pipe_buf;
+ char *buf;
+ union SIGNAL *sig;
+#else /* __UNIX__ */
+ char buf[BUFSIZ];
+ fd_set readfds;
+#endif
+
if (argc >= 2 && argv[1][0]=='-') {
switch (argv[1][1]) {
case 'h':
@@ -149,7 +196,13 @@ int to_erl(int argc, char **argv)
}
#ifdef DEBUG
- fprintf(stderr, "%s: pid is : %d\n", argv[0], (int)getpid());
+ fprintf(stderr, "%s: pid is : %d\n", argv[0],(int)
+#ifdef __OSE__
+ current_process()
+#else /* __UNIX__ */
+ getpid()
+#endif
+ );
#endif
strn_cpy(pipename, sizeof(pipename),
@@ -187,6 +240,7 @@ int to_erl(int argc, char **argv)
/* write FIFO */
sn_printf(FIFO2,sizeof(FIFO2),"%s.w",pipename);
+#ifndef __OSE__
/* Check that nobody is running to_erl on this pipe already */
if ((wfd = open (FIFO1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) {
/* Open as server succeeded -- to_erl is already running! */
@@ -200,6 +254,7 @@ int to_erl(int argc, char **argv)
exit(1);
}
}
+#endif
if ((rfd = open (FIFO1, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
#ifdef DEBUG
@@ -226,6 +281,7 @@ int to_erl(int argc, char **argv)
fprintf(stderr, "Attaching to %s (^D to exit)\n\n", pipename);
+#ifndef __OSE__
/* Set break handler to our handler */
signal(SIGINT,handle_ctrlc);
@@ -344,6 +400,8 @@ int to_erl(int argc, char **argv)
#ifdef DEBUG
show_terminal_settings(&tty_smode);
#endif
+
+#endif /* !__OSE__ */
/*
* "Write a ^L to the FIFO which causes the other end to redisplay
* the input line."
@@ -357,10 +415,22 @@ int to_erl(int argc, char **argv)
fprintf(stderr, "Error in writing ^L to FIFO.\n");
}
+#ifdef __OSE__
+ /* we have a tiny stack so we malloc the buffers */
+ stdin_buf = malloc(sizeof(char) * BUFSIZ);
+ pipe_buf = malloc(sizeof(char) * BUFSIZ);
+
+ efs_examine_fd(rfd,FLIB_FD_HANDLE,&pipe_fh);
+ efs_examine_fd(0,FLIB_FD_HANDLE,&stdin_fh);
+ READ_AIO(stdin_read_req,0,BUFSIZ,stdin_buf);
+ READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_buf);
+#endif
+
/*
* read and write
*/
while (1) {
+#ifndef __OSE__
FD_ZERO(&readfds);
FD_SET(0, &readfds);
FD_SET(rfd, &readfds);
@@ -393,8 +463,21 @@ int to_erl(int argc, char **argv)
}
recv_sig = 0;
}
- else if (FD_ISSET(0, &readfds)) {
+ else
+#else /* __OSE__ */
+ SIGSELECT sigsel[] = {0};
+ sig = receive(sigsel);
+ len = 0;
+#endif
+#ifndef __OSE__
+ if (FD_ISSET(0,&readfds)) {
len = read(0, buf, sizeof(buf));
+#else /* __OSE__ */
+ if (sig->signo == FM_READ_PTR_REPLY &&
+ sig->fm_read_ptr.handle == stdin_fh) {
+ len = sig->fm_read_ptr.status == EFS_SUCCESS ? sig->fm_read_ptr.actual : -1;
+ buf = sig->fm_read_ptr.buffer;
+#endif
if (len <= 0) {
close(rfd);
close(wfd);
@@ -406,7 +489,7 @@ int to_erl(int argc, char **argv)
break;
}
/* check if there is an eof character in input */
- for (i = 0; i < len && buf[i] != tty_eof; i++);
+ for (i = 0; i < len-1 && buf[i] != tty_eof; i++);
if (buf[i] == tty_eof) {
fprintf(stderr, "[Quit]\n\r");
break;
@@ -424,14 +507,25 @@ int to_erl(int argc, char **argv)
break;
}
STATUS("\" OK\r\n");
+#ifdef __OSE__
+ aio_dispatch(sig);
+ READ_AIO(stdin_read_req, 0, BUFSIZ, stdin_buf);
+#endif
}
/*
* Read from FIFO, write to terminal.
*/
+#ifndef __OSE__
if (FD_ISSET(rfd, &readfds)) {
STATUS("FIFO read: ");
len = read(rfd, buf, BUFSIZ);
+#else /* __OSE__ */
+ if (sig->signo == FM_READ_PTR_REPLY &&
+ sig->fm_read_ptr.handle == pipe_fh) {
+ len = sig->fm_read_ptr.status == EFS_SUCCESS ? sig->fm_read_ptr.actual : -1;
+ buf = sig->fm_read_ptr.buffer;
+#endif
if (len < 0 && errno == EAGAIN) {
/*
* No data this time, but the writing end of the FIFO is still open.
@@ -457,11 +551,13 @@ int to_erl(int argc, char **argv)
close(wfd);
break;
}
+#ifndef __OSE__
if (protocol_ver >= 1) {
/* Tell run_erl size of terminal window */
signal(SIGWINCH, handle_sigwinch);
raise(SIGWINCH);
}
+#endif
got_some = 1;
}
@@ -476,15 +572,21 @@ int to_erl(int argc, char **argv)
break;
}
STATUS("\" OK\r\n");
+#ifdef __OSE__
+ aio_dispatch(sig);
+ READ_AIO(pipe_read_req, rfd, BUFSIZ, pipe_buf);
+#endif
}
}
}
+#ifndef __OSE__
/*
* Reset terminal characterstics
* XXX
*/
tcsetattr(0, TCSADRAIN, &tty_rmode);
+#endif
return 0;
}
@@ -506,6 +608,7 @@ static int write_all(int fd, const char* buf, int len)
return len;
}
+#ifndef __OSE__
static int window_size_seq(char* buf, size_t bufsz)
{
#ifdef TIOCGWINSZ
@@ -523,6 +626,7 @@ static int window_size_seq(char* buf, size_t bufsz)
#endif /* TIOCGWINSZ */
return 0;
}
+#endif /* !__OSE__ */
/* to_erl run_erl
* | |
@@ -574,7 +678,7 @@ static int version_handshake(char* buf, int len, int wfd)
}
-#ifdef DEBUG
+#if defined(DEBUG) && !defined(__OSE__)
#define S(x) ((x) > 0 ? 1 : 0)
static void show_terminal_settings(struct termios *t)
@@ -604,4 +708,4 @@ static void show_terminal_settings(struct termios *t)
fprintf(stderr,"c_cc:\n");
fprintf(stderr,"c_cc[VEOF] %d\n", t->c_cc[VEOF]);
}
-#endif
+#endif /* DEBUG && !__OSE__ */
diff --git a/erts/etc/ose/run_erl.c b/erts/etc/ose/run_erl.c
index 7e62502be2..c1a258515c 100644
--- a/erts/etc/ose/run_erl.c
+++ b/erts/etc/ose/run_erl.c
@@ -25,10 +25,639 @@
# include "config.h"
#endif
+/* System includes */
+#include <aio.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
-int main(int argc, char **argv)
-{
- fprintf(stderr, "run_erl is not supported on OSE targets.\n");
- return 1;
+/* OSE includes */
+#include "ose.h"
+#include "ose_spi/ose_spi.h"
+#include "efs.h"
+#include "pm.h"
+#include "ose_spi/fm.sig"
+
+/* erts includes */
+#include "run_erl.h"
+#include "run_erl_common.h"
+#include "safe_string.h" /* sn_printf, strn_cpy, strn_cat, etc */
+
+typedef struct RunErlSetup_ {
+ SIGSELECT signo;
+ int run_daemon;
+ char *logdir;
+ char *command;
+ char *pipename;
+ char *blockname;
+} RunErlSetup;
+
+typedef struct ProgramState_ {
+ /* child process */
+ int ifd, ofd;
+ OSDOMAIN domain;
+ PROCESS progpid, mainbid;
+ struct PmProgramInfo *info;
+ /* to_erl */
+ char w_pipe[FILENAME_BUFSIZ],
+ r_pipe[FILENAME_BUFSIZ];
+} ProgramState;
+
+union SIGNAL {
+ SIGSELECT signo;
+ RunErlSetup setup;
+ struct FmReadPtr fm_read_ptr;
+ struct FmWritePtr fm_write_ptr;
+};
+
+static OSBOOLEAN hunt_in_block(char *block_name,
+ char *process_name,
+ PROCESS *pid);
+static int create_child_process(char *command_string, char *blockname,
+ ProgramState *state);
+
+
+static OSBOOLEAN hunt_in_block(char *block_name,
+ char *process_name,
+ PROCESS *pid) {
+ struct OS_pid_list *list;
+ PROCESS block_id = OSE_ILLEGAL_PROCESS;
+ int i;
+ char *name;
+
+ *pid = OSE_ILLEGAL_PROCESS;
+
+ list = get_bid_list(0);
+
+ if (!list)
+ return 0;
+
+ for (i = 0; i < list->count; i++) {
+
+ if (list->list[i] == get_bid(current_process()))
+ continue;
+
+ name = (char*)get_pid_info(list->list[i], OSE_PI_NAME);
+ if (name) {
+ if (strcmp(name,block_name) == 0) {
+ block_id = list->list[i];
+ free_buf((union SIGNAL**)&name);
+ break;
+ }
+ free_buf((union SIGNAL**)&name);
+ }
+ }
+
+ free_buf((union SIGNAL**)&list);
+
+ if (block_id == OSE_ILLEGAL_PROCESS)
+ return 0;
+
+ list = get_pid_list(block_id);
+
+ if (!list)
+ return 0;
+
+ for (i = 0; i < list->count; i++) {
+ name = (char*)get_pid_info(list->list[i], OSE_PI_NAME);
+ if (name) {
+ if (strcmp(name,process_name) == 0) {
+ *pid = list->list[i];
+ free_buf((union SIGNAL**)&name);
+ break;
+ }
+ free_buf((union SIGNAL**)&name);
+ }
+ }
+
+ free_buf((union SIGNAL**)&list);
+
+ if (*pid == OSE_ILLEGAL_PROCESS)
+ return 0;
+
+ return 1;
+
+}
+
+
+static int create_child_process(char *command_string, char *blockname,
+ ProgramState *state) {
+ char *command = command_string;
+ char *argv;
+ int i = 0;
+ int ret_status;
+ PmStatus pm_status;
+ int tmp_io[2];
+ int fd_arr[3];
+ int ifd[2], ofd[2];
+ char *handle;
+ struct PmLoadModuleInfoReply *mod_info;
+
+ /* Parse out cmd and argv from the command string */
+ while (1) {
+ if (command[i] == ' ' || command[i] == '\0') {
+ if (command[i] == '\0')
+ argv = NULL;
+ else {
+ command[i] = '\0';
+ argv = command_string + i + 1;
+ }
+ break;
+ }
+ i++;
+ }
+
+ if (blockname)
+ handle = blockname;
+ else
+ handle = simple_basename(command);
+
+ if (ose_pm_load_module_info(handle,&mod_info) == PM_SUCCESS) {
+ /* Already installed */
+ free_buf((union SIGNAL**)&mod_info);
+ } else if ((pm_status = ose_pm_install_load_module(0,"ELF",command,handle,0,0,NULL))
+ != PM_SUCCESS) {
+ ERROR1(LOG_ERR,"ose_pm_install_load_module failed - pmstatus: 0x%08x\n",
+ pm_status);
+ return 0;
+ }
+
+ state->domain = PM_NEW_DOMAIN;
+
+ pm_status = ose_pm_create_program(&state->domain, handle, 0, 0 , NULL,
+ &state->progpid, &state->mainbid);
+
+ if (pm_status != PM_SUCCESS) {
+ if (pm_status == PM_EINSTALL_HANDLE_IN_USE)
+ ERROR1(LOG_ERR,"ose_pm_create_program failed - "
+ "install handle \"%s\" is in use. You can specify another "
+ "install handle by using the -block option to run_erl.\n",handle);
+ else
+ ERROR1(LOG_ERR,"ose_pm_create_program failed - pmstatus: 0x%08x\n",
+ pm_status);
+ return 0;
+ }
+
+ pm_status = ose_pm_program_info(state->progpid, &state->info);
+ /* FIXME don't forget to free this ((union SIGNAL **)&info) */
+ if (pm_status != PM_SUCCESS) {
+ ERROR1(LOG_ERR,"ose_pm_program_info failed - pmstatus: 0x%08x\n",
+ pm_status);
+ return 0;
+ }
+
+ /* We only clone stdin+stdout, what about stderr? */
+
+ /* create pipes */
+ if (pipe(ifd) < 0) {
+ if (errno == ENOENT)
+ ERRNO_ERR0(LOG_ERR,"The /pipe file system is not available\n");
+ else
+ ERRNO_ERR0(LOG_ERR,"pipe ifd failed\n");
+ return 0;
+ }
+
+ if (pipe(ofd) < 0) {
+ ERRNO_ERR0(LOG_ERR,"pipe ofd failed\n");
+ return 0;
+ }
+
+ /* FIXME Lock? */
+
+ /* backup our stdin stdout */
+ if ((tmp_io[0] = dup(0)) < 0) {
+ ERRNO_ERR0(LOG_ERR,"dup 0 failed\n");
+ return 0;
+ }
+
+ if ((tmp_io[1] = dup(1)) < 0) {
+ ERRNO_ERR0(LOG_ERR,"dup 1 failed\n");
+ return 0;
+ }
+
+ /* set new pipe to fd 0,1 */
+ if (dup2(ifd[1], 1) < 0) {
+ ERRNO_ERR0(LOG_ERR,"dup2 1 failed\n");
+ return 0;
+ }
+
+ if (dup2(ofd[0], 0) < 0) {
+ ERRNO_ERR0(LOG_ERR,"dup2 0 failed\n");
+ return 0;
+ }
+
+ /* clone array to newly created */
+ fd_arr[0] = 2; /* Number of fd's */
+ fd_arr[1] = 0;
+ fd_arr[2] = 1;
+
+ if ((ret_status = efs_clone_array(state->info->main_process, fd_arr))
+ != EFS_SUCCESS) {
+ ERROR1(LOG_ERR,"efs_close_array filed, errcode: %d\n", ret_status);
+ return 0;
+ }
+
+ if (dup2(tmp_io[1], 1) < 0) {
+ ERRNO_ERR0(LOG_ERR,"restoring dup2 1 failed\n");
+ return 0;
+ }
+
+ if (dup2(tmp_io[0], 0) < 0) {
+ ERRNO_ERR0(LOG_ERR,"restoring dup2 1 failed\n");
+ return 0;
+ }
+
+ /* close loose-ends */
+ sf_close(tmp_io[0]);
+ sf_close(tmp_io[1]);
+ sf_close(ifd[1]);
+ sf_close(ofd[0]);
+ state->ifd = ifd[0];
+ state->ofd = ofd[1];
+
+ if (argv && set_env(state->progpid, "ARGV", argv)) {
+ ERRNO_ERR0(LOG_ERR,"something went wrong with set_env\n");
+ }
+
+ /*
+ * Start the program.
+ */
+ pm_status = ose_pm_start_program(state->progpid);
+ if (pm_status != PM_SUCCESS) {
+ ERROR1(LOG_ERR,"ose_pm_install_load_module failed - pmstatus: 0x%08x\n",
+ pm_status);
+ return 0;
+ }
+
+ return 1;
+}
+
+#define SET_AIO(REQ,FD,SIZE,BUFF) \
+ /* Make sure to clean data structure of previous request */ \
+ memset(&(REQ),0,sizeof(REQ)); \
+ (REQ).aio_fildes = FD; \
+ (REQ).aio_offset = FM_POSITION_CURRENT; \
+ (REQ).aio_nbytes = SIZE; \
+ (REQ).aio_buf = BUFF; \
+ (REQ).aio_sigevent.sigev_notify = SIGEV_NONE
+
+#define READ_AIO(REQ,FD,SIZE,BUFF) do { \
+ SET_AIO(REQ,FD,SIZE,BUFF); \
+ if (aio_read(&(REQ)) != 0) \
+ ERRNO_ERR1(LOG_ERR,"aio_read of child_read_req(%d) failed\n",FD); \
+ } while (0)
+
+#define WRITE_AIO(FD,SIZE,BUFF) do { \
+ struct aiocb *write_req = malloc(sizeof(struct aiocb)); \
+ char *write_buff = malloc(sizeof(char)*SIZE); \
+ memcpy(write_buff,BUFF,SIZE); \
+ SET_AIO(*write_req,FD,SIZE,write_buff); \
+ if (aio_write(write_req) != 0) \
+ ERRNO_ERR1(LOG_ERR,"aio_write of write_req(%d) failed\n",FD); \
+ } while(0)
+
+int pass_on(ProgramState *state);
+int pass_on(ProgramState *s) {
+ SIGSELECT sigsel[] = {0,FM_READ_PTR_REPLY};
+ union SIGNAL *sig;
+ char child_read_buff[BUFSIZ], pipe_read_buff[BUFSIZ];
+ struct aiocb child_read_req, pipe_read_req;
+ int rfd, wfd = 0;
+ FmHandle rfh, child_rfh;
+ int outstanding_writes = 0, got_some = 0, child_done = 0;
+
+ if ((rfd = sf_open(s->r_pipe, O_RDONLY, 0)) < 0) {
+ ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.\n", s->r_pipe);
+ rfd = 0;
+ return 1;
+ }
+
+ attach(NULL,s->progpid);
+
+ /* Open the log file */
+ erts_run_erl_log_open();
+
+ efs_examine_fd(rfd,FLIB_FD_HANDLE,&rfh);
+ efs_examine_fd(s->ifd,FLIB_FD_HANDLE,&child_rfh);
+
+ READ_AIO(child_read_req,s->ifd,BUFSIZ,child_read_buff);
+ READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
+
+ while (1) {
+ time_t now,last_activity;
+
+ time(&last_activity);
+ sig = receive_w_tmo(erts_run_erl_log_alive_minutes*60000,sigsel);
+
+ time(&now);
+
+ if (sig) {
+ erts_run_erl_log_activity(0,now,last_activity);
+ } else {
+ /* timeout */
+ erts_run_erl_log_activity(1,now,last_activity);
+ continue;
+ }
+
+ switch (sig->signo) {
+ case OS_ATTACH_SIG: {
+ if (rfd) { sf_close(rfd); rfd = 0; }
+ free_buf(&sig);
+ child_done = 1;
+ /* Make sure to to let all outstanding write request finish */
+ if (outstanding_writes)
+ break;
+ if (wfd) sf_close(wfd);
+ return 0;
+ }
+ case FM_WRITE_PTR_REPLY: {
+ if (sig->fm_write_ptr.status == EFS_SUCCESS) {
+ if (sig->fm_write_ptr.actual < sig->fm_write_ptr.requested) {
+ WRITE_AIO(wfd, sig->fm_write_ptr.requested-sig->fm_write_ptr.actual,
+ sig->fm_write_ptr.buffer+sig->fm_write_ptr.actual);
+ }
+ } else {
+ /* Assume to_erl has terminated. */
+ sf_close(wfd);
+ wfd = 0;
+ }
+ free((char*)sig->fm_write_ptr.buffer);
+ aio_dispatch(sig);
+ if ((--outstanding_writes == 0) && child_done) {
+ if (wfd) sf_close(wfd);
+ return 0;
+ }
+ break;
+ }
+ case FM_READ_PTR_REPLY: {
+ /* Child fd */
+ if (sig->fm_read_ptr.handle == child_rfh) {
+
+ /* Child terminated */
+ if (sig->fm_read_ptr.status != EFS_SUCCESS ||
+ sig->fm_read_ptr.actual == 0) {
+
+ if (rfd) { sf_close(rfd); rfd = 0; }
+
+ if (sig->fm_read_ptr.status != EFS_SUCCESS) {
+ ERROR0(LOG_ERR,"Erlang closed the connection.");
+ aio_dispatch(sig);
+ return 1;
+ }
+
+ /* child closed connection gracefully */
+ aio_dispatch(sig);
+ if (outstanding_writes) {
+ child_done = 1;
+ break;
+ }
+
+ if (wfd) sf_close(wfd);
+
+ return 0;
+ } else {
+ erts_run_erl_log_write(sig->fm_read_ptr.buffer,
+ sig->fm_read_ptr.actual);
+ if (wfd) {
+ WRITE_AIO(wfd, sig->fm_read_ptr.actual, sig->fm_read_ptr.buffer);
+ outstanding_writes++;
+ }
+ aio_dispatch(sig);
+ READ_AIO(child_read_req, s->ifd,BUFSIZ, child_read_buff);
+ }
+ /* pipe fd */
+ } else if (sig->fm_read_ptr.handle == rfh) {
+ if (sig->fm_read_ptr.status != EFS_SUCCESS) {
+ if(rfd) sf_close(rfd);
+ if(wfd) sf_close(wfd);
+ aio_dispatch(sig);
+ ERRNO_ERR0(LOG_ERR,"Error in reading from FIFO.");
+ return 1;
+ }
+ if (sig->fm_read_ptr.actual == 0) {
+ /* to_erl closed its end of the pipe */
+ aio_dispatch(sig);
+ sf_close(rfd);
+ rfd = sf_open(s->r_pipe,O_RDONLY|DONT_BLOCK_PLEASE, 0);
+ if (rfd < 0) {
+ ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.",
+ s->r_pipe);
+ rfd = 0;
+ } else {
+ READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
+ }
+ got_some = 0; /* reset for next session */
+ } else {
+ int len = sig->fm_read_ptr.actual;
+ char *buffer = sig->fm_read_ptr.buffer;
+ if (!wfd) {
+ /* Try to open the write pipe to to_erl. Now that we got some data
+ * from to_erl, to_erl should already be reading this pipe - open
+ * should succeed. But in case of error, we just ignore it.
+ */
+ if ((wfd = sf_open(s->w_pipe, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) {
+ erts_run_erl_log_status("Client expected on FIFO %s, "
+ "but can't open (len=%d)\n",
+ s->w_pipe, sig->fm_read_ptr.actual);
+ sf_close(rfd);
+ rfd = sf_open(s->r_pipe, O_RDONLY|DONT_BLOCK_PLEASE, 0);
+ if (rfd < 0) {
+ ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.",
+ s->r_pipe);
+ return 1;
+ }
+ wfd = 0;
+ } else {
+#ifdef DEBUG
+ erts_run_erl_log_status("run_erl: %s opened for writing\n",
+ s->w_pipe);
+#endif
+ }
+ }
+
+ if (!got_some && wfd && buffer[0] == '\014') {
+ char wbuf[30];
+ int wlen = sn_printf(wbuf,sizeof(wbuf),"[run_erl v%u-%u]\n",
+ RUN_ERL_HI_VER, RUN_ERL_LO_VER);
+ /* For some reason this, the first write aio seems to
+ not get an FM_WRITE_PTR_REPLY, so we do not do:
+ outstanding_writes++;
+ */
+ WRITE_AIO(wfd, wlen, wbuf);
+ }
+ got_some = 1;
+
+ /* Write the message */
+#ifdef DEBUG
+ erts_run_erl_log_status("Pty master write; ");
+#endif
+ len = erts_run_erl_extract_ctrl_seq(buffer,len);
+
+ if (len > 0) {
+ int wlen = erts_run_erl_write_all(s->ofd, buffer, len);
+ if (wlen != len) {
+ aio_dispatch(sig);
+ ERRNO_ERR0(LOG_ERR,"Error in writing to terminal.");
+ if(rfd) sf_close(rfd);
+ if(wfd) sf_close(wfd);
+ return 1;
+ }
+ }
+#ifdef DEBUG
+ erts_run_erl_log_status("OK\n");
+#endif
+ aio_dispatch(sig);
+ READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff);
+ }
+ }
+ break;
+ }
+ default: {
+ free_buf(&sig);
+ break;
+ }
+ }
+ }
+}
+
+OS_PROCESS(run_erl_process) {
+ char *logdir, *command, *blockname;
+ SIGSELECT sigsel[] = {1,ERTS_SIGNAL_RUN_ERL_SETUP};
+ union SIGNAL *sig = receive(sigsel);
+ ProgramState state;
+ char pipename[FILENAME_BUFSIZ];
+
+ state.info = NULL;
+
+ logdir = strdup(sig->setup.logdir);
+ command = strdup(sig->setup.command);
+ strn_cpy(pipename,sizeof(pipename),sig->setup.pipename);
+
+ if (sig->setup.blockname)
+ blockname = strdup(sig->setup.blockname);
+ else
+ blockname = NULL;
+
+ erts_run_erl_log_init(sig->setup.run_daemon, logdir);
+
+ free_buf(&sig);
+
+ if (erts_run_erl_open_fifo(pipename,state.w_pipe,state.r_pipe))
+ kill_proc(current_process());
+
+ if (create_child_process(command,blockname,&state))
+ pass_on(&state);
+
+ free(logdir);
+ free(command);
+ if (blockname)
+ free(blockname);
+
+ if (state.info)
+ free_buf(((union SIGNAL**)&state.info));
+
+ sf_close(state.ifd);
+ sf_close(state.ofd);
+
+ unlink(state.w_pipe);
+ unlink(state.r_pipe);
+
+ kill_proc(current_process());
+}
+
+int run_erl(int argc,char **argv) {
+ char *pipename, *logdir, *command, *blockname = NULL;
+ int pipename_len, logdir_len, command_len, blockname_len = 0;
+ int i = 1, run_daemon = 0;
+ PROCESS pid;
+ SIGSELECT sigsel[] = {0};
+ union SIGNAL *sig;
+
+ if(argc < 4) {
+ fprintf(stderr,RUN_ERL_USAGE,"run_erl");
+ return 1;
+ }
+
+ while (1) {
+ if (argv[i][0] != '-')
+ break;
+ if (!strcmp(argv[i],"-daemon")) {
+ run_daemon = 1;
+ i++;
+ continue;
+ }
+ if (!strcmp(argv[i],"-block")) {
+ blockname = argv[i+1];
+ blockname_len = strlen(argv[i+1]) + 1;
+ i+=2;
+ continue;
+ }
+ fprintf(stderr,RUN_ERL_USAGE,"run_erl");
+ return 1;
+ }
+
+ pipename = argv[i++];
+ logdir = argv[i++];
+ command = argv[i++];
+
+ /* + 1 to include NULL at end */
+ logdir_len = strlen(logdir) + 1;
+ command_len = strlen(command) + 1;
+ pipename_len = strlen(pipename) + 1;
+
+ if (run_daemon) {
+ /* We request that the run_erl_process should be started from the
+ main process so that it does not die when the shell command
+ returns */
+ PROCESS main_pid;
+ hunt_in_block("run_erl","main",&main_pid);
+ sig = alloc(sizeof(sig),ERTS_SIGNAL_RUN_ERL_DAEMON);
+ send(&sig,main_pid);
+ sig = receive(sigsel);
+ pid = sender(&sig);
+ free_buf(&sig);
+ } else {
+ pid = create_process(OS_BG_PROC,"run_erl_process",
+ run_erl_process, 0x800,
+ 0, 0, 0, NULL, 0, 0);
+ }
+
+ sig = alloc(sizeof(RunErlSetup)+
+ logdir_len+command_len+pipename_len+blockname_len,
+ ERTS_SIGNAL_RUN_ERL_SETUP);
+ sig->setup.run_daemon = run_daemon;
+ sig->setup.logdir = ((char*)sig)+sizeof(RunErlSetup);
+ sig->setup.command = ((char*)sig)+sizeof(RunErlSetup)+logdir_len;
+ sig->setup.pipename = ((char*)sig)+sizeof(RunErlSetup)+logdir_len+command_len;
+ if (blockname)
+ sig->setup.blockname = ((char*)sig)+sizeof(RunErlSetup)+
+ logdir_len+command_len+pipename_len;
+ else
+ sig->setup.blockname = NULL;
+
+ strcpy(sig->setup.logdir,logdir);
+ strcpy(sig->setup.command,command);
+ strcpy(sig->setup.pipename,pipename);
+ if (blockname) strcpy(sig->setup.blockname,blockname);
+
+ send(&sig,pid);
+
+ if (run_daemon) {
+ /* We are a daemon, error msgs will be sent to ramlog */
+ start(pid);
+ return 1;
+ }
+
+ /* We are not daemon, error msgs will be sent to stderr and we block here */
+ efs_clone(pid);
+ start(pid);
+
+ attach(NULL,pid);
+ sig = receive(sigsel);
+
+ return 1;
}
diff --git a/erts/etc/ose/to_erl.c b/erts/etc/ose/run_erl.h
index af672159e2..128f551670 100644
--- a/erts/etc/ose/to_erl.c
+++ b/erts/etc/ose/run_erl.h
@@ -16,19 +16,14 @@
*
* %CopyrightEnd%
*/
-/*
- * Module: to_erl.c
- *
- */
+#ifndef ERL_RUN_ERL_H
+#define ERL_RUN_ERL_H
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "ose.h"
+
+#include "erts.sig"
-#include <stdio.h>
+int run_erl(int argc, char **argv);
+OS_PROCESS(run_erl_process);
-int main(int argc, char **argv)
-{
- fprintf(stderr, "to_erl is not supported on OSE targets.\n");
- return 1;
-}
+#endif
diff --git a/erts/etc/ose/run_erl_main.c b/erts/etc/ose/run_erl_main.c
new file mode 100644
index 0000000000..d396ebe93b
--- /dev/null
+++ b/erts/etc/ose/run_erl_main.c
@@ -0,0 +1,77 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2013. 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%
+ */
+/*
+ * Module: run_erl_main.c
+ *
+ * Container for load module that installs both run_erl and to_erl command.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "ose.h"
+#include "shell.h"
+
+#include "run_erl_common.h"
+#include "run_erl.h"
+#include "to_erl_common.h"
+
+union SIGNAL {
+ SIGSELECT signo;
+};
+
+int main(int argc, char **argv)
+{
+
+ char run_erl_usage[320],
+ to_erl_usage[120];
+
+ sprintf(run_erl_usage,RUN_ERL_USAGE,"run_erl [-daemon] [-block blockname]");
+ sprintf(to_erl_usage,TO_ERL_USAGE,"pipename");
+
+ shell_add_cmd_attrs(
+ "run_erl",run_erl_usage,
+ "Redirect Erlang input and output streams",
+ run_erl,DEFAULT_PROC_TYPE,DEFAULT_PRIORITY,DEFAULT_STACK_SIZE);
+
+ shell_add_cmd_attrs(
+ "to_erl",to_erl_usage,
+ "Attach to redirected Erlang input and output streams",
+ to_erl,DEFAULT_PROC_TYPE,DEFAULT_PRIORITY,DEFAULT_STACK_SIZE);
+
+ while (1) {
+ static const SIGSELECT sigsel[] = {0};
+ union SIGNAL *sig = receive(sigsel);
+
+ if (sig->signo == ERTS_SIGNAL_RUN_ERL_DAEMON) {
+ PROCESS pid = create_process(OS_BG_PROC,"run_erl_daemon",
+ run_erl_process, 0x800,
+ 0, 0, 0, NULL, 0, 0);
+ send_w_s(&sig,pid,sender(&sig));
+ } else {
+ printf("Got unexpected signal!");
+ free_buf(&sig);
+ }
+ }
+
+ return 1;
+}