Chris Angelico wrote:
>There's a strong convention that zero == success, nonzero == failure,
>so this would apply as-is to a lot of programs. Obviously this
>shouldn't be the one and only way to run a subprocess (this is NOT a
>proposed change to Process.run, it's a separate function), so if you
>want to invoke grep(1) and accept 0 (lines found) and 1 (no lines
>found) but not 2 (error), then you'd make an app-specific function;
>but 0 vs other is common enough that I think this fits the standard
>library.

>Example of prior art: Python's subprocess.check_call and check_output
>functions raise an exception on non-zero return value:

Well, ok, fair enough.  But then, try to improve on the interface and
preferably make it work like this:
(unless there already is an easy Pike-API for this, I'm not intimately
familiar with the Process-group)

// This leaves stdin and stdout and stderr unaltered
Process.pipe.run("fgrep -e test").run("sort").run("wc");

string s = "Your.input.text";

// This leaves stdout and stderr unaltered
Process.pipe.stdin(s).run("fgrep -e test").run("sort").run("wc");

Stdio.File in = Stdio.File("foo.bar.file");
Stdio.File out = Stdio.FakeFile();

// This leaves stderr unaltered
Process.pipe.stdin(in).run("fgrep -e test").run("sort")
  .run("wc").stdout(out);
string output = out->read();

Stdio.File in = Stdio.File("foo.bar.file");
Stdio.File out = Stdio.FakeFile();
Stdio.File devnull = Stdio.File("/dev/null","w");

// This leaves stderr unaltered, except for the "sort" run, we silence it there
Process.pipe.stdin(in).run("fgrep -e test").stderr(devnull).run("sort")
  .run("wc").stdout(out);
string output = out->read();

Stdio.File in = Stdio.File("foo.bar.file");
Stdio.File out = Stdio.FakeFile();
Stdio.File devnull = Stdio.File("/dev/null","w");
Stdio.File sortout = Stdio.FakeFile();

// This leaves stderr unaltered, except for the "sort" run, we silence it there
// The stdout of sort is copied to both the sortout file, and to the wc
// process (compare "man 1 tee")
Process.pipe.stdin(in).run("fgrep -e test").stderr(devnull).run("sort")
  .tee(sortout).run("wc").stdout(out);
string sortoutput = sortout->read();
string output = out->read();


In all this, yes, throw exceptions if any of the processes returns non-zero
exitcodes.
In essence the above interface would allow you to run arbitrarily complex
(shell-like) pipes, basically supporting everything bash does too.
Maybe the only thing missing here would be the ability to ignore certain
signals per remainder of the process train, e.g.:

Process.pipe.stdin(in).blocksignal(SIGHUP).run("fgrep -e test")
 .stderr(devnull).run("sort").tee(sortout)
 .unblocksignal(SIGHUP).run("wc").stdout(out);

Which would tie SIGHUP to SIG_IGN for fgrep and sort, and allow it through
again for wc.

As an extra convenience function, I could imagine this:

string output = Process.pipe.stdin(in).run("fgrep -e test").run("sort")
  .run("wc").stdoutstring;

Which would generate that output string you are after in one-go.
-- 
Stephen.

Reply via email to