ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/rtprocess.h
Revision: 3.19
Committed: Fri Feb 28 16:23:47 2020 UTC (4 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 3.18: +44 -1 lines
Log Message:
Added more comments about how to use new filtering features

File Contents

# User Rev Content
1 greg 3.19 /* RCSid $Id: rtprocess.h,v 3.18 2020/02/28 05:18:49 greg Exp $ */
2 schorsch 3.1 /*
3     * rtprocess.h
4     * Routines to communicate with separate process via dual pipes
5     *
6     * WARNING: On Windows, there's a system header named <process.h>.
7     */
8     #ifndef _RAD_PROCESS_H_
9     #define _RAD_PROCESS_H_
10    
11 schorsch 3.3 #include <errno.h>
12 greg 3.13 #include <stdio.h>
13 schorsch 3.16 #if defined(_WIN32) || defined(_WIN64)
14 schorsch 3.3 #include <windows.h> /* DWORD etc. */
15 schorsch 3.10 typedef DWORD RT_PID;
16 schorsch 3.3 #include <process.h> /* getpid() and others */
17 schorsch 3.16 #define getpid _getpid
18     #define execv _execv
19 greg 3.17 #define execvp _execvp
20 schorsch 3.1 #else
21     #include <sys/param.h>
22 schorsch 3.10 #include <sys/types.h>
23     typedef pid_t RT_PID;
24 schorsch 3.1 #endif
25    
26     #include "paths.h"
27    
28 schorsch 3.4 #ifdef __cplusplus
29     extern "C" {
30     #endif
31 schorsch 3.1
32     /* On Windows, a process ID is a DWORD. That might actually be the
33     same thing as an int, but it's better not to assume anything.
34    
35     This means that we shouldn't rely on PIDs and file descriptors
36     being the same type, so we have to describe processes with a struct,
37 schorsch 3.10 instead of the original int[3]. For that purpose, we typedef a
38     platform independent RT_PID.
39 schorsch 3.1 */
40    
41 greg 3.18 /* On Unix, we can set flags and assign descriptors before opening a
42     process, coupling an existing input or output to the new process rather
43     than opening both pipes. If PF_FILT_INP is passed in the flags member of
44     SUBPROC, then the given r stream will be attached to the standard input
45     of the child process, and subsequent reads from that descriptor in the
46     parent get data from the standard output of the child, instead. The
47     returned w descriptor is set to -1, since there is no longer any way
48     to write to the input of the child. The default r descriptor of 0 will
49     compel the child to act as a filter on the standard input of the parent.
50     Whatever r handle you specify, the child will filter its read operations.
51     Note that this should be called before anything has been buffered using r.
52     If PF_FILT_OUT is set in flags, then the given w stream will be
53     attached to the standard output of the child, and subsequent writes
54     to that descriptor in the parent send data to the standard input
55     of the child. The returned r descriptor is set to -1, since
56     there is no output to read from any longer in the child. The
57     default w descriptor of 1 will cause the child to act as a filter
58     on the output of the parent. Make sure to call fflush(stdout) first
59     if any data was buffered. It is illegal to set both PF_FILT_INP and
60     PF_FILT_OUT, as a circular process is guaranteed to hang.
61 greg 3.19
62     If you want behavior similar to popen(cmd, "w") (again Unix-only),
63     keeping stdout open in parent, use a duplicate descriptor like so:
64     {
65     SUBPROC rtp = sp_inactive;
66     FILE *fout;
67     fflush(stdout);
68     rtp.w = dup(fileno(stdout));
69     rtp.flags |= PF_FILT_OUT;
70     if (open_process(&rtp, cmd_argv) <= 0) {
71     perror(cmd_argv[0]); exit(1);
72     }
73     fout = fdopen(rtp.w, "w");
74     ...write data to filter using fout until finished...
75     fclose(fout);
76     if (close_process(&rtp)) {
77     perror(cmd_argv[0]); exit(1);
78     }
79     ...can continue sending data directly to stdout...
80     }
81     We could also have called open_process() after fdopen() above, or after
82     using fopen() on a file if we wanted to insert our filter before it.
83     A similar sequence may be used to filter from stdin without closing
84     it, though process termination becomes more difficult with two readers.
85     Filtering input from a file works better, since the file is then read by
86     the child only, as in:
87     {
88     SUBPROC rtp = sp_inactive;
89     FILE *fin = fopen(fname, "r");
90     if (fin == NULL) {
91     open_error(fname); exit(1);
92     }
93     rtp.r = fileno(fin);
94     rtp.flags |= PF_FILT_INP;
95     if (open_process(&rtp, cmd_argv) <= 0) {
96     perror(cmd_argv[0]); fclose(fin); exit(1);
97     }
98     ...read filtered file data from fin until EOF...
99     fclose(fin);
100     if (close_process(&rtp)) {
101     perror(cmd_argv[0]); exit(1);
102     }
103     }
104 greg 3.18 */
105    
106 schorsch 3.1
107     #ifndef PIPE_BUF
108     #ifdef PIPSIZ
109     #define PIPE_BUF PIPSIZ
110     #else
111     #ifdef PIPE_MAX
112     #define PIPE_BUF PIPE_MAX
113     #else
114     #define PIPE_BUF 512 /* hyperconservative */
115     #endif
116     #endif
117     #endif
118 greg 3.18 /* process flags */
119     #define PF_RUNNING 1 /* process is running */
120     #define PF_FILT_INP 2 /* use assigned read descriptor */
121     #define PF_FILT_OUT 4 /* use assigned write descriptor */
122 schorsch 3.1
123     typedef struct {
124 greg 3.18 int flags; /* what is being done */
125     int r; /* read handle */
126     int w; /* write handle */
127     RT_PID pid; /* process ID */
128 schorsch 3.1 } SUBPROC;
129    
130 greg 3.18 #define SP_INACTIVE {0,0,1,-1} /* for static initializations */
131 schorsch 3.1
132 greg 3.15 #define close_process(pd) close_processes(pd,1)
133    
134 schorsch 3.1 extern int open_process(SUBPROC *pd, char *av[]);
135 greg 3.15 extern int close_processes(SUBPROC pd[], int nproc);
136 schorsch 3.1 extern int process(SUBPROC *pd, char *recvbuf, char *sendbuf, int nbr, int nbs);
137     extern int readbuf(int fd, char *bpos, int siz);
138     extern int writebuf(int fd, char *bpos, int siz);
139 schorsch 3.5
140 schorsch 3.16 #if defined(_WIN32) || defined(_WIN64)
141 schorsch 3.5 /* any non-negative increment will send the process to IDLE_PRIORITY_CLASS. */
142 greg 3.14 extern int win_kill(RT_PID pid, int sig /* ignored */);
143 schorsch 3.5 extern int win_nice(int inc);
144     #endif
145 schorsch 3.1
146 greg 3.18 extern SUBPROC sp_inactive;
147 schorsch 3.1
148     #ifdef __cplusplus
149     }
150     #endif
151     #endif /* _RAD_PROCESS_H_ */
152