VMS Help
CRTL, decc$set_child_standard_streams
*Conan The Librarian
|
For a child spawned by a function from the exec family of
functions, associates specified file descriptors with a child's
standard streams: stdin, stdout, and stderr.
Format
#include <unixlib.h>
int decc$set_child_standard_streams (int fd1, int fd2, int fd3);
fd1
The file associated with this file descriptor in the parent
process is associated with file descriptor number 0 (stdin) in
the child process. If -1 is specified, the file associated with
the parent's file descriptor number 0 is used (the default).
fd2
The file associated with this file descriptor in the parent
process is associated with file descriptor number 1 (stdout) in
the child process. If -1 is specified, the file associated with
the parent's file descriptor number 1 is used (the default).
fd3
The file associated with this file descriptor in the parent
process is associated with file descriptor number 2 (stderr) in
the child process. If -1 is specified, the file associated with
the parent's file descriptor number 2 is used (the default).
The decc$set_child_standard_streams function allows mapping of
specified file descriptors to the child's stdin/stdout/stderr
streams, thereby compensating, to a certain degree, the lack of a
real fork function on OpenVMS systems.
On UNIX systems, the code between fork and exec is executed in
the context of the child process:
parent:
create pipes p1, p2 and p3
fork
child:
map stdin to p1 like dup2(p1, stdin);
map stdout to p2 like dup2(p2, stdout);
map stderr to p3 like dup2(p3, stderr);
exec (child reads from stdin and writes to stdout and stderr)
exit
parent:
communicates with the child using pipes
On OpenVMS systems, the same task could be achieved as follows:
parent:
create pipes p1, p2 and p3
decc$set_child_standard_streams(p1, p2, p3);
vfork
exec (child reads from stdin and writes to stdout and stderr)
parent:
communicates with the child using pipes
Once established through the call to decc$set_child_standard_
streams, the mapping of the child's standard streams remains in
effect until explicitly disabled by one of the following calls:
decc$set_child_standard_streams(-1, -1, -1);
Or:
decc$set_child_standard_streams(0, 1, 2);
Usually, the child process inherits all its parent's open file
descriptors. However, if file descriptor number n was specified
in the call to decc$set_child_standard_streams, it is not
inherited by the child process as file descriptor number n;
instead, it becomes one of the child's standard streams.
NOTES
o Standard streams can be redirected only to pipes.
o If the parent process redefines the DCL DEFINE command,
this redefinition is not in effect in a subprocess with
user-defined channels. The subprocess always sees the
standard DCL DEFINE command.
o It is the responsibility of the parent process to consume
all the output written by the child process to stdout and
stderr. Depending on how the subprocess writes to stdout
and stderr-in wait or nowait mode-the subprocess might be
placed in LEF state waiting for the reader. For example,
DCL writes to SYS$OUTPUT and SYS$ERROR in a wait mode,
so a child process executing a DCL command procedure will
wait until all the output is read by the parent process.
Recommendation: Read the pipes associated with the child
process' stdout and stderr in a loop until an EOF message
is received, or declare write attention ASTs on these
mailboxes.
o The amount of data written to SYS$OUTPUT depends on the
verification status of the process (SET VERIFY/NOVERIFY
command); the subprocess inherits the verification status
of the parent process. It is the caller's responsibility
to set the verification status of the parent process to
match the expected amount of data written to SYS$OUTPUT
by the subprocess.
o Some applications, like DTM, define SYS$ERROR as
SYS$OUTPUT. If stderr is not redefined by the caller,
it is set in the subprocess as the parent's SYS$ERROR,
which in this case translates to the parent's SYS$OUTPUT.
If the caller redefines stdout to a pipe and does not
redefine stderr, output sent to stderr goes to the pipe
associated with stdout, and the amount of data written
to this mailbox may be more than expected. Although
redefinition of any subset of standard channels is
supported, it is always safe to explicitly redefine all
of them (or at least stdout and stderr) to avoid this
situation.
o For a child process executing a DCL command procedure,
SYS$COMMAND is set to the pipe specified for the child's
stdin so that the parent process can feed the child
requesting data from SYS$COMMAND through the pipe. For
DCL command procedures, it is impossible to pass data
from the parent to the child by means of the child's
SYS$INPUT because for a command procedure, DCL defines
SYS$INPUT as the command file itself.
x The number of file descriptors set for the
child. This number does not include file
descriptors specified as -1 in the call.
-1 indicates that an invalid file descriptor was
specified; errno is set to EBADF.
parent.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int decc$set_child_standard_streams(int, int, int);
main()
{
int fdin[2], fdout[2], fderr[2];
char msg[] = "parent writing to child's stdin";
char buf[80];
int nbytes;
pipe(fdin);
pipe(fdout);
pipe(fderr);
if ( vfork() == 0 ) {
decc$set_child_standard_streams(fdin[0], fdout[1], fderr[1]);
execl( "child", "child" );
}
else {
write(fdin[1], msg, sizeof(msg));
nbytes = read(fdout[0], buf, sizeof(buf));
buf[nbytes] = '\0';
puts(buf);
nbytes = read(fderr[0], buf, sizeof(buf));
buf[nbytes] = '\0';
puts(buf);
}
}
child.c
#include <stdio.h>
#include <unistd.h>
main()
{
char msg[] = "child writing to stderr";
char buf[80];
int nbytes;
nbytes = read(0, buf, sizeof(buf));
write(1, buf, nbytes);
write(2, msg, sizeof(msg));
}
child.com
$ read sys$command s
$ write sys$output s
$ write sys$error "child writing to stderr"
This example program returns the following for both child.c and
child.com:
$ run parent
parent writing to child's stdin
child writing to stderr
Note that in order to activate child.com, you must explicitly
specify execl("child.com", ...) in the parent.c program.