1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
/*
* Copyright 2005 Bart Massey.
* All Rights Reserved. See the file COPYING in this directory
* for licensing information.
*/
/*
* Implementation of process manipulation functions.
*/
namespace Process {
import File, Thread;
public void system(string cmd, string args ...)
/* Fork a separate process. The string cmd is the
actual command to be executed, whereas args forms
the argument vector. */
{
file[3] descs = {stdin, stdout, stderr};
int pid = filter(cmd, args, descs);
}
public void copy(file readfd, file writefd)
/* Generic copy-input-to-output sometimes useful
in process manipulation. */
{
while (!end(readfd))
putb(getb(readfd), writefd);
}
public typedef void(file) agent;
public void run_process(agent writer, agent reader,
string cmd, string args ...)
/* Run a separate process, invoking an extra thread
so that the process can be concurrently written
to and read from. The writer should accept a
file descriptor suitable for writing, the reader
a file descriptor suitable for reading. The
string cmd is the actual command to be executed,
whereas args forms the argument vector. Return
when both the writer and reader have returned. */
{
file[*] inpipe = mkpipe();
file[*] outpipe = mkpipe();
file[3] descs = {inpipe[0], outpipe[1], stderr};
int pid = filter(cmd, args, descs);
close(inpipe[0]);
close(outpipe[1]);
thread t = fork(reader(outpipe[0]));
writer(inpipe[1]);
close(inpipe[1]);
join(t);
close(outpipe[0]);
}
public typedef enum {
read,
write
} popen_direction;
public file popen(popen_direction d, bool nullf,
string cmd, string args ...)
/* Return a file descriptor suitable for reading
(when d = read) or writing (when d = write) a
separate process. If nullf is true, the unused
descriptor will be connected to /dev/null.
Otherwise, it will be connected to standard input
(when d = read) or standard output (when d =
write). The string cmd is the actual command to
be executed, whereas args forms the argument
vector. */
{
switch(nullf) {
case true:
switch(d) {
case popen_direction.read:
twixt(file[*] pipe = mkpipe(); close(pipe[1])) {
twixt(file nullf = open("/dev/null", "r"); close(nullf)) {
file[3] descs = {nullf, pipe[1], stderr};
filter(cmd, args, descs);
}
return pipe[0];
}
case popen_direction.write:
twixt(file[*] pipe = mkpipe(); close(pipe[0])) {
twixt(file nullf = open("/dev/null", "w"); close(nullf)) {
file[3] descs = {pipe[0], nullf, stderr};
filter(cmd, args, descs);
}
return pipe[1];
}
}
break;
case false:
switch(d) {
case popen_direction.read:
twixt(file[*] pipe = mkpipe(); close(pipe[1])) {
file[3] descs = {stdin, pipe[1], stderr};
filter(cmd, args, descs);
return pipe[0];
}
case popen_direction.write:
twixt(file[*] pipe = mkpipe(); close(pipe[0])) {
file[3] descs = {pipe[0], stdout, stderr};
filter(cmd, args, descs);
return pipe[1];
}
}
break;
}
abort("bad popen state");
}
}
|