Skip to content

Commit

Permalink
Implementing standard input redirection
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchpaulus committed Sep 17, 2024
1 parent 0379e37 commit c7aba54
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 9 deletions.
70 changes: 61 additions & 9 deletions mshell/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,35 @@ public EvalResult Evaluate(List<TokenNew> tokens, Stack<MShellObject> stack, Exe
}

}
else if (t.TokenType == TokenType.LESSTHAN)
{
// This can either be normal comparison for numbers, or it's a redirect on a list.
index++;
if (stack.Count < 2) return FailWithMessage($"'{t.RawText}' operator requires at least two objects on the stack. Found {stack.Count} object.\n");

var arg1 = stack.Pop();
var arg2 = stack.Pop();

if (arg1.IsNumeric() && arg2.IsNumeric())
{
_push(new MShellBool(arg2.FloatNumeric() < arg1.FloatNumeric()), stack);
}
else if (arg1.TryPickString(out var s) && arg2.TryPickList(out var list))
{
list.StandardInputFile = s.Content;
// Push the list back on the stack
_push(list, stack);
}
else if (arg1.TryPickString(out s) && arg2.TryPickQuotation(out var quotation))
{
quotation.StandardInputFile = s.Content;
_push(quotation, stack);
}
else
{
return FailWithMessage($"Currently only implemented redirection for '{t.RawText}' operator or numerics.\n");
}
}
else if (t.TokenType == TokenType.PIPE)
{
index++;
Expand Down Expand Up @@ -867,6 +896,8 @@ public EvalResult Evaluate(List<TokenNew> tokens, Stack<MShellObject> stack, Exe
if (o.TryPickQuotation(out var quotation))
{
var evalResult = Evaluate(quotation.Tokens, stack, quotation.Context);
if (quotation.Context.StandardInput is not null) quotation.Context.StandardInput.Dispose();

if (!evalResult.Success) return evalResult;
if (evalResult.BreakNum != -1) return evalResult;
}
Expand Down Expand Up @@ -901,6 +932,7 @@ private void ExecuteQuotation(MShellQuotation q)

public (EvalResult, int) RunProcess(MShellList list, ExecuteContext context)
{

if (list.Items.Any(o => !o.IsCommandLineable()))
{
var badTypes = list.Items.Where(o => !o.IsCommandLineable());
Expand All @@ -918,7 +950,7 @@ private void ExecuteQuotation(MShellQuotation q)
FileName = arguments[0],
UseShellExecute = false,
RedirectStandardError = false,
RedirectStandardInput = list.StandardInputFile is not null,
RedirectStandardInput = list.StandardInputFile is not null || context.StandardInput is not null,
RedirectStandardOutput = list.StandardOutFile is not null || context.StandardOutput is not null,
CreateNoWindow = true,
};
Expand Down Expand Up @@ -954,8 +986,14 @@ private void ExecuteQuotation(MShellQuotation q)

if (list.StandardInputFile is not null)
{
using StreamWriter w = p.StandardInput;
w.Write(File.ReadAllBytes(list.StandardInputFile));
using FileStream s = new FileStream(list.StandardInputFile, FileMode.Open);
s.CopyTo(p.StandardInput.BaseStream);
p.StandardInput.Close();
}
else if (context.StandardInput is not null)
{
context.StandardInput.CopyTo(p.StandardInput.BaseStream);
p.StandardInput.Close();
}

p.WaitForExit();
Expand Down Expand Up @@ -1003,7 +1041,7 @@ private void ExecuteQuotation(MShellQuotation q)
var firstProcessStartInfo = new ProcessStartInfo()
{
FileName = listItems[0].Items[0].CommandLine(),
RedirectStandardInput = firstList.StandardInputFile is not null,
RedirectStandardInput = firstList.StandardInputFile is not null || context.StandardInput is not null,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
Expand Down Expand Up @@ -1054,6 +1092,13 @@ private void ExecuteQuotation(MShellQuotation q)
{
using FileStream s = new(stdinFile, FileMode.Open);
s.CopyTo(processes[0].StandardInput.BaseStream);
processes[0].StandardInput.BaseStream.Close();
}
else if (context.StandardInput is not null)
{
// using FileStream fs = new(context.StandardInput, FileMode.Open);
context.StandardInput.CopyTo(processes[0].StandardInput.BaseStream);
processes[0].StandardInput.BaseStream.Close();
}

for (int i = 0; i < processes.Count - 1; i++)
Expand Down Expand Up @@ -1497,11 +1542,18 @@ public class MShellQuotation
public string? StandardInputFile { get; set; } = null;
public string? StandardOutputFile { get; set; }= null;

public ExecuteContext Context => new()
public ExecuteContext Context
{
StandardOutput = StandardOutputFile,
StandardInput = StandardInputFile,
};
get
{
Stream? stdIn = (StandardInputFile is null) ? null : new FileStream(StandardInputFile, FileMode.Open);
return new ExecuteContext
{
StandardOutput = StandardOutputFile,
StandardInput = stdIn,
};
}
}

public MShellQuotation(List<TokenNew> tokens, int startIndex, int endIndexExc)
{
Expand Down Expand Up @@ -1606,7 +1658,7 @@ public EvalResult(bool success, int breakNum)
}
public class ExecuteContext()
{
public string? StandardInput { get; set; } = null;
public Stream? StandardInput { get; set; } = null;
public string? StandardOutput { get; set; } = null;

public override string ToString() => $"stdin: '{StandardInput}'\nstdout: '{StandardOutput}'\n";
Expand Down
2 changes: 2 additions & 0 deletions mshell/tests/stdin_for_test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Hello,
World!
7 changes: 7 additions & 0 deletions mshell/tests/stdin_redirect.msh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[grep "World"] "stdin_for_test.txt" < ;

(
[grep "Hello"];
# We shouldn't get a World because the first grep should have consumed all the stdin.
[grep "World"];
) "stdin_for_test.txt" < x
2 changes: 2 additions & 0 deletions mshell/tests/stdin_redirect.msh.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
World!
Hello,

0 comments on commit c7aba54

Please sign in to comment.