/sys$common/syshlp/HELPLIB.HLB  —  CRTL  decc$set_child_standard_streams
    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.
Close Help