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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
*/
#define import_spp
#define import_libc
#define import_xnames
#define import_stdio
#define import_prstat
#include <iraf.h>
/* CPRCON -- Connected subprocesses. A connected subprocess is an active filter
** which communicates with the parent process via an input stream and an output
** stream. A connected subprocess is logically equivalent to the user terminal.
** The set of useful operations thus far identified for connected subprocesses
** are open and close, read and write, and signal (interrupt). The read and
** write operations are provided by interfacing the IPC channels from the
** subprocess to FIO. The remaining operations are peculiar to connected
** subprocesses and are summarized below.
**
** pid = c_propen (process, in, out)
** stat = c_prclose (pid)
** stat = c_prstati (pid, param)
** c_prsignal (pid, signal)
** c_prredir (pid, stream, new_fd)
** c_prchdir (pid, newdir)
** c_prenvset (pid, envvar, valuestr)
**
** A connected subprocess must be opened either with c_propen or with the low
** level procedure PROPCPR (the latter does not require that the subprocess
** recognize the standard IPC protocol). An idle subprocess may be closed
** with c_prclose, which not only closes the process but releases important
** system resources. The c_prsignal procedure raises the X_INT (interrupt)
** exception in a subprocess, generally following receipt of a user interrupt
** by the parent process. Redirection of the child's standard i/o streams
** is provided by c_prredir. Finally, c_prchdir and c_prenvsets are used
** to update the current directory and environment in child processes.
*/
/* C_PROPEN -- Open a connected subprocess, i.e., spawn the subprocess and
** connect the two IPC channels connecting the child and parent to FIO.
** The FIO streams may subsequently be opened for C style STDIO by calling
** FDOPEN, if desired. The C_PROPEN procedure sends the current environment
** and working directory to the child as part of process startup. The process
** id (PID) of the child process is returned as the function value. This
** magic integer value uniquely identifies the process to the system.
**
** N.B.: opening a child process leaves the child in the IRAF Main interpreter
** loop, with the child waiting for a command from the parent. A child process
** is capabable of performing an arbitrary number of "tasks". To get the child
** to run a task, the parent must write the name of the task to the OUT stream,
** then read from the IN stream, responding to all queries from the child until
** "bye" or "error" is received.
*/
unsigned int
c_propen (
char *process, /* filename of executable process */
int *in, /* FD for reading from child */
int *out /* FD for writing to child */
)
{
register unsigned int pid;
XINT x_in = *in, x_out = *out;
iferr (pid = (unsigned int) PROPEN (c_sppstr(process), &x_in, &x_out))
return (NULL);
else {
*in = (int) x_in;
*out = (int) x_out;
FDTOFP(*in)->_fflags |= _FIPC;
return (pid);
}
}
/* C_PRCLOSE -- Close a connected subprocess. The "bye" command is sent to
** the child, commanding it to shut down, and when the task terminates the
** exit status is returned as the function value. The C_PRCLOSE procedure
** must be called at process termination to free system resources. C_PRCLOSE
** is automatically called by the system if error recovery takes place in
** the parent process. Calling C_PRCLOSE is equivalent to individually
** closing the IN and OUT streams to the subprocess (which is what happens
** if system error recovery takes place).
*/
int
c_prclose (
unsigned int pid /* process id returned by C_PROPEN */
)
{
XINT x_pid = pid;
return (PRCLOSE (&x_pid));
}
/* C_PRSTATI -- Get status on a connected subprocess. See <libc/prstat.h>
** for a list of parameters.
*/
int
c_prstati (
int pid, /* process id of process */
int param /* parameter for which value is ret */
)
{
XINT x_pid = pid, x_param = param;
return (PRSTATI (&x_pid, &x_param));
}
/* C_PRSIGNAL -- Send a signal, i.e., asynchronous interrupt, to a connected
** child process. Currently only the X_INT signal is implemented, and the
** second argument is not used. The value X_INT should nontheless be passed.
*/
int
c_prsignal (
unsigned pid, /* process id of process */
int signal /* not used at present */
)
{
XINT x_pid = pid, x_signal = signal;
iferr (PRSIGNAL (&x_pid, &x_signal))
return (ERR);
else
return (OK);
}
/* C_PRREDIR -- Redirect one of the standard i/o streams of the child process.
** By default the child inherits the standard i/o streams of the parent at
** C_PROPEN time, i.e., the STDOUT of the child is connected to the STDOUT of
** the parent. If the parent's STDOUT is subsequently redirected, e.g., with
** C_FREDIR, the child's output will be redirected as well. More commonly
** one or more of the child's streams will be explicitly redirected with
** C_PRREDIR. Such redirection remains in effect for the life of the
** process, i.e., until process termination via C_PRCLOSE or until another
** call to C_PRREDIR. Note that often this is not what is desired, rather,
** one wishes to redirect a stream for the duration of a task running within
** the process. For this reason it is recommended that C_PRREDIR be called
** for each standard stream (it costs almost nothing) immediately prior to
** task execution.
**
** Example:
** fp = fopen ("tmp$spoolfile", "w");
** if (c_prredir (pid, STDOUT, fileno(fp)) == ERR)
** ...
*/
int
c_prredir (
unsigned pid, /* process id of child */
int stream, /* child's stream to be redirected */
int new_fd /* FD of opened file in parent */
)
{
XINT x_pid = pid, x_stream = stream, x_new_fd = new_fd;
iferr (PRREDIR (&x_pid, &x_stream, &x_new_fd))
return (ERR);
else
return (OK);
}
/* C_PRCHDIR -- Change the current working directory of a child process.
** If pid=NULL all currently connected processes are updated. May only
** be called when the child process is idle.
*/
int
c_prchdir (
int pid,
char *newdir
)
{
XINT x_pid = pid;
return (PRCHDIR (&x_pid, c_sppstr (newdir)));
}
/* C_PRENVSET -- Transmit a set environment directive to the child process.
** If pid=NULL all currently connected processes are updated. May only
** be called when the child process is idle.
*/
int
c_prenvset (
int pid,
char *envvar,
char *value
)
{
XCHAR spp_value[SZ_LINE];
XINT x_pid = pid;
c_strupk (value, spp_value, SZ_LINE);
return (PRENVSET (&x_pid, c_sppstr (envvar), spp_value));
}
|