|
From: <cr...@us...> - 2009-03-15 06:00:02
|
Revision: 5108
http://jnode.svn.sourceforge.net/jnode/?rev=5108&view=rev
Author: crawley
Date: 2009-03-15 05:59:57 +0000 (Sun, 15 Mar 2009)
Log Message:
-----------
Lots of changes aimed at getting Bjorne pipelines to work.
Modified Paths:
--------------
trunk/shell/src/shell/org/jnode/shell/AbstractCommand.java
trunk/shell/src/shell/org/jnode/shell/AsyncCommandInvoker.java
trunk/shell/src/shell/org/jnode/shell/CommandRunnable.java
trunk/shell/src/shell/org/jnode/shell/CommandRunner.java
trunk/shell/src/shell/org/jnode/shell/CommandShell.java
trunk/shell/src/shell/org/jnode/shell/CommandThreadImpl.java
trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java
trunk/shell/src/shell/org/jnode/shell/RedirectingInterpreter.java
trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneBuiltin.java
trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneContext.java
trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneInterpreter.java
trunk/shell/src/shell/org/jnode/shell/bjorne/CaseCommandNode.java
trunk/shell/src/shell/org/jnode/shell/bjorne/ColonBuiltin.java
trunk/shell/src/shell/org/jnode/shell/bjorne/CommandNode.java
trunk/shell/src/shell/org/jnode/shell/bjorne/ForCommandNode.java
trunk/shell/src/shell/org/jnode/shell/bjorne/FunctionDefinitionNode.java
trunk/shell/src/shell/org/jnode/shell/bjorne/IfCommandNode.java
trunk/shell/src/shell/org/jnode/shell/bjorne/ListCommandNode.java
trunk/shell/src/shell/org/jnode/shell/bjorne/LoopCommandNode.java
trunk/shell/src/shell/org/jnode/shell/bjorne/SimpleCommandNode.java
trunk/shell/src/shell/org/jnode/shell/io/BaseCommandIO.java
trunk/shell/src/shell/org/jnode/shell/io/CommandIO.java
trunk/shell/src/shell/org/jnode/shell/io/CommandIOMarker.java
trunk/shell/src/shell/org/jnode/shell/io/CommandInput.java
trunk/shell/src/shell/org/jnode/shell/io/CommandInputOutput.java
trunk/shell/src/shell/org/jnode/shell/io/CommandOutput.java
trunk/shell/src/shell/org/jnode/shell/io/Pipeline.java
trunk/shell/src/shell/org/jnode/shell/io/PipelineOutputStream.java
trunk/shell/src/shell/org/jnode/shell/isolate/IsolateCommandInvoker.java
trunk/shell/src/shell/org/jnode/shell/isolate/IsolateCommandThreadImpl.java
trunk/shell/src/shell/org/jnode/shell/proclet/ProcletCommandInvoker.java
trunk/shell/src/test/org/jnode/test/shell/bjorne/BjorneContextTests.java
trunk/shell/src/test/org/jnode/test/shell/bjorne/bjorne-shell-tests.xml
trunk/shell/src/test/org/jnode/test/shell/harness/TestEmu.java
Added Paths:
-----------
trunk/shell/src/shell/org/jnode/shell/bjorne/BjornePipeline.java
trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneSubshellRunner.java
trunk/shell/src/shell/org/jnode/shell/io/CommandIOHolder.java
Removed Paths:
-------------
trunk/shell/src/shell/org/jnode/shell/bjorne/StreamHolder.java
Modified: trunk/shell/src/shell/org/jnode/shell/AbstractCommand.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/AbstractCommand.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/AbstractCommand.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -94,7 +94,7 @@
CommandIO[] myIOs = new CommandIO[] {
new CommandInput(System.in),
new CommandOutput(System.out),
- new CommandOutput(System.err),
+ new CommandOutput(System.err)
};
command.initialize(new CommandLine(args), myIOs);
command.execute();
Modified: trunk/shell/src/shell/org/jnode/shell/AsyncCommandInvoker.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/AsyncCommandInvoker.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/AsyncCommandInvoker.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -107,9 +107,8 @@
CommandRunner cr = null;
CommandIO[] ios = cmdLine.getStreams();
- CommandIO[] resolvedIOs;
try {
- resolvedIOs = commandShell.resolveStreams(ios);
+ commandShell.resolveStreams(ios);
} catch (ClassCastException ex) {
throw new ShellFailureException("streams array broken", ex);
}
@@ -120,7 +119,7 @@
throw new ShellInvocationException("Problem while creating command instance", ex);
}
if (command != null) {
- cr = new CommandRunner(this, cmdInfo, cmdLine, resolvedIOs, sysProps, env);
+ cr = new CommandRunner(this, cmdInfo, cmdLine, ios, sysProps, env);
} else {
try {
method = cmdInfo.getCommandClass().getMethod(MAIN_METHOD, MAIN_ARG_TYPES);
@@ -140,7 +139,7 @@
method.setAccessible(true);
cr = new CommandRunner(
this, cmdInfo, cmdInfo.getCommandClass(), method,
- new Object[] {cmdLine.getArguments()}, resolvedIOs, sysProps, env);
+ new Object[] {cmdLine.getArguments()}, ios, sysProps, env);
} catch (NoSuchMethodException e) {
// continue;
}
@@ -149,9 +148,6 @@
"No entry point method found for " + cmdInfo.getCommandClass());
}
}
-
- // These are now the real streams ...
- cmdLine.setStreams(resolvedIOs);
return cr;
}
Modified: trunk/shell/src/shell/org/jnode/shell/CommandRunnable.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandRunnable.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/CommandRunnable.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -4,4 +4,6 @@
void flushStreams();
+ int getRC();
+
}
Modified: trunk/shell/src/shell/org/jnode/shell/CommandRunner.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandRunner.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/CommandRunner.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -93,7 +93,6 @@
public void run() {
try {
- boolean ok = false;
try {
if (method != null) {
try {
@@ -121,10 +120,9 @@
// bounce us to the older execute(CommandLine, InputStream, PrintStream,
// PrintStream) method.
Command cmd = cmdInfo.createCommandInstance();
- cmd.initialize(commandLine, getIos());
+ cmd.initialize(commandLine, getIOs());
cmd.execute();
}
- ok = true;
} catch (PrivilegedActionException ex) {
Exception ex2 = ex.getException();
if (ex2 instanceof InvocationTargetException) {
@@ -132,26 +130,7 @@
} else {
throw ex2;
}
- } finally {
- IOException savedEx = null;
- // Make sure that we try to flush all IOs, even if some of the flushes
- // result in IOExceptions.
- for (CommandIO io : getIos()) {
- try {
- io.flush();
- } catch (IOException ex) {
- shellErr.println("Failed to flush output: " + ex.getMessage());
- if (ok) {
- savedEx = ex;
- }
- }
- }
- if (savedEx != null) {
- // If we weren't already propagating an exception, and the flush failed,
- // propagate one of the IOExceptions.
- throw savedEx;
- }
- }
+ }
} catch (SyntaxErrorException ex) {
try {
HelpFactory.getHelpFactory().getHelp(commandLine.getCommandName(), cmdInfo).usage(shellErr);
@@ -197,7 +176,7 @@
return args;
}
- public CommandIO[] getIos() {
+ public CommandIO[] getIOs() {
return ios;
}
Modified: trunk/shell/src/shell/org/jnode/shell/CommandShell.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandShell.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/CommandShell.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -979,12 +979,10 @@
}
}
- public CommandIO[] resolveStreams(CommandIO[] ios) {
- CommandIO[] res = new CommandIO[ios.length];
- for (int i = 0; i < res.length; i++) {
- res[i] = resolveStream(ios[i]);
+ public void resolveStreams(CommandIO[] ios) {
+ for (int i = 0; i < ios.length; i++) {
+ ios[i] = resolveStream(ios[i]);
}
- return res;
}
public PrintStream resolvePrintStream(CommandIO io) {
Modified: trunk/shell/src/shell/org/jnode/shell/CommandThreadImpl.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/CommandThreadImpl.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/CommandThreadImpl.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -83,11 +83,7 @@
}
public int getReturnCode() {
- if (this.runner instanceof CommandRunner) {
- return ((CommandRunner) this.runner).getRC();
- } else {
- return 0;
- }
+ return this.runner.getRC();
}
@SuppressWarnings("deprecation")
Modified: trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/DefaultCommandInvoker.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -86,9 +86,9 @@
}
try {
final CommandIO[] ios = cmdLine.getStreams();
- if (ios[0] != CommandLine.DEFAULT_STDIN
- || ios[1] != CommandLine.DEFAULT_STDOUT
- || ios[2] != CommandLine.DEFAULT_STDERR) {
+ if (ios[0] != CommandLine.DEFAULT_STDIN ||
+ ios[1] != CommandLine.DEFAULT_STDOUT ||
+ ios[2] != CommandLine.DEFAULT_STDERR) {
err.println("Warning: redirections ignored by the '"
+ getName() + "' invoker");
}
Modified: trunk/shell/src/shell/org/jnode/shell/RedirectingInterpreter.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/RedirectingInterpreter.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/RedirectingInterpreter.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -332,7 +332,6 @@
// squash
}
prevIOs[Command.STD_OUT] = CommandLine.DEVNULL;
- prev.commandLine.setStreams(prevIOs);
}
} else {
// the previous stage has explicitly redirected stdout
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneBuiltin.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneBuiltin.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneBuiltin.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -30,7 +30,7 @@
BjorneContext context) throws ShellException;
void error(String msg, BjorneContext context) {
- context.resolvePrintStream(context.getStream(Command.STD_ERR)).println(msg);
+ context.resolvePrintStream(context.getIO(Command.STD_ERR)).println(msg);
}
}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneContext.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneContext.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneContext.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -49,15 +49,15 @@
import org.jnode.shell.Command;
import org.jnode.shell.CommandLine;
-import org.jnode.shell.CommandThread;
+import org.jnode.shell.CommandShell;
import org.jnode.shell.PathnamePattern;
import org.jnode.shell.ShellException;
import org.jnode.shell.ShellFailureException;
import org.jnode.shell.ShellSyntaxException;
import org.jnode.shell.io.CommandIO;
-import org.jnode.shell.io.CommandIOMarker;
import org.jnode.shell.io.CommandInput;
import org.jnode.shell.io.CommandOutput;
+import org.jnode.shell.io.CommandIOHolder;
/**
* This class holds the shell variable and stream state for a bjorne shell
@@ -70,10 +70,6 @@
*/
public class BjorneContext {
- public static final CommandIOMarker PIPE_IN = new CommandIOMarker("PIPEIN");
-
- public static final CommandIOMarker PIPE_OUT = new CommandIOMarker("PIPEOUT");
-
private static final int NONE = 0;
private static final int PREHASH = 1;
@@ -122,13 +118,13 @@
private String options = "";
- private StreamHolder[] holders;
+ private CommandIOHolder[] holders;
private boolean echoExpansions;
private BjorneContext parent;
- public BjorneContext(BjorneInterpreter interpreter, StreamHolder[] holders) {
+ public BjorneContext(BjorneInterpreter interpreter, CommandIOHolder[] holders) {
this.interpreter = interpreter;
this.holders = holders;
this.variables = new HashMap<String, VariableSlot>();
@@ -138,12 +134,12 @@
this(interpreter, defaultStreamHolders());
}
- private static StreamHolder[] defaultStreamHolders() {
- StreamHolder[] res = new StreamHolder[4];
- res[Command.STD_IN] = new StreamHolder(CommandLine.DEFAULT_STDIN, false);
- res[Command.STD_OUT] = new StreamHolder(CommandLine.DEFAULT_STDOUT, false);
- res[Command.STD_ERR] = new StreamHolder(CommandLine.DEFAULT_STDERR, false);
- res[Command.SHELL_ERR] = new StreamHolder(CommandLine.DEFAULT_STDERR, false);
+ private static CommandIOHolder[] defaultStreamHolders() {
+ CommandIOHolder[] res = new CommandIOHolder[4];
+ res[Command.STD_IN] = new CommandIOHolder(CommandLine.DEFAULT_STDIN, false);
+ res[Command.STD_OUT] = new CommandIOHolder(CommandLine.DEFAULT_STDOUT, false);
+ res[Command.STD_ERR] = new CommandIOHolder(CommandLine.DEFAULT_STDERR, false);
+ res[Command.SHELL_ERR] = new CommandIOHolder(CommandLine.DEFAULT_STDERR, false);
return res;
}
@@ -227,18 +223,22 @@
/**
* Create a copy of some stream holders without passing ownership.
*/
- public static StreamHolder[] copyStreamHolders(StreamHolder[] holders) {
- StreamHolder[] res = new StreamHolder[holders.length];
+ public static CommandIOHolder[] copyStreamHolders(CommandIOHolder[] holders) {
+ CommandIOHolder[] res = new CommandIOHolder[holders.length];
for (int i = 0; i < res.length; i++) {
- res[i] = new StreamHolder(holders[i]);
+ res[i] = new CommandIOHolder(holders[i]);
}
return res;
}
- StreamHolder[] getCopyOfHolders() {
+ CommandIOHolder[] getCopyOfHolders() {
return copyStreamHolders(holders);
}
+ CommandIOHolder[] getHolders() {
+ return holders;
+ }
+
void setArgs(String[] args) {
this.args = Arrays.asList(args.clone());
}
@@ -749,7 +749,7 @@
case QUERY:
if (value == null) {
String msg = word.length() > 0 ? word : (parameter + " is unset");
- resolvePrintStream(getStream(Command.STD_ERR)).println(msg);
+ resolvePrintStream(getIO(Command.STD_ERR)).println(msg);
throw new BjorneControlException(BjorneInterpreter.BRANCH_EXIT, 1);
} else {
return value;
@@ -757,7 +757,7 @@
case COLONQUERY:
if (value == null || value.length() == 0) {
String msg = word.length() > 0 ? word : (parameter + " is unset or null");
- resolvePrintStream(getStream(Command.STD_ERR)).println(msg);
+ resolvePrintStream(getIO(Command.STD_ERR)).println(msg);
throw new BjorneControlException(BjorneInterpreter.BRANCH_EXIT, 1);
} else {
return value;
@@ -925,30 +925,54 @@
return interpreter.resolveInputStream(stream);
}
- CommandIO getStream(int index) {
+ CommandIO getIO(int index) {
if (index < 0) {
throw new ShellFailureException("negative stream index");
} else if (index < holders.length) {
- return holders[index].stream;
+ return holders[index].getIO();
} else {
return null;
}
}
- void setStream(int index, CommandIO stream, boolean mine) {
+ void setIO(int index, CommandIO io, boolean mine) {
if (index < 0 || index >= holders.length) {
- throw new ShellFailureException("negative stream index");
+ throw new ShellFailureException("bad stream index");
} else {
- holders[index].setStream(stream, mine);
+ holders[index].setIO(io, mine);
}
}
- void closeStreams() {
- for (StreamHolder holder : holders) {
+ void setIO(int index, CommandIOHolder holder) {
+ if (index < 0 || index >= holders.length) {
+ throw new ShellFailureException("bad stream index");
+ } else {
+ holders[index].setIO(holder);
+ }
+ }
+
+ void closeIOs() {
+ for (CommandIOHolder holder : holders) {
holder.close();
}
}
+
+ void flushIOs() {
+ for (CommandIOHolder holder : holders) {
+ holder.flush();
+ }
+ }
+
+ CommandIO[] getIOs() {
+ CommandIO[] io = new CommandIO[holders.length];
+ int i = 0;
+ for (CommandIOHolder holder : holders) {
+ io[i++] = (holder == null) ? null : holder.getIO();
+ }
+ return io;
+ }
+
void performAssignments(BjorneToken[] assignments) throws ShellException {
if (assignments != null) {
for (int i = 0; i < assignments.length; i++) {
@@ -972,8 +996,10 @@
* input/outputStreamTuple streams for this command.
* @throws ShellException
*/
- StreamHolder[] evaluateRedirections(RedirectionNode[] redirects) throws ShellException {
- return evaluateRedirections(redirects, copyStreamHolders(holders));
+ CommandIOHolder[] evaluateRedirections(RedirectionNode[] redirects) throws ShellException {
+ CommandIOHolder[] res = copyStreamHolders(holders);
+ evaluateRedirections(redirects, res);
+ return res;
}
/**
@@ -984,10 +1010,10 @@
* @return the stream state after redirections
* @throws ShellException
*/
- StreamHolder[] evaluateRedirections(
- RedirectionNode[] redirects, StreamHolder[] holders) throws ShellException {
+ void evaluateRedirections(
+ RedirectionNode[] redirects, CommandIOHolder[] holders) throws ShellException {
if (redirects == null) {
- return holders;
+ return;
}
boolean ok = false;
try {
@@ -1018,12 +1044,12 @@
}
// If necessary, grow the fd table.
if (fd >= holders.length) {
- StreamHolder[] tmp = new StreamHolder[fd + 1];
+ CommandIOHolder[] tmp = new CommandIOHolder[fd + 1];
System.arraycopy(holders, 0, tmp, 0, fd + 1);
holders = tmp;
}
- StreamHolder stream;
+ CommandIOHolder stream;
switch (redir.getRedirectionType()) {
case REDIR_DLESS:
throw new UnsupportedOperationException("<<");
@@ -1037,9 +1063,9 @@
throw new ShellException("File already exists");
}
CommandOutput tmp = new CommandOutput(new FileOutputStream(file));
- stream = new StreamHolder(tmp, true);
+ stream = new CommandIOHolder(tmp, true);
} catch (IOException ex) {
- throw new ShellException("Cannot open input file", ex);
+ throw new ShellException("Cannot open output file", ex);
}
break;
@@ -1048,9 +1074,9 @@
try {
FileOutputStream tmp = new FileOutputStream(redir.getArg().getText(),
redir.getRedirectionType() == REDIR_DGREAT);
- stream = new StreamHolder(new CommandOutput(tmp), true);
+ stream = new CommandIOHolder(new CommandOutput(tmp), true);
} catch (IOException ex) {
- throw new ShellException("Cannot open input file", ex);
+ throw new ShellException("Cannot open output file", ex);
}
break;
@@ -1058,7 +1084,7 @@
try {
File file = new File(redir.getArg().getText());
CommandInput tmp = new CommandInput(new FileInputStream(file));
- stream = new StreamHolder(tmp, true);
+ stream = new CommandIOHolder(tmp, true);
} catch (IOException ex) {
throw new ShellException("Cannot open input file", ex);
}
@@ -1067,7 +1093,7 @@
case REDIR_LESSAND:
try {
int fromFd = Integer.parseInt(redir.getArg().getText());
- stream = (fromFd >= holders.length) ? null : new StreamHolder(holders[fromFd]);
+ stream = (fromFd >= holders.length) ? null : new CommandIOHolder(holders[fromFd]);
} catch (NumberFormatException ex) {
throw new ShellException("Invalid fd after >&");
}
@@ -1076,7 +1102,7 @@
case REDIR_GREATAND:
try {
int fromFd = Integer.parseInt(redir.getArg().getText());
- stream = (fromFd >= holders.length) ? null : new StreamHolder(holders[fromFd]);
+ stream = (fromFd >= holders.length) ? null : new CommandIOHolder(holders[fromFd]);
} catch (NumberFormatException ex) {
throw new ShellException("Invalid fd after >&");
}
@@ -1092,18 +1118,13 @@
ok = true;
} finally {
if (!ok) {
- for (StreamHolder holder : holders) {
+ for (CommandIOHolder holder : holders) {
holder.close();
}
}
}
- return holders;
}
- public CommandThread fork(CommandLine command, CommandIO[] ios) throws ShellException {
- return interpreter.fork(command, ios);
- }
-
public boolean patternMatch(CharSequence text, CharSequence pat) {
int flags = PathnamePattern.EAGER | PathnamePattern.DEFAULT_FLAGS;
Pattern regex = PathnamePattern.compilePosixShellPattern(pat, flags);
@@ -1117,4 +1138,13 @@
public int nosArgs() {
return args.size();
}
+
+ public CommandShell getShell() {
+ return interpreter.getShell();
+ }
+
+ public String getName() {
+ return interpreter.getUniqueName();
+ }
+
}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneInterpreter.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneInterpreter.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneInterpreter.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -49,7 +49,6 @@
import org.jnode.shell.CommandInterpreter;
import org.jnode.shell.CommandLine;
import org.jnode.shell.CommandShell;
-import org.jnode.shell.CommandThread;
import org.jnode.shell.Completable;
import org.jnode.shell.IncompleteCommandException;
import org.jnode.shell.ShellException;
@@ -137,6 +136,8 @@
new HashMap<String, BjorneBuiltin>();
private static boolean DEBUG = false;
+
+ private static long subshellCount;
static {
BUILTINS.put("break", new BreakBuiltin());
@@ -235,7 +236,7 @@
myContext = this.context;
} else {
myContext = new BjorneContext(this);
- myContext.setStream(1, new CommandOutput(capture), true);
+ myContext.setIO(1, new CommandOutput(capture), true);
}
BjorneTokenizer tokens = new BjorneTokenizer(command);
CommandNode tree = new BjorneParser(tokens, "> ").parse();
@@ -363,11 +364,12 @@
public InputStream resolveInputStream(CommandIO stream) {
return shell.resolveInputStream(stream);
}
+
+ private static synchronized long getSubshellNumber() {
+ return subshellCount++;
+ }
- public CommandThread fork(CommandLine command, CommandIO[] streams)
- throws ShellException {
- command.setStreams(streams);
- CommandInfo cmdInfo = command.parseCommandLine(shell);
- return shell.invokeAsynchronous(command, cmdInfo);
+ public String getUniqueName() {
+ return getName() + "-" + getSubshellNumber();
}
}
Added: trunk/shell/src/shell/org/jnode/shell/bjorne/BjornePipeline.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/BjornePipeline.java (rev 0)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/BjornePipeline.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -0,0 +1,224 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2003-2009 JNode.org
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; If not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+ package org.jnode.shell.bjorne;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jnode.shell.Command;
+import org.jnode.shell.CommandShell;
+import org.jnode.shell.CommandThread;
+import org.jnode.shell.ShellException;
+import org.jnode.shell.ShellFailureException;
+import org.jnode.shell.ThreadExitListener;
+import org.jnode.shell.io.CommandIO;
+import org.jnode.shell.io.CommandIOHolder;
+import org.jnode.shell.io.CommandIOMarker;
+import org.jnode.shell.io.CommandInput;
+import org.jnode.shell.io.CommandOutput;
+import org.jnode.shell.io.Pipeline;
+
+/**
+ * This class deals with construction and running of multi-command
+ * pipelines for the Bjorne shell.
+ *
+ * @author cr...@jn...
+ */
+class BjornePipeline {
+ private static class PipelineStage {
+ private String stageName;
+ private CommandNode command;
+ private BjorneContext context;
+ private CommandThread thread;
+ private CommandIOHolder[] holders;
+ private BjornePipeline nestedPipeline;
+ }
+
+ private int stageCount = 0;
+ private int nextStage = 0;
+ private final PipelineStage[] stages;
+ private final BjornePipeline parent;
+ private final Map<String, Pipeline> pipes;
+ private int activeStageCount;
+
+
+ BjornePipeline(int len) {
+ this.stages = new PipelineStage[len];
+ this.parent = null;
+ this.pipes = new HashMap<String, Pipeline>();
+ }
+
+ BjornePipeline(BjornePipeline parent, int len) {
+ this.stages = new PipelineStage[len];
+ this.parent = parent;
+ this.pipes = null;
+ }
+
+ void closeStreams() {
+ for (PipelineStage stage : stages) {
+ if (stage != null) {
+ for (CommandIOHolder holder : stage.holders) {
+ holder.close();
+ }
+ if (stage.nestedPipeline != null) {
+ stage.nestedPipeline.closeStreams();
+ }
+ }
+ }
+ }
+
+ void wire() throws ShellException {
+ evaluateRedirections();
+ createPipes();
+ activatePipes();
+ }
+
+ private void evaluateRedirections() throws ShellException {
+ for (PipelineStage stage : stages) {
+ RedirectionNode[] redirects = stage.command.getRedirects();
+ stage.context.evaluateRedirections(redirects, stage.holders);
+ }
+ }
+
+ private void createPipes() throws ShellFailureException {
+ try {
+ for (PipelineStage stage : stages) {
+ for (CommandIOHolder holder : stage.holders) {
+ CommandIO io = holder.getIO();
+ if (io instanceof CommandIOMarker) {
+ CommandIOMarker marker = (CommandIOMarker) io;
+ String name = marker.getName();
+
+ if (name.startsWith("PIPE-")) {
+ holder.setIO(
+ (marker.getDirection() == CommandIO.DIRECTION_OUT ?
+ getOutPipeIO(name) : getInPipeIO(name)),
+ true);
+ }
+ }
+ }
+ if (stage.nestedPipeline != null) {
+ stage.nestedPipeline.createPipes();
+ }
+ }
+ } catch (IOException ex) {
+ throw new ShellFailureException("IO error while creating pipes.");
+ }
+ }
+
+ private CommandIO getOutPipeIO(String name) throws IOException {
+ if (parent != null) {
+ return parent.getOutPipeIO(name);
+ } else {
+ Pipeline pipe = pipes.get(name);
+ if (pipe == null) {
+ pipe = new Pipeline();
+ pipes.put(name, pipe);
+ }
+ return new CommandOutput(pipe.createSource());
+ }
+ }
+
+ private CommandIO getInPipeIO(String name) throws IOException {
+ if (parent != null) {
+ return parent.getInPipeIO(name);
+ } else {
+ Pipeline pipe = pipes.get(name);
+ if (pipe == null) {
+ pipe = new Pipeline();
+ pipes.put(name, pipe);
+ }
+ return new CommandInput(pipe.createSink());
+ }
+ }
+
+ private void activatePipes() {
+ for (Pipeline pipe : pipes.values()) {
+ try {
+ pipe.activate();
+ } catch (IOException ex) {
+ pipe.shutdown();
+ }
+ }
+ }
+
+ int run(CommandShell shell) throws ShellException {
+ for (PipelineStage stage : stages) {
+ stage.thread = stage.command.fork(shell, stage.context);
+ }
+ activeStageCount = stages.length;
+ synchronized (this) {
+ for (PipelineStage stage : stages) {
+ ThreadCallback callback = new ThreadCallback(stage.context);
+ stage.thread.start(callback);
+ }
+ while (activeStageCount > 0) {
+ try {
+ this.wait();
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ break;
+ }
+ }
+ return stages[stages.length - 1].thread.getReturnCode();
+ }
+ }
+
+ void addStage(CommandNode commandNode, BjorneContext context) throws ShellException {
+ int i = nextStage++;
+ PipelineStage stage = stages[i] = new PipelineStage();
+ stage.stageName = stageName();
+ stage.command = commandNode;
+ stage.holders = context.getHolders();
+ if (i > 0) {
+ String pipeName = "PIPE-" + stages[i - 1].stageName;
+ stages[i - 1].holders[Command.STD_OUT].setIO(
+ new CommandIOMarker(pipeName, CommandIO.DIRECTION_OUT), true);
+ stage.holders[Command.STD_IN].setIO(
+ new CommandIOMarker(pipeName, CommandIO.DIRECTION_IN), true);
+ }
+ stage.context = context;
+ stage.nestedPipeline = commandNode.buildPipeline(context);
+ context.evaluateRedirections(commandNode.getRedirects(), stage.holders);
+ }
+
+ private String stageName() {
+ return (parent != null) ? parent.stageName() : ("STAGE-" + ++stageCount);
+ }
+
+ private class ThreadCallback implements ThreadExitListener {
+ private BjorneContext context;
+
+ public ThreadCallback(BjorneContext context) {
+ this.context = context;
+ }
+
+ public void notifyThreadExited(CommandThread thread) {
+ synchronized (BjornePipeline.this) {
+ context.closeIOs();
+ activeStageCount--;
+ if (activeStageCount <= 0) {
+ BjornePipeline.this.notify();
+ }
+ }
+ }
+ }
+}
Added: trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneSubshellRunner.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneSubshellRunner.java (rev 0)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/BjorneSubshellRunner.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -0,0 +1,35 @@
+package org.jnode.shell.bjorne;
+
+import org.jnode.shell.CommandRunnable;
+import org.jnode.shell.ShellException;
+
+public abstract class BjorneSubshellRunner implements CommandRunnable {
+ private int rc;
+ private final BjorneContext context;
+
+ public BjorneSubshellRunner(BjorneContext context) {
+ super();
+ this.context = context;
+ }
+
+ @Override
+ public void flushStreams() {
+ context.flushIOs();
+ }
+
+ @Override
+ public int getRC() {
+ return rc;
+ }
+
+ public final void run() {
+ try {
+ rc = doRun();
+ } catch (ShellException ex) {
+ // FIXME ... this isn't right ...
+ rc = 1;
+ }
+ }
+
+ protected abstract int doRun() throws ShellException;
+}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/CaseCommandNode.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/CaseCommandNode.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/CaseCommandNode.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -20,6 +20,10 @@
package org.jnode.shell.bjorne;
+import org.jnode.shell.CommandRunnable;
+import org.jnode.shell.CommandShell;
+import org.jnode.shell.CommandThread;
+import org.jnode.shell.CommandThreadImpl;
import org.jnode.shell.ShellException;
public class CaseCommandNode extends CommandNode {
@@ -75,4 +79,16 @@
}
return rc;
}
+
+ @Override
+ public CommandThread fork(CommandShell shell, final BjorneContext context)
+ throws ShellException {
+
+ CommandRunnable cr = new BjorneSubshellRunner(context) {
+ @Override
+ public int doRun() throws ShellException {
+ return CaseCommandNode.this.execute(context);
+ }};
+ return new CommandThreadImpl(cr, context.getName());
+ }
}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/ColonBuiltin.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/ColonBuiltin.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/ColonBuiltin.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -30,7 +30,6 @@
* @author cr...@jn...
*/
final class ColonBuiltin extends BjorneBuiltin {
- @SuppressWarnings("deprecation")
public int invoke(CommandLine command, BjorneInterpreter interpreter,
BjorneContext context) throws ShellException {
return 0;
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/CommandNode.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/CommandNode.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/CommandNode.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -20,6 +20,8 @@
package org.jnode.shell.bjorne;
+import org.jnode.shell.CommandShell;
+import org.jnode.shell.CommandThread;
import org.jnode.shell.ShellException;
public abstract class CommandNode {
@@ -59,6 +61,9 @@
public abstract int execute(BjorneContext context) throws ShellException;
+ public abstract CommandThread fork(CommandShell shell, BjorneContext context)
+ throws ShellException;
+
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("nodeType=").append(nodeType);
@@ -82,4 +87,9 @@
}
sb.append(']');
}
+
+ public BjornePipeline buildPipeline(BjorneContext context) throws ShellException {
+ return null;
+ }
+
}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/ForCommandNode.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/ForCommandNode.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/ForCommandNode.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -20,6 +20,10 @@
package org.jnode.shell.bjorne;
+import org.jnode.shell.CommandRunnable;
+import org.jnode.shell.CommandShell;
+import org.jnode.shell.CommandThread;
+import org.jnode.shell.CommandThreadImpl;
import org.jnode.shell.ShellException;
public class ForCommandNode extends CommandNode {
@@ -70,4 +74,16 @@
}
return rc;
}
+
+ @Override
+ public CommandThread fork(CommandShell shell, final BjorneContext context)
+ throws ShellException {
+
+ CommandRunnable cr = new BjorneSubshellRunner(context) {
+ @Override
+ public int doRun() throws ShellException {
+ return ForCommandNode.this.execute(context);
+ }};
+ return new CommandThreadImpl(cr, context.getName());
+ }
}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/FunctionDefinitionNode.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/FunctionDefinitionNode.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/FunctionDefinitionNode.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -20,6 +20,12 @@
package org.jnode.shell.bjorne;
+import org.jnode.shell.CommandRunnable;
+import org.jnode.shell.CommandShell;
+import org.jnode.shell.CommandThread;
+import org.jnode.shell.CommandThreadImpl;
+import org.jnode.shell.ShellException;
+
public class FunctionDefinitionNode extends CommandNode {
private final BjorneToken name;
@@ -52,4 +58,18 @@
public int execute(BjorneContext context) {
return -1;
}
+
+ @Override
+ public CommandThread fork(CommandShell shell, final BjorneContext context)
+ throws ShellException {
+
+ CommandRunnable cr = new BjorneSubshellRunner(context) {
+ @Override
+ public int doRun() throws ShellException {
+ return FunctionDefinitionNode.this.execute(context);
+ }};
+ return new CommandThreadImpl(cr, context.getName());
+ }
+
+
}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/IfCommandNode.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/IfCommandNode.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/IfCommandNode.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -20,6 +20,10 @@
package org.jnode.shell.bjorne;
+import org.jnode.shell.CommandRunnable;
+import org.jnode.shell.CommandShell;
+import org.jnode.shell.CommandThread;
+import org.jnode.shell.CommandThreadImpl;
import org.jnode.shell.ShellException;
public class IfCommandNode extends CommandNode {
@@ -81,4 +85,18 @@
}
return rc;
}
+
+ @Override
+ public CommandThread fork(CommandShell shell, final BjorneContext context)
+ throws ShellException {
+
+ CommandRunnable cr = new BjorneSubshellRunner(context) {
+ @Override
+ public int doRun() throws ShellException {
+ return IfCommandNode.this.execute(context);
+ }};
+ return new CommandThreadImpl(cr, context.getName());
+ }
+
+
}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/ListCommandNode.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/ListCommandNode.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/ListCommandNode.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -20,34 +20,20 @@
package org.jnode.shell.bjorne;
-import java.io.IOException;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
import java.util.List;
import org.jnode.driver.console.CompletionInfo;
-import org.jnode.shell.CommandLine;
+import org.jnode.shell.CommandRunnable;
import org.jnode.shell.CommandShell;
import org.jnode.shell.CommandThread;
+import org.jnode.shell.CommandThreadImpl;
import org.jnode.shell.Completable;
import org.jnode.shell.ShellException;
-import org.jnode.shell.ShellFailureException;
-import org.jnode.shell.ThreadExitListener;
import org.jnode.shell.help.CompletionException;
-import org.jnode.shell.io.CommandIO;
-import org.jnode.shell.io.CommandInput;
-import org.jnode.shell.io.CommandOutput;
-import org.jnode.shell.io.NullInputStream;
-import org.jnode.shell.io.NullOutputStream;
+import org.jnode.shell.io.CommandIOHolder;
public class ListCommandNode extends CommandNode implements Completable {
- private static class PipelineStage {
- private CommandLine command;
- private BjorneContext context;
- private CommandThread thread;
- private StreamHolder[] holders;
- }
private final CommandNode[] commands;
@@ -74,33 +60,24 @@
int listFlags = getFlags();
int rc = 0;
try {
- if (getNodeType() == BjorneInterpreter.CMD_SUBSHELL) {
- // This simulates creating a 'subshell'.
- context = new BjorneContext(context);
- StreamHolder[] holders = context.evaluateRedirections(getRedirects());
- for (int i = 0; i < holders.length; i++) {
- CommandIO stream = holders[i].getStream();
- context.setStream(i, stream, holders[i].isMine());
- }
- }
if ((listFlags & BjorneInterpreter.FLAG_PIPE) != 0) {
- PipelineStage[] stages = assemblePipeline(context);
- boolean done = false;
+ BjornePipeline pipeline = buildPipeline(context);
try {
- rc = runPipeline(stages);
- done = true;
+ pipeline.wire();
+ rc = pipeline.run(context.getShell());
} finally {
- if (!done) {
- // If we are propagating an exception, all streams that
- // were opened by 'assemblePipeline' must be closed.
- for (PipelineStage stage : stages) {
- for (StreamHolder holder : stage.holders) {
- holder.close();
- }
- }
- }
+ pipeline.closeStreams();
}
} else {
+ if (getNodeType() == BjorneInterpreter.CMD_SUBSHELL) {
+ // This simulates creating a 'subshell'.
+ context = new BjorneContext(context);
+ CommandIOHolder[] holders = context.evaluateRedirections(getRedirects());
+ for (int i = 0; i < holders.length; i++) {
+ context.setIO(i, holders[i]);
+ }
+ }
+
for (CommandNode command : commands) {
int commandFlags = command.getFlags();
if ((commandFlags & BjorneInterpreter.FLAG_AND_IF) != 0) {
@@ -118,7 +95,7 @@
}
} finally {
if (getNodeType() == BjorneInterpreter.CMD_SUBSHELL) {
- context.closeStreams();
+ context.closeIOs();
}
}
if ((listFlags & BjorneInterpreter.FLAG_BANG) != 0) {
@@ -127,119 +104,29 @@
return rc;
}
- private class ThreadCallback implements ThreadExitListener {
- private PipelineStage[] stages;
- private int count;
+ @Override
+ public CommandThread fork(CommandShell shell, final BjorneContext context)
+ throws ShellException {
- ThreadCallback(PipelineStage[] stages) {
- this.stages = stages;
- this.count = stages.length;
- }
-
- public void notifyThreadExited(CommandThread thread) {
- synchronized (stages) {
- for (PipelineStage stage : stages) {
- if (stage.thread == thread) {
- for (StreamHolder holder : stage.holders) {
- holder.close();
- }
- break;
- }
- }
- count--;
- if (count <= 0) {
- stages.notify();
- }
- }
- }
+ CommandRunnable cr = new BjorneSubshellRunner(context) {
+ @Override
+ public int doRun() throws ShellException {
+ return ListCommandNode.this.execute(context);
+ }};
+ return new CommandThreadImpl(cr, context.getName());
}
-
- private int runPipeline(final PipelineStage[] stages) throws ShellException {
- for (PipelineStage stage : stages) {
- CommandIO[] streams = new CommandIO[stage.holders.length];
- for (int i = 0; i < streams.length; i++) {
- streams[i] = stage.holders[i].getStream();
- }
- stage.thread = stage.context.fork(stage.command, streams);
- }
- synchronized (stages) {
- ThreadCallback callback = new ThreadCallback(stages);
- for (PipelineStage stage : stages) {
- stage.thread.start(callback);
- }
- while (callback.count > 0) {
- try {
- stages.wait();
- } catch (InterruptedException ex) {
- Thread.currentThread().interrupt();
- break;
- }
- }
- return stages[stages.length - 1].thread.getReturnCode();
- }
- }
- private PipelineStage[] assemblePipeline(BjorneContext context) throws ShellException {
+ public BjornePipeline buildPipeline(BjorneContext context) throws ShellException {
int len = commands.length;
- final StreamHolder pipeInMarker = new StreamHolder(BjorneContext.PIPE_IN, false);
- final StreamHolder pipeOutMarker = new StreamHolder(BjorneContext.PIPE_OUT, false);
- PipelineStage[] stages = new PipelineStage[len];
+ BjornePipeline pipeline = new BjornePipeline(len);
for (int i = 0; i < len; i++) {
- SimpleCommandNode commandNode = (SimpleCommandNode) commands[i];
- PipelineStage stage = stages[i] = new PipelineStage();
- stage.context = new BjorneContext(context);
- stage.context.performAssignments(commandNode.getAssignments());
- stage.command = stage.context.expandAndSplit(commandNode.getWords());
- stage.holders = context.getCopyOfHolders();
- if (i < len - 1) {
- stage.holders[1] = pipeOutMarker;
- }
- if (i > 0) {
- stage.holders[0] = pipeInMarker;
- }
- stage.context.evaluateRedirections(commandNode.getRedirects(), stage.holders);
+ CommandNode commandNode = commands[i];
+ BjorneContext childContext = new BjorneContext(context);
+ pipeline.addStage(commandNode, childContext);
}
- for (int i = 0; i < len - 1; i++) {
- StreamHolder newIn = null, newOut = null;
- PipelineStage thisStage = stages[i];
- PipelineStage nextStage = stages[i + 1];
- if (thisStage.holders[1] == pipeOutMarker) {
- if (nextStage.holders[0] == pipeInMarker) {
- PipedOutputStream pipeOut = new PipedOutputStream();
- PipedInputStream pipeIn = new PipedInputStream();
- try {
- pipeIn.connect(pipeOut);
- } catch (IOException ex) {
- throw new ShellFailureException("plumbing failure", ex);
- }
- newIn = new StreamHolder(new CommandInput(pipeIn), true);
- newOut = new StreamHolder(new CommandOutput(pipeOut), true);
- } else {
- newOut = new StreamHolder(new CommandOutput(new NullOutputStream()), true);
- }
- } else {
- if (nextStage.holders[0] == pipeInMarker) {
- newIn = new StreamHolder(new CommandInput(new NullInputStream()), true);
- }
- }
- if (newOut != null) {
- for (int j = 0; j < thisStage.holders.length; j++) {
- if (thisStage.holders[j] == pipeOutMarker) {
- thisStage.holders[j] = newOut;
- }
- }
- }
- if (newIn != null) {
- for (int j = 0; j < nextStage.holders.length; j++) {
- if (nextStage.holders[j] == pipeInMarker) {
- nextStage.holders[j] = newIn;
- }
- }
- }
- }
- return stages;
+ return pipeline;
}
-
+
@Override
public void complete(CompletionInfo completion, CommandShell shell) throws CompletionException {
// TODO Auto-generated method stub
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/LoopCommandNode.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/LoopCommandNode.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/LoopCommandNode.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -20,6 +20,10 @@
package org.jnode.shell.bjorne;
+import org.jnode.shell.CommandRunnable;
+import org.jnode.shell.CommandShell;
+import org.jnode.shell.CommandThread;
+import org.jnode.shell.CommandThreadImpl;
import org.jnode.shell.ShellException;
public class LoopCommandNode extends CommandNode {
@@ -85,4 +89,16 @@
}
return rc;
}
+
+ @Override
+ public CommandThread fork(CommandShell shell, final BjorneContext context)
+ throws ShellException {
+
+ CommandRunnable cr = new BjorneSubshellRunner(context) {
+ @Override
+ public int doRun() throws ShellException {
+ return LoopCommandNode.this.execute(context);
+ }};
+ return new CommandThreadImpl(cr, context.getName());
+ }
}
Modified: trunk/shell/src/shell/org/jnode/shell/bjorne/SimpleCommandNode.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/SimpleCommandNode.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/SimpleCommandNode.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -21,12 +21,15 @@
package org.jnode.shell.bjorne;
import org.jnode.driver.console.CompletionInfo;
+import org.jnode.shell.CommandInfo;
import org.jnode.shell.CommandLine;
import org.jnode.shell.CommandShell;
+import org.jnode.shell.CommandThread;
import org.jnode.shell.ShellException;
import org.jnode.shell.ShellFailureException;
import org.jnode.shell.help.CompletionException;
import org.jnode.shell.io.CommandIO;
+import org.jnode.shell.io.CommandIOHolder;
public class SimpleCommandNode extends CommandNode implements BjorneCompletable {
@@ -68,7 +71,7 @@
@Override
public int execute(final BjorneContext context) throws ShellException {
- StreamHolder[] holders = null;
+ CommandIOHolder[] holders = null;
int rc;
try {
BjorneToken[] words = getWords();
@@ -85,20 +88,20 @@
BjorneContext childContext = new BjorneContext(context);
childContext.performAssignments(assignments);
holders = childContext.evaluateRedirections(getRedirects());
- CommandIO[] streams = new CommandIO[holders.length];
- for (int i = 0; i < streams.length; i++) {
- streams[i] = holders[i].getStream();
+ CommandIO[] ios = new CommandIO[holders.length];
+ for (int i = 0; i < ios.length; i++) {
+ ios[i] = holders[i].getIO();
}
if ((getFlags() & BjorneInterpreter.FLAG_ASYNC) != 0) {
throw new ShellFailureException(
"asynchronous execution (&) not implemented yet");
} else {
- rc = childContext.execute(command, streams);
+ rc = childContext.execute(command, ios);
}
}
} finally {
if (holders != null) {
- for (StreamHolder holder : holders) {
+ for (CommandIOHolder holder : holders) {
holder.close();
}
}
@@ -109,6 +112,14 @@
context.setLastReturnCode(rc);
return rc;
}
+
+ public CommandThread fork(CommandShell shell, BjorneContext context)
+ throws ShellException {
+ CommandLine command = context.expandAndSplit(getWords());
+ command.setStreams(context.getIOs());
+ CommandInfo cmdInfo = command.parseCommandLine(shell);
+ return shell.invokeAsynchronous(command, cmdInfo);
+ }
@Override
public void complete(CompletionInfo completion, BjorneContext context, CommandShell shell)
Deleted: trunk/shell/src/shell/org/jnode/shell/bjorne/StreamHolder.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/bjorne/StreamHolder.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/bjorne/StreamHolder.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -1,65 +0,0 @@
-/*
- * $Id$
- *
- * Copyright (C) 2003-2009 JNode.org
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; If not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-package org.jnode.shell.bjorne;
-
-import java.io.IOException;
-
-import org.jnode.shell.io.CommandIO;
-
-public class StreamHolder {
- CommandIO stream;
- private boolean isMine;
-
- public StreamHolder(CommandIO stream, boolean isMine) {
- this.stream = stream;
- this.isMine = isMine;
- }
-
- public StreamHolder(StreamHolder other) {
- this.stream = other.stream;
- this.isMine = false;
- }
-
- public CommandIO getStream() {
- return stream;
- }
-
- public void setStream(CommandIO stream, boolean isMine) {
- close();
- this.stream = stream;
- this.isMine = isMine;
- }
-
- public void close() {
- if (isMine) {
- try {
- isMine = false; // just in case we call close twice
- stream.close();
- } catch (IOException ex) {
- // FIXME - should we squash or report this?
- }
- }
- }
-
- public boolean isMine() {
- return isMine;
- }
-}
Modified: trunk/shell/src/shell/org/jnode/shell/io/BaseCommandIO.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/io/BaseCommandIO.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/io/BaseCommandIO.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -78,10 +78,25 @@
}
}
- public abstract void close() throws IOException;
+ public final boolean isPipe() {
+ if (systemObject == null) {
+ return false;
+ } else {
+ return IOUtils.isPipe(systemObject);
+ }
+ }
- public void flush() throws IOException {
+ public synchronized final void close() throws IOException {
+ doClose();
}
+
+ abstract void doClose() throws IOException;
+
+ public synchronized final void flush() throws IOException {
+ doFlush();
+ }
+
+ abstract void doFlush() throws IOException;
@Override
public final PrintStream getPrintStream() throws CommandIOException {
Modified: trunk/shell/src/shell/org/jnode/shell/io/CommandIO.java
===================================================================
--- trunk/shell/src/shell/org/jnode/shell/io/CommandIO.java 2009-03-15 05:55:22 UTC (rev 5107)
+++ trunk/shell/src/shell/org/jnode/shell/io/CommandIO.java 2009-03-15 05:59:57 UTC (rev 5108)
@@ -129,6 +129,13 @@
* @return <code>true</code> if the associated stream is interactive.
*/
public boolean isTTY();
+
+ /**
+ * Query if this CommandIO is associated with a pipe.
+ *
+ * @return <code>true</code> if the associated stream is a pipe.
+ */
+ public boolean isPipe();
/**
* Obtain the 'base' stream object for this CommandIO. This will be
@@ -155,4 +162,5 @@
* @throws IOException
*/
public void flush() throws IOException;
+
}
Added: trunk/shell/src/shell/org/jnode/shell/io/CommandIOHolder.java
==========================================...
[truncated message content] |