/* Stderr */ SshStream ssh_stream_fd_stderr(void) { SshStream str; str = ssh_stream_fd_wrap2(2, 2, FALSE); if (str == NULL) ssh_fatal("Insufficient resources to create stderr stream"); return str; }
int main(int argc, char **argv) { SshStream stdio_stream; SshSigner signer; char config_filename[512]; char *temp_name; #ifdef SLEEP_AFTER_STARTUP sleep(30); #endif /* SLEEP_AFTER_STARTUP */ /* Get program name (without path). */ if ((temp_name = strrchr(argv[0], '/')) != NULL) progname = ssh_xstrdup(temp_name + 1); else progname = ssh_xstrdup(argv[0]); /* XXX there should be a way to give command-line parameters to this program, but, they should only be used if the uid is the same as euid. */ ssh_event_loop_initialize(); signer = ssh_xcalloc(1, sizeof(*signer)); #ifdef SIGNER_QUIET signer->quiet = TRUE; #else /* SIGNER_QUIET */ signer->quiet = FALSE; #endif /* SIGNER_QUIET */ ssh_debug_register_callbacks(signer_ssh_fatal, signer_ssh_warning, signer_ssh_debug, (void *)signer); #ifdef SIGNER_DEBUG ssh_debug_set_global_level(5); #endif /* SIGNER_DEBUG */ /* Act as server. */ signer->config = ssh_server_create_config(); SSH_TRACE(2, ("public key file: %s", signer->config->public_host_key_file)); SSH_TRACE(2, ("private key file: %s", signer->config->host_key_file)); SSH_TRACE(2, ("randomseed file: %s", signer->config->random_seed_file)); /* Initialize user context with euid. This is used to dig up the hostkey and such. */ signer->effective_user_data = ssh_user_initialize_with_uid(geteuid(), FALSE); signer->random_state = ssh_randseed_open(signer->effective_user_data, signer->config); /* XXX what about alternative config files? This should be possible to configure somehow. An option for configure is probably a good idea. */ snprintf(config_filename, sizeof(config_filename), "%s/%s", SSH_SERVER_DIR, SSH_SERVER_CONFIG_FILE); if (!ssh_config_read_file(signer->effective_user_data, signer->config, NULL, config_filename, NULL)) ssh_warning("%s: Failed to read config file %s", argv[0], config_filename); stdio_stream = ssh_stream_fd_wrap2(fileno(stdin), fileno(stdout), TRUE); signer->wrapper = ssh_packet_wrap(stdio_stream, signer_received_packet, signer_received_eof, signer_can_send, signer); ssh_event_loop_run(); return 0; }
SshStream ssh_stream_fd_stdio() { return ssh_stream_fd_wrap2(0, 1, FALSE); }
SshStream ssh_stream_fd_wrap(int fd, Boolean close_on_destroy) { return ssh_stream_fd_wrap2(fd, fd, close_on_destroy); }
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; }
SshStream ssh_stream_fd_wrap(SshIOHandle fd, Boolean close_on_destroy) { return ssh_stream_fd_wrap2(fd, fd, close_on_destroy); }