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);
1 – Arguments
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).
2 – Description
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.
3 – Return Values
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.
4 – Example
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.