aboutsummaryrefslogtreecommitdiffstats
path: root/erts/etc/vxworks/erl_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/etc/vxworks/erl_io.c')
-rw-r--r--erts/etc/vxworks/erl_io.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/erts/etc/vxworks/erl_io.c b/erts/etc/vxworks/erl_io.c
new file mode 100644
index 0000000000..0032b77079
--- /dev/null
+++ b/erts/etc/vxworks/erl_io.c
@@ -0,0 +1,108 @@
+/*
+ * %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%
+ */
+/* Some stuff to let the Erlang and VxWorks shells coexist peacefully.
+ Basically, run Erlang as a spawned task with input redirected to
+ the slave side of a pseudo-tty, and connect explicitly to the master
+ side of the pseudo-tty to send input to Erlang when desired. */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <ioLib.h>
+#include <taskLib.h>
+#include <ptyDrv.h>
+
+extern int spTaskPriority, spTaskOptions;
+
+#define TBUFSIZ 512
+
+#define DEFAULT_STACK_SIZE 100000
+
+static int slavefd = -1, masterfd = -1;
+static run_erl();
+
+/* Frontend to the Erlang startup function - callable from VxWorks shell
+ or script. 'arg' is actually a string passed to the real startup. */
+start_erl(arg)
+int arg;
+{
+ int stacksize;
+ char *stackenv;
+
+ /* create and open the pty - we want the master side to be open
+ all the time, since closing it probably generates EOF on the
+ slave side */
+ (void)ptyDevCreate("/pty/erlang.", TBUFSIZ, TBUFSIZ);
+ if (slavefd != -1)
+ (void)close(slavefd);
+ slavefd = open("/pty/erlang.S", O_RDONLY, 0);
+ if (masterfd != -1)
+ (void)close(masterfd);
+ masterfd = open("/pty/erlang.M", O_WRONLY, 0);
+
+ /* flush any old leftover garbage */
+ (void) ioctl(masterfd, FIOFLUSH, 0);
+ if ((stackenv = getenv("ERLSTACKSIZE")) == NULL)
+ stacksize = DEFAULT_STACK_SIZE;
+ else
+ stacksize = atoi(stackenv);
+ /* spawn Erlang, via stub below */
+ return(taskSpawn("erlang", spTaskPriority, spTaskOptions, stacksize,
+ run_erl, arg, 0,0,0,0,0,0,0,0,0));
+}
+
+/* Little stub that runs in the spawned task - we need this to redirect
+ stdin reliably (redirections aren't "inherited" in VxWorks) */
+static
+run_erl(arg)
+int arg;
+{
+ ioTaskStdSet(0, 0, slavefd); /* redirect stdin to slave side of pty */
+
+ /* We don't want to redirect stdout/err since no one will be reading
+ from the master side (to_erl - and the open()s above - could be
+ made bidirectional, but still the master side would only be read
+ when to_erl was running), and output can eventually fill the pty
+ buffer and cause the Erlang system to block. Not redirecting
+ stdout/err will have the effect that output from Erlang, e.g. the
+ shell prompt, will appear on console/rlogin/whatever even when
+ to_erl isn't running, which may be confusing - can't win 'em all... */
+
+ erl_exec(arg, 0,0,0,0,0,0,0,0); /* call the real startup */
+}
+
+/* Function callable from VxWorks shell to talk to Erlang - stop talking
+ and return to VxWorks shell through ^D (EOF) */
+to_erl()
+{
+ char buf[TBUFSIZ];
+ int cc;
+
+ if (masterfd == -1) { /* sanity check */
+ fprintf(stderr, "Must start_erl first!\n");
+ return(-1);
+ }
+ while ((cc = read(0, buf, TBUFSIZ)) > 0) /* just pass everything through */
+ if (write(masterfd, buf, cc) != cc) {
+ fprintf(stderr, "Write to Erlang failed!\n");
+ return(-1);
+ }
+ return(cc);
+}