/* Create a new context. Note that the handlers are set up for a pipe server/client - this way we don't need extra dummy functions */ int _assuan_new_context(assuan_context_t *r_ctx) { static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write, 0, 0 }; assuan_context_t ctx; int rc; *r_ctx = NULL; ctx = xtrycalloc(1, sizeof * ctx); if(!ctx) return _assuan_error(ASSUAN_Out_Of_Core); ctx->input_fd = -1; ctx->output_fd = -1; ctx->inbound.fd = -1; ctx->outbound.fd = -1; ctx->io = &io; ctx->listen_fd = -1; /* Use the pipe server handler as a default. */ ctx->deinit_handler = deinit_pipe_server; ctx->accept_handler = accept_connection; ctx->finish_handler = finish_connection; rc = _assuan_register_std_commands(ctx); if(rc) xfree(ctx); else *r_ctx = ctx; return rc; }
/* Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing 1 - FD has already been accepted. */ int assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd, unsigned int flags) { assuan_context_t ctx; int rc; *r_ctx = NULL; ctx = xtrycalloc (1, sizeof *ctx); if (!ctx) return _assuan_error (ASSUAN_Out_Of_Core); ctx->is_server = 1; if ((flags & 2)) ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */ ctx->input_fd = ASSUAN_INVALID_FD; ctx->output_fd = ASSUAN_INVALID_FD; ctx->inbound.fd = ASSUAN_INVALID_FD; ctx->outbound.fd = ASSUAN_INVALID_FD; if ((flags & 2)) { ctx->listen_fd = ASSUAN_INVALID_FD; ctx->connected_fd = fd; } else { ctx->listen_fd = fd; ctx->connected_fd = ASSUAN_INVALID_FD; } ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server; ctx->accept_handler = ((flags & 2) ? accept_connection_bottom : accept_connection); ctx->finish_handler = finish_connection; ctx->io = &io; if ((flags & 1)) _assuan_init_uds_io (ctx); rc = _assuan_register_std_commands (ctx); if (rc) xfree (ctx); else *r_ctx = ctx; return rc; }
/* This actually is a int file descriptor (and not assuan_fd_t) as _get_osfhandle is called on W32 systems. */ gpg_error_t assuan_init_pipe_server (assuan_context_t ctx, assuan_fd_t filedes[2]) { const char *s; unsigned long ul; gpg_error_t rc; assuan_fd_t infd = ASSUAN_INVALID_FD; assuan_fd_t outfd = ASSUAN_INVALID_FD; int is_usd = 0; TRACE_BEG (ctx, ASSUAN_LOG_CTX, "assuan_init_pipe_server", ctx); if (filedes) { TRACE_LOG2 ("fd[0]=0x%x, fd[1]=0x%x", filedes[0], filedes[1]); } rc = _assuan_register_std_commands (ctx); if (rc) return TRACE_ERR (rc); #ifdef HAVE_W32_SYSTEM infd = filedes[0]; outfd = filedes[1]; #else s = getenv ("_assuan_connection_fd"); if (s && *s && is_valid_socket (s)) { /* Well, we are called with an bi-directional file descriptor. Prepare for using sendmsg/recvmsg. In this case we ignore the passed file descriptors. */ infd = atoi (s); outfd = atoi (s); is_usd = 1; } else if (filedes && filedes[0] != ASSUAN_INVALID_FD && filedes[1] != ASSUAN_INVALID_FD ) { /* Standard pipe server. */ infd = filedes[0]; outfd = filedes[1]; } else { rc = _assuan_error (ctx, GPG_ERR_ASS_SERVER_START); return TRACE_ERR (rc); } #endif ctx->is_server = 1; ctx->engine.release = _assuan_server_release; ctx->engine.readfnc = _assuan_simple_read; ctx->engine.writefnc = _assuan_simple_write; ctx->engine.sendfd = NULL; ctx->engine.receivefd = NULL; ctx->max_accepts = 1; s = getenv ("_assuan_pipe_connect_pid"); if (s && (ul=strtoul (s, NULL, 10)) && ul) ctx->pid = (pid_t)ul; else ctx->pid = (pid_t)-1; ctx->accept_handler = NULL; ctx->finish_handler = _assuan_server_finish; ctx->inbound.fd = infd; ctx->outbound.fd = outfd; if (is_usd) _assuan_init_uds_io (ctx); return TRACE_SUC(); }