Esempio n. 1
0
static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
  HANDLE handle;

  if (fd == -1) {
    *dup = INVALID_HANDLE_VALUE;
    return ERROR_INVALID_HANDLE;
  }

  handle = uv__get_osfhandle(fd);
  return uv__duplicate_handle(loop, handle, dup);
}
Esempio n. 2
0
static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
  HANDLE handle;

  if (fd == -1) {
    *dup = INVALID_HANDLE_VALUE;
    uv__set_artificial_error(loop, UV_EBADF);
    return -1;
  }

  handle = (HANDLE)_get_osfhandle(fd);
  return uv__duplicate_handle(loop, handle, dup);
}
Esempio n. 3
0
int uv__stdio_create(uv_loop_t* loop, uv_process_options_t* options,
    BYTE** buffer_ptr) {
  BYTE* buffer;
  int count, i;

  count = options->stdio_count;

  if (count < 0 || count > 255) {
    /* Only support FDs 0-255 */
    uv__set_artificial_error(loop, UV_ENOTSUP);
    return -1;
  } else if (count < 3) {
    /* There should always be at least 3 stdio handles. */
    count = 3;
  }

  /* Allocate the child stdio buffer */
  buffer = malloc(CHILD_STDIO_SIZE(count));
  if (buffer == NULL) {
    uv__set_artificial_error(loop, UV_ENOMEM);
    return -1;
  }

  /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
  /* clean up on failure. */
  CHILD_STDIO_COUNT(buffer) = count;
  for (i = 0; i < count; i++) {
    CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
    CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
  }

  for (i = 0; i < count; i++) {
    uv_stdio_container_t fdopt;
    if (i < options->stdio_count) {
      fdopt = options->stdio[i];
    } else {
      fdopt.flags = UV_IGNORE;
    }

    switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
            UV_INHERIT_STREAM)) {
      case UV_IGNORE:
        /* Starting a process with no stdin/stout/stderr can confuse it. */
        /* So no matter what the user specified, we make sure the first */
        /* three FDs are always open in their typical modes, e.g. stdin */
        /* be readable and stdout/err should be writable. For FDs > 2, don't */
        /* do anything - all handles in the stdio buffer are initialized with */
        /* INVALID_HANDLE_VALUE, which should be okay. */
        if (i <= 2) {
          DWORD access = (i == 0) ? FILE_GENERIC_READ :
                                    FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
          if (uv__create_nul_handle(loop,
                                &CHILD_STDIO_HANDLE(buffer, i),
                                access) < 0) {
            goto error;
          }
          CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
        }
        break;

      case UV_CREATE_PIPE: {
        /* Create a pair of two connected pipe ends; one end is turned into */
        /* an uv_pipe_t for use by the parent. The other one is given to */
        /* the child. */
        uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
        HANDLE child_pipe;

        /* Create a new, connected pipe pair. stdio[i].stream should point */
        /* to an uninitialized, but not connected pipe handle. */
        assert(fdopt.data.stream->type == UV_NAMED_PIPE);
        assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
        assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));

        if (uv__create_stdio_pipe_pair(loop,
                                      parent_pipe,
                                      &child_pipe,
                                      fdopt.flags) < 0) {
          goto error;
        }

        CHILD_STDIO_HANDLE(buffer, i) = child_pipe;
        CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
        break;
      }

      case UV_INHERIT_FD: {
        /* Inherit a raw FD. */
        HANDLE child_handle;

        /* Make an inheritable duplicate of the handle. */
        if (uv__duplicate_fd(loop, fdopt.data.fd, &child_handle) < 0) {
          goto error;
        }

        /* Figure out what the type is. */
        switch (GetFileType(child_handle)) {
          case FILE_TYPE_DISK:
            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN;
            break;

          case FILE_TYPE_PIPE:
            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;

          case FILE_TYPE_CHAR:
          case FILE_TYPE_REMOTE:
            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
            break;

          case FILE_TYPE_UNKNOWN:
            if (GetLastError != 0) {
              uv__set_sys_error(loop, GetLastError());
              CloseHandle(child_handle);
              goto error;
            }
            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
            break;

          default:
            assert(0);
        }

        CHILD_STDIO_HANDLE(buffer, i) = child_handle;
        break;
      }

      case UV_INHERIT_STREAM: {
        /* Use an existing stream as the stdio handle for the child. */
        HANDLE stream_handle, child_handle;
        unsigned char crt_flags;
        uv_stream_t* stream = fdopt.data.stream;

        /* Leech the handle out of the stream. */
        if (stream->type == UV_TTY) {
          stream_handle = ((uv_tty_t*) stream)->handle;
          crt_flags = FOPEN | FDEV;
        } else if (stream->type == UV_NAMED_PIPE &&
                   stream->flags & UV_HANDLE_CONNECTED) {
          stream_handle = ((uv_pipe_t*) stream)->handle;
          crt_flags = FOPEN | FPIPE;
        } else {
          stream_handle = INVALID_HANDLE_VALUE;
          crt_flags = 0;
        }

        if (stream_handle == NULL ||
            stream_handle == INVALID_HANDLE_VALUE) {
          /* The handle is already closed, or not yet created, or the */
          /* stream type is not supported. */
          uv__set_artificial_error(loop, UV_ENOTSUP);
          goto error;
        }

        /* Make an inheritable copy of the handle. */
        if (uv__duplicate_handle(loop,
                             stream_handle,
                             &child_handle) < 0) {
          goto error;
        }

        CHILD_STDIO_HANDLE(buffer, i) = child_handle;
        CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags;
        break;
      }

      default:
        assert(0);
    }
  }

  *buffer_ptr  = buffer;
  return 0;

 error:
  uv__stdio_destroy(buffer);
  return -1;
}