File: process.5c

package info (click to toggle)
nickle 2.68-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 2,336 kB
  • ctags: 3,288
  • sloc: ansic: 31,198; yacc: 1,860; lex: 858; sh: 830; makefile: 229
file content (115 lines) | stat: -rw-r--r-- 3,204 bytes parent folder | download | duplicates (7)
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");
    }

}