void protocol_start_session(DbXmlSessionData *session) { int r; DbXmlCredentials cred; DbXmlSessionOptions options; DbXmlSessionOptions *options_set; memset(&cred, 0, sizeof(DbXmlCredentials)); memset(&options, 0, sizeof(DbXmlSessionOptions)); if (initial_handshake(session) != 0) return; r = receive_credentials(session, &cred); if (r == 0) r = check_authentication(session, &cred); free_credentials(session, &cred); r = receive_session_options(session, &options); int init = -1; options_set = NULL; if (r == 0) init = r = initialize_session(session, &options, &options_set); session_response(session, r); if (r != 0) return; if (r == 0) r = send_session_options(session, options_set); free_session_options(session, &options); if (r == 0) protocol_request_response(session); if (init == 0) free_session(session); }
/* This function is similar to pipe_connect but uses a socketpair and sets the I/O up to use sendmsg/recvmsg. */ static gpg_error_t socketpair_connect (assuan_context_t ctx, const char *name, const char **argv, assuan_fd_t *fd_child_list, void (*atfork) (void *opaque, int reserved), void *atforkvalue) { gpg_error_t err; int idx; int fds[2]; char mypidstr[50]; pid_t pid; int *child_fds = NULL; int child_fds_cnt = 0; struct at_socketpair_fork atp; int rc; TRACE_BEG3 (ctx, ASSUAN_LOG_CTX, "socketpair_connect", ctx, "name=%s,atfork=%p,atforkvalue=%p", name ? name : "(null)", atfork, atforkvalue); atp.user_atfork = atfork; atp.user_atforkvalue = atforkvalue; atp.parent_pid = getpid (); if (!ctx || (name && (!argv || !argv[0])) || (!name && !argv)) return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE); if (! ctx->flags.no_fixsignals) fix_signals (); sprintf (mypidstr, "%lu", (unsigned long)getpid ()); if (fd_child_list) while (fd_child_list[child_fds_cnt] != ASSUAN_INVALID_FD) child_fds_cnt++; child_fds = _assuan_malloc (ctx, (child_fds_cnt + 2) * sizeof (int)); if (! child_fds) return TRACE_ERR (gpg_err_code_from_syserror ()); child_fds[1] = ASSUAN_INVALID_FD; if (fd_child_list) memcpy (&child_fds[1], fd_child_list, (child_fds_cnt + 1) * sizeof (int)); if (_assuan_socketpair (ctx, AF_LOCAL, SOCK_STREAM, 0, fds)) { TRACE_LOG1 ("socketpair failed: %s", strerror (errno)); _assuan_free (ctx, child_fds); return TRACE_ERR (GPG_ERR_ASS_GENERAL); } atp.peer_fd = fds[1]; child_fds[0] = fds[1]; rc = _assuan_spawn (ctx, &pid, name, argv, ASSUAN_INVALID_FD, ASSUAN_INVALID_FD, child_fds, at_socketpair_fork_cb, &atp, 0); if (rc < 0) { err = gpg_err_code_from_syserror (); _assuan_close (ctx, fds[0]); _assuan_close (ctx, fds[1]); _assuan_free (ctx, child_fds); return TRACE_ERR (err); } /* For W32, the user needs to know the server-local names of the inherited handles. Return them here. Note that the translation of the peer socketpair fd (fd_child_list[0]) must be done by the wrapper program based on the environment variable _assuan_connection_fd. */ if (fd_child_list) { for (idx = 0; fd_child_list[idx] != -1; idx++) /* We add 1 to skip over the socketpair end. */ fd_child_list[idx] = child_fds[idx + 1]; } _assuan_free (ctx, child_fds); /* If this is the server child process, exit early. */ if (! name && (*argv)[0] == 's') { _assuan_close (ctx, fds[0]); return 0; } _assuan_close (ctx, fds[1]); ctx->engine.release = _assuan_client_release; ctx->finish_handler = _assuan_client_finish; ctx->max_accepts = 1; ctx->inbound.fd = fds[0]; ctx->outbound.fd = fds[0]; _assuan_init_uds_io (ctx); err = initial_handshake (ctx); if (err) _assuan_reset (ctx); return err; }
static gpg_error_t pipe_connect (assuan_context_t ctx, const char *name, const char **argv, assuan_fd_t *fd_child_list, void (*atfork) (void *opaque, int reserved), void *atforkvalue, unsigned int flags) { gpg_error_t rc; assuan_fd_t rp[2]; assuan_fd_t wp[2]; pid_t pid; int res; struct at_pipe_fork atp; unsigned int spawn_flags; atp.user_atfork = atfork; atp.user_atforkvalue = atforkvalue; atp.parent_pid = getpid (); if (!ctx || !name || !argv || !argv[0]) return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE); if (! ctx->flags.no_fixsignals) fix_signals (); if (_assuan_pipe (ctx, rp, 1) < 0) return _assuan_error (ctx, gpg_err_code_from_syserror ()); if (_assuan_pipe (ctx, wp, 0) < 0) { _assuan_close (ctx, rp[0]); _assuan_close_inheritable (ctx, rp[1]); return _assuan_error (ctx, gpg_err_code_from_syserror ()); } spawn_flags = 0; if (flags & ASSUAN_PIPE_CONNECT_DETACHED) spawn_flags |= ASSUAN_SPAWN_DETACHED; /* FIXME: Use atfork handler that closes child fds on Unix. */ res = _assuan_spawn (ctx, &pid, name, argv, wp[0], rp[1], fd_child_list, at_pipe_fork_cb, &atp, spawn_flags); if (res < 0) { rc = gpg_err_code_from_syserror (); _assuan_close (ctx, rp[0]); _assuan_close_inheritable (ctx, rp[1]); _assuan_close_inheritable (ctx, wp[0]); _assuan_close (ctx, wp[1]); return _assuan_error (ctx, rc); } /* Close the stdin/stdout child fds in the parent. */ _assuan_close_inheritable (ctx, rp[1]); _assuan_close_inheritable (ctx, wp[0]); ctx->engine.release = _assuan_client_release; ctx->engine.readfnc = _assuan_simple_read; ctx->engine.writefnc = _assuan_simple_write; ctx->engine.sendfd = NULL; ctx->engine.receivefd = NULL; ctx->finish_handler = _assuan_client_finish; ctx->max_accepts = 1; ctx->accept_handler = NULL; ctx->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */ ctx->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */ ctx->pid = pid; rc = initial_handshake (ctx); if (rc) _assuan_reset (ctx); return rc; }