diff options
Diffstat (limited to 'erts/etc/vxworks/erl_io.c')
-rw-r--r-- | erts/etc/vxworks/erl_io.c | 108 |
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); +} |