static gpgme_error_t start (engine_gpgsm_t gpgsm, const char *command) { gpgme_error_t err; assuan_fd_t afdlist[5]; int fdlist[5]; int nfds; int i; /* We need to know the fd used by assuan for reads. We do this by using the assumption that the first returned fd from assuan_get_active_fds() is always this one. */ nfds = assuan_get_active_fds (gpgsm->assuan_ctx, 0 /* read fds */, afdlist, DIM (afdlist)); if (nfds < 1) return gpg_error (GPG_ERR_GENERAL); /* FIXME */ /* For now... */ for (i = 0; i < nfds; i++) fdlist[i] = (int) afdlist[i]; /* We "duplicate" the file descriptor, so we can close it here (we can't close fdlist[0], as that is closed by libassuan, and closing it here might cause libassuan to close some unrelated FD later). Alternatively, we could special case status_fd and register/unregister it manually as needed, but this increases code duplication and is more complicated as we can not use the close notifications etc. A third alternative would be to let Assuan know that we closed the FD, but that complicates the Assuan interface. */ gpgsm->status_cb.fd = _gpgme_io_dup (fdlist[0]); if (gpgsm->status_cb.fd < 0) return gpg_error_from_syserror (); if (_gpgme_io_set_close_notify (gpgsm->status_cb.fd, close_notify_handler, gpgsm)) { _gpgme_io_close (gpgsm->status_cb.fd); gpgsm->status_cb.fd = -1; return gpg_error (GPG_ERR_GENERAL); } err = add_io_cb (gpgsm, &gpgsm->status_cb, status_handler); if (!err && gpgsm->input_cb.fd != -1) err = add_io_cb (gpgsm, &gpgsm->input_cb, _gpgme_data_outbound_handler); if (!err && gpgsm->output_cb.fd != -1) err = add_io_cb (gpgsm, &gpgsm->output_cb, _gpgme_data_inbound_handler); if (!err && gpgsm->message_cb.fd != -1) err = add_io_cb (gpgsm, &gpgsm->message_cb, _gpgme_data_outbound_handler); if (!err) err = assuan_write_line (gpgsm->assuan_ctx, command); if (!err) gpgsm_io_event (gpgsm, GPGME_EVENT_START, NULL); return err; }
static gpgme_error_t start(engine_gpgsm_t gpgsm, const char *command) { gpgme_error_t err; int fdlist[5]; int nfds; /* We need to know the fd used by assuan for reads. We do this by using the assumption that the first returned fd from assuan_get_active_fds() is always this one. */ nfds = assuan_get_active_fds(gpgsm->assuan_ctx, 0 /* read fds */, fdlist, DIM(fdlist)); if(nfds < 1) return gpg_error(GPG_ERR_GENERAL); /* FIXME */ /* We duplicate the file descriptor, so we can close it without disturbing assuan. Alternatively, we could special case status_fd and register/unregister it manually as needed, but this increases code duplication and is more complicated as we can not use the close notifications etc. */ gpgsm->status_cb.fd = dup(fdlist[0]); if(gpgsm->status_cb.fd < 0) return gpg_error_from_syserror(); if(_gpgme_io_set_close_notify(gpgsm->status_cb.fd, close_notify_handler, gpgsm)) { close(gpgsm->status_cb.fd); gpgsm->status_cb.fd = -1; return gpg_error(GPG_ERR_GENERAL); } err = add_io_cb(gpgsm, &gpgsm->status_cb, status_handler); if(!err && gpgsm->input_cb.fd != -1) err = add_io_cb(gpgsm, &gpgsm->input_cb, _gpgme_data_outbound_handler); if(!err && gpgsm->output_cb.fd != -1) err = add_io_cb(gpgsm, &gpgsm->output_cb, _gpgme_data_inbound_handler); if(!err && gpgsm->message_cb.fd != -1) err = add_io_cb(gpgsm, &gpgsm->message_cb, _gpgme_data_outbound_handler); if(!err) err = map_assuan_error(assuan_write_line(gpgsm->assuan_ctx, command)); if(!err) (*gpgsm->io_cbs.event)(gpgsm->io_cbs.event_priv, GPGME_EVENT_START, NULL); return err; }
static gpgme_error_t engspawn_start (engine_spawn_t esp, const char *file, const char *argv[], unsigned int flags) { gpgme_error_t err; int i, n; int status; struct spawn_fd_item_s *fd_list; pid_t pid; unsigned int spflags; const char *save_argv0 = NULL; if (!esp || !file || !argv || !argv[0]) return gpg_error (GPG_ERR_INV_VALUE); spflags = 0; if ((flags & GPGME_SPAWN_DETACHED)) spflags |= IOSPAWN_FLAG_DETACHED; if ((flags & GPGME_SPAWN_ALLOW_SET_FG)) spflags |= IOSPAWN_FLAG_ALLOW_SET_FG; err = build_fd_data_map (esp); if (err) return err; n = 0; for (i = 0; esp->fd_data_map[i].data; i++) n++; fd_list = calloc (n+1, sizeof *fd_list); if (!fd_list) return gpg_error_from_syserror (); /* Build the fd list for the child. */ n = 0; for (i = 0; esp->fd_data_map[i].data; i++) { fd_list[n].fd = esp->fd_data_map[i].peer_fd; fd_list[n].dup_to = esp->fd_data_map[i].dup_to; n++; } fd_list[n].fd = -1; fd_list[n].dup_to = -1; if (argv[0] && !*argv[0]) { save_argv0 = argv[0]; argv[0] = _gpgme_get_basename (file); } status = _gpgme_io_spawn (file, (char * const *)argv, spflags, fd_list, NULL, NULL, &pid); if (save_argv0) argv[0] = save_argv0; free (fd_list); if (status == -1) return gpg_error_from_syserror (); for (i = 0; esp->fd_data_map[i].data; i++) { err = add_io_cb (esp, esp->fd_data_map[i].fd, esp->fd_data_map[i].inbound, esp->fd_data_map[i].inbound ? _gpgme_data_inbound_handler : _gpgme_data_outbound_handler, esp->fd_data_map[i].data, &esp->fd_data_map[i].tag); if (err) return err; /* FIXME: kill the child */ } engspawn_io_event (esp, GPGME_EVENT_START, NULL); return 0; }