/** @brief Initialize the option parser * * @param option_list list of options available * @param name program name for use in messages * @param version program version for use in messages * * @return bool */ int optparse_init(option_decl_t *option_list, const char *name, const char *version) { int result; options = option_list; prg_name = name; prg_version = version; #ifdef OPTPARSE_DEBUG printf("%s:%d: initializing argument list .. ", __FILE__, __LINE__); #endif result = arglist_init(); #ifdef OPTPARSE_DEBUG if (result) { printf("OK\n"); } else { printf("failed\n"); } #endif return result; }
static void lshd_service_request_handler(struct transport_forward *self, uint32_t length, const uint8_t *packet) { struct simple_buffer buffer; unsigned msg_number; const uint8_t *name; uint32_t name_length; simple_buffer_init(&buffer, length, packet); if (parse_uint8(&buffer, &msg_number) && (msg_number == SSH_MSG_SERVICE_REQUEST) && parse_string(&buffer, &name_length, &name) && parse_eod(&buffer)) { CAST(lshd_context, ctx, self->super.ctx); const struct service_entry *service = service_config_lookup(ctx->service_config, name_length, name); if (service) { int pipe[2]; pid_t child; if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe) < 0) { werror("lshd_service_request_handler: socketpair failed: %e.\n", errno); transport_disconnect(&self->super, SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, "Service could not be started"); return; } child = fork(); if (child < 0) { werror("lshd_service_request_handler: fork failed: %e.\n", errno); close(pipe[0]); close(pipe[1]); transport_disconnect(&self->super, SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, "Service could not be started"); return; } if (child) { /* Parent process */ close(pipe[1]); transport_send_packet(&self->super, TRANSPORT_WRITE_FLAG_PUSH, format_service_accept(name_length, name)); /* Setup forwarding. Replaces event_handler and packet_handler. */ transport_forward_setup(self, pipe[0], pipe[0]); } else { /* Child process */ struct arglist args; const char *program; unsigned i; close(pipe[0]); dup2(pipe[1], STDIN_FILENO); dup2(pipe[1], STDOUT_FILENO); close(pipe[1]); /* FIXME: Pass sufficient information so that $SSH_CLIENT can be set properly. */ arglist_init (&args); program = service->args.argv[0]; arglist_push (&args, program); /* If not absolute, interpret it relative to libexecdir. */ if (program[0] != '/') program = lsh_get_cstring(ssh_format("%lz/%lz", ctx->service_config->libexec_dir, program)); for (i = 1; i < service->args.argc; i++) { const char *arg = service->args.argv[i]; if (arg[0] == '$') { if (!strcmp(arg+1, "(session_id)")) arg = lsh_get_cstring(ssh_format("%lxS", self->super.session_id)); } arglist_push (&args, arg); } debug("exec of service %s, program %z. Argument list:\n", name_length, name, program); for (i = 0; i < args.argc; i++) debug(" %z\n", args.argv[i]); execv(program, (char **) args.argv); werror("lshd_service_request_handler: exec of %z failed: %e.\n", args.argv[0], errno); _exit(EXIT_FAILURE); } } else transport_disconnect(&self->super, SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, "Service not available"); } else transport_protocol_error(&self->super, "Invalid SERVICE_REQUEST"); }