SshStream ssh_stream_fd_wrap2(SshIOHandle readfd, SshIOHandle writefd,
                              Boolean close_on_destroy)
{
  SshFdStream sdata;
  SshStream str;

  sdata = ssh_malloc(sizeof(*sdata));

  if (sdata == NULL)
    return NULL;

  memset(sdata, 0, sizeof(*sdata));
  sdata->readfd = readfd;
  sdata->writefd = writefd;
  sdata->close_on_destroy = close_on_destroy;
  sdata->read_has_failed = FALSE;
  sdata->write_has_failed = FALSE;
  sdata->destroyed = FALSE;
  sdata->keep_nonblocking = FALSE;
  sdata->callback = NULL_FNPTR;
  if (readfd >= 0)
    {
      if (ssh_io_register_fd(readfd, ssh_stream_fd_callback, (void *)sdata)
           == FALSE )
        {
          ssh_free(sdata);
          return NULL;
        }
    }
  if (readfd != writefd && writefd >= 0)
    {
      if (ssh_io_register_fd(writefd, ssh_stream_fd_callback, (void *)sdata)
           == FALSE )
        {
          if (readfd >= 0)
            ssh_io_unregister_fd(readfd,TRUE);
          ssh_free(sdata);
          return NULL;
        }
    }
  str = ssh_stream_create(&ssh_stream_fd_methods, (void *)sdata);
  if (str == NULL)
    {
      ssh_free(sdata);
      if (readfd >= 0)
        ssh_io_unregister_fd(readfd, TRUE);
      if (readfd != writefd && writefd >= 0)
        ssh_io_unregister_fd(writefd, TRUE);
      return NULL;
    }
  return str;

}
SshStream ssh_packet_impl_create(SshPacketReceiveProc received_packet,
                                 SshPacketEofProc received_eof,
                                 SshPacketCanSendProc can_send,
                                 SshPacketImplDestroyProc destroy,
                                 void *context)
{
  SshPacketImpl up;
  SshStream stream;

  /* Allocate and initialize the context. */
  if ((up = ssh_calloc(1, sizeof(*up))) == NULL)
    return NULL;

  ssh_buffer_init(&up->incoming);
  ssh_buffer_init(&up->outgoing);
  ssh_buffer_init(&up->outgoing_packet);
  up->can_receive = FALSE;
  up->incoming_eof = FALSE;
  up->outgoing_eof = FALSE;
  up->up_write_blocked = FALSE;
  up->up_read_blocked = FALSE;
  up->send_blocked = TRUE; /* Cause a callback immediately. */

  /* Save the callback functions. */
  up->received_packet = received_packet;
  up->received_eof = received_eof;
  up->can_send = can_send;
  up->destroy = destroy;
  up->context = context;

  up->up_callback = NULL_FNPTR;
  up->up_context = NULL;

  /* Cause the send callback to be called if non-NULL.  Note that it isn't
     called until from the bottom of the event loop. */
  ssh_packet_impl_restart_send(up);

  /* Wrap it into a stream. */
  stream = ssh_stream_create(&ssh_packet_impl_methods, (void *)up);

  if (stream == NULL)
    ssh_fatal("Insufficient memory to create packet stream object!");

  /* Enable receives. */
  ssh_packet_impl_can_receive(stream, TRUE);

  return stream;
}
Beispiel #3
0
SshStream ssh_stream_fd_wrap2(int readfd, int writefd,
			      Boolean close_on_destroy)
{
  SshFdStream sdata;

  sdata = ssh_xmalloc(sizeof(*sdata));
  memset(sdata, 0, sizeof(*sdata));
  sdata->readfd = readfd;
  sdata->writefd = writefd;
  sdata->close_on_destroy = close_on_destroy;
  sdata->read_has_failed = FALSE;
  sdata->write_has_failed = FALSE;
  sdata->destroyed = FALSE;
  sdata->in_callback = FALSE;
  sdata->keep_nonblocking = FALSE;
  sdata->callback = NULL;
  if (readfd >= 0)
    ssh_io_register_fd(readfd, ssh_stream_fd_callback, (void *)sdata);
  if (readfd != writefd && writefd >= 0)
    ssh_io_register_fd(writefd, ssh_stream_fd_callback, (void *)sdata);
  return ssh_stream_create(&ssh_stream_fd_methods, (void *)sdata);
}
Beispiel #4
0
SshPipeStatus ssh_pipe_create_and_fork(SshStream *stdio_return,
                                       SshStream *stderr_return)
{
    int pin[2], pout[2], perr[2];
    pid_t pid;
    SshPipeStream pipes;

    if (pipe(pin) < 0)
        return SSH_PIPE_ERROR;
    if (pipe(pout) < 0)
    {
        close(pin[0]);
        close(pin[1]);
        return SSH_PIPE_ERROR;
    }
    if (stderr_return != NULL && pipe(perr) < 0)
    {
        close(pin[0]);
        close(pin[1]);
        close(pout[0]);
        close(pout[1]);
        return SSH_PIPE_ERROR;
    }

    /* Initialize SIGCHLD handling.  This will ensure the SIGCHLD won't get
       delivered until we register the handler for the new process below. */
    ssh_sigchld_initialize();

    /* Fork a child process. */
    pid = fork();
    if (pid < 0)
    {
        ssh_warning("Fork failed: %s", strerror(errno));
        close(pin[0]);
        close(pin[1]);
        close(pout[0]);
        close(pout[1]);
        if (stderr_return != NULL)
        {
            close(perr[0]);
            close(perr[1]);
        }
        return SSH_PIPE_ERROR;
    }

    /* The remaining processing depends on whether we are the parent or
       the child. */
    if (pid == 0)
    {
        /* Redirect stdin. */
        close(pin[1]);
        if (dup2(pin[0], 0) < 0)
            perror("dup2 stdin");
        close(pin[0]);

        /* Redirect stdout. */
        close(pout[0]);
        if (dup2(pout[1], 1) < 0)
            perror("dup2 stdout");
        close(pout[1]);

        if (stderr_return != NULL)
        {
            /* Redirect stderr. */
            close(perr[0]);
            if (dup2(perr[1], 2) < 0)
                perror("dup2 stderr");
            close(perr[1]);
        }

        *stdio_return = NULL;
        if (stderr_return != NULL)
            *stderr_return = NULL;
        return SSH_PIPE_CHILD_OK;
    }

    /* Parent */
    pipes = ssh_xcalloc(sizeof(*pipes), 1);
    pipes->pid = pid;
    pipes->callback = NULL;
    pipes->callback_context = NULL;

    pipes->status_returned = FALSE;
    pipes->exit_status = -1;

    /* Close the child-side file descriptors. */
    close(pin[0]);
    close(pout[1]);
    if (stderr_return != NULL)
        close(perr[1]);

    /* Register a handler for SIGCHLD for our new child. */
    ssh_sigchld_register(pid, ssh_pipe_sigchld_handler, (void *)pipes);

    /* Wrap the master fd into a stream. */
    pipes->stdio_stream = ssh_stream_fd_wrap2(pout[0], pin[1], TRUE);
    *stdio_return = ssh_stream_create(&ssh_pipe_methods, (void *) pipes);

    /* Create the stderr stream if requested. */
    /* XXX should another context (errpipes?) be allocated for this, so that
       this, too, could be created as above?*/
    if (stderr_return != NULL)
        *stderr_return = ssh_stream_fd_wrap(perr[0], TRUE);

    return SSH_PIPE_PARENT_OK;
}