typedef struct
{
int fd; /* FD we talk about. */
+ int server_fd; /* Server FD for this connection. */
int dir; /* Inbound/Outbound, maybe given implicit? */
void *data; /* Handler-specific data. */
void *tag; /* ID from the user for gpgme_remove_io_callback. */
/* Input, output etc are from the servers perspective. */
iocb_data_t input_cb;
- int input_fd_server;
iocb_data_t output_cb;
- int output_fd_server;
iocb_data_t message_cb;
- int message_fd_server;
struct
{
if (gpgsm->status_cb.tag)
(*gpgsm->io_cbs.remove) (gpgsm->status_cb.tag);
gpgsm->status_cb.fd = -1;
+ gpgsm->status_cb.tag = NULL;
}
else if (gpgsm->input_cb.fd == fd)
{
if (gpgsm->input_cb.tag)
(*gpgsm->io_cbs.remove) (gpgsm->input_cb.tag);
gpgsm->input_cb.fd = -1;
+ gpgsm->input_cb.tag = NULL;
}
else if (gpgsm->output_cb.fd == fd)
{
if (gpgsm->output_cb.tag)
(*gpgsm->io_cbs.remove) (gpgsm->output_cb.tag);
gpgsm->output_cb.fd = -1;
+ gpgsm->output_cb.tag = NULL;
}
else if (gpgsm->message_cb.fd == fd)
{
if (gpgsm->message_cb.tag)
(*gpgsm->io_cbs.remove) (gpgsm->message_cb.tag);
gpgsm->message_cb.fd = -1;
+ gpgsm->message_cb.tag = NULL;
}
}
engine_gpgsm_t gpgsm;
const char *argv[5];
int argc;
+#if !USE_DESCRIPTOR_PASSING
int fds[2];
int child_fds[4];
+#endif
char *dft_display = NULL;
char dft_ttyname[64];
char *dft_ttytype = NULL;
gpgsm->status_cb.tag = 0;
gpgsm->input_cb.fd = -1;
+ gpgsm->input_cb.dir = 0;
gpgsm->input_cb.tag = 0;
- gpgsm->input_fd_server = -1;
+ gpgsm->input_cb.server_fd = -1;
gpgsm->output_cb.fd = -1;
+ gpgsm->output_cb.dir = 1;
gpgsm->output_cb.tag = 0;
- gpgsm->output_fd_server = -1;
+ gpgsm->output_cb.server_fd = -1;
gpgsm->message_cb.fd = -1;
+ gpgsm->message_cb.dir = 0;
gpgsm->message_cb.tag = 0;
- gpgsm->message_fd_server = -1;
+ gpgsm->message_cb.server_fd = -1;
gpgsm->status.fnc = 0;
gpgsm->colon.fnc = 0;
gpgsm->io_cbs.event = NULL;
gpgsm->io_cbs.event_priv = NULL;
+#if !USE_DESCRIPTOR_PASSING
if (_gpgme_io_pipe (fds, 0) < 0)
{
err = gpg_error_from_errno (errno);
goto leave;
}
gpgsm->input_cb.fd = fds[1];
- gpgsm->input_cb.dir = 0;
- gpgsm->input_fd_server = fds[0];
+ gpgsm->input_cb.server_fd = fds[0];
if (_gpgme_io_pipe (fds, 1) < 0)
{
goto leave;
}
gpgsm->output_cb.fd = fds[0];
- gpgsm->output_cb.dir = 1;
- gpgsm->output_fd_server = fds[1];
+ gpgsm->output_cb.server_fd = fds[1];
if (_gpgme_io_pipe (fds, 0) < 0)
{
goto leave;
}
gpgsm->message_cb.fd = fds[1];
- gpgsm->message_cb.dir = 0;
- gpgsm->message_fd_server = fds[0];
+ gpgsm->message_cb.server_fd = fds[0];
- child_fds[0] = gpgsm->input_fd_server;
- child_fds[1] = gpgsm->output_fd_server;
- child_fds[2] = gpgsm->message_fd_server;
+ child_fds[0] = gpgsm->input_cb.server_fd;
+ child_fds[1] = gpgsm->output_cb.server_fd;
+ child_fds[2] = gpgsm->message_cb.server_fd;
child_fds[3] = -1;
+#endif
argc = 0;
argv[argc++] = "gpgsm";
argv[argc++] = "--server";
argv[argc++] = NULL;
- err = assuan_pipe_connect (&gpgsm->assuan_ctx,
- file_name ? file_name : _gpgme_get_gpgsm_path (),
- argv, child_fds);
+#if USE_DESCRIPTOR_PASSING
+ err = assuan_pipe_connect_ext
+ (&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
+ argv, NULL, NULL, NULL, 1);
+#else
+ err = assuan_pipe_connect
+ (&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
+ argv, child_fds);
+#endif
if (err)
goto leave;
if (!err
&& (_gpgme_io_set_close_notify (gpgsm->status_cb.fd,
+ close_notify_handler, gpgsm)))
+ {
+ err = gpg_error (GPG_ERR_GENERAL);
+ goto leave;
+ }
+
+#if !USE_DESCRIPTOR_PASSING
+ if (!err
+ && (_gpgme_io_set_close_notify (gpgsm->input_cb.fd,
close_notify_handler, gpgsm)
- || _gpgme_io_set_close_notify (gpgsm->input_cb.fd,
- close_notify_handler, gpgsm)
|| _gpgme_io_set_close_notify (gpgsm->output_cb.fd,
close_notify_handler, gpgsm)
|| _gpgme_io_set_close_notify (gpgsm->message_cb.fd,
err = gpg_error (GPG_ERR_GENERAL);
goto leave;
}
-
+#endif
+
leave:
/* Close the server ends of the pipes. Our ends are closed in
gpgsm_release(). */
- if (gpgsm->input_fd_server != -1)
- _gpgme_io_close (gpgsm->input_fd_server);
- if (gpgsm->output_fd_server != -1)
- _gpgme_io_close (gpgsm->output_fd_server);
- if (gpgsm->message_fd_server != -1)
- _gpgme_io_close (gpgsm->message_fd_server);
+#if !USE_DESCRIPTOR_PASSING
+ if (gpgsm->input_cb.server_fd != -1)
+ _gpgme_io_close (gpgsm->input_cb.server_fd);
+ if (gpgsm->output_cb.server_fd != -1)
+ _gpgme_io_close (gpgsm->output_cb.server_fd);
+ if (gpgsm->message_cb.server_fd != -1)
+ _gpgme_io_close (gpgsm->message_cb.server_fd);
+#endif
if (err)
gpgsm_release (gpgsm);
}
+typedef enum { INPUT_FD, OUTPUT_FD, MESSAGE_FD } fd_type_t;
+
+static void
+gpgsm_clear_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type)
+{
+#if !USE_DESCRIPTOR_PASSING
+ switch (fd_type)
+ {
+ case INPUT_FD:
+ _gpgme_io_close (gpgsm->input_cb.fd);
+ break;
+ case OUTPUT_FD:
+ _gpgme_io_close (gpgsm->output_cb.fd);
+ break;
+ case MESSAGE_FD:
+ _gpgme_io_close (gpgsm->message_cb.fd);
+ break;
+ }
+#endif
+}
+
#define COMMANDLINELEN 40
static gpgme_error_t
-gpgsm_set_fd (assuan_context_t ctx, const char *which, int fd, const char *opt)
+gpgsm_set_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type, const char *opt)
{
+ gpg_error_t err = 0;
char line[COMMANDLINELEN];
+ char *which;
+ iocb_data_t *iocb_data;
+ int dir;
+ int fd;
+
+ switch (fd_type)
+ {
+ case INPUT_FD:
+ which = "INPUT";
+ iocb_data = &gpgsm->input_cb;
+ break;
+
+ case OUTPUT_FD:
+ which = "OUTPUT";
+ iocb_data = &gpgsm->output_cb;
+ break;
+
+ case MESSAGE_FD:
+ which = "MESSAGE";
+ iocb_data = &gpgsm->message_cb;
+ break;
+
+ default:
+ return gpg_error (GPG_ERR_INV_VALUE);
+ }
+
+ dir = iocb_data->dir;
+
+#if USE_DESCRIPTOR_PASSING
+ {
+ int fds[2];
+
+ if (_gpgme_io_pipe (fds, 0) < 0)
+ return gpg_error_from_errno (errno);
+
+ iocb_data->fd = dir ? fds[0] : fds[1];
+ iocb_data->server_fd = dir ? fds[1] : fds[0];
+
+ if (_gpgme_io_set_close_notify (iocb_data->fd,
+ close_notify_handler, gpgsm))
+ {
+ err = gpg_error (GPG_ERR_GENERAL);
+ goto leave_set_fd;
+ }
+ }
+#endif
+
+ fd = iocb_data->server_fd;
+
+#if USE_DESCRIPTOR_PASSING
+ err = assuan_sendfd (gpgsm->assuan_ctx, fd);
+ if (err)
+ goto leave_set_fd;
+
+ _gpgme_io_close (fd);
+ if (opt)
+ snprintf (line, COMMANDLINELEN, "%s FD %s", which, opt);
+ else
+ snprintf (line, COMMANDLINELEN, "%s FD", which);
+#else
if (opt)
snprintf (line, COMMANDLINELEN, "%s FD=%i %s", which, fd, opt);
else
snprintf (line, COMMANDLINELEN, "%s FD=%i", which, fd);
+#endif
+
+ err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
- return gpgsm_assuan_simple_command (ctx, line, NULL, NULL);
+#if USE_DESCRIPTOR_PASSING
+ leave_set_fd:
+ if (err)
+ {
+ _gpgme_io_close (iocb_data->fd);
+ _gpgme_io_close (iocb_data->server_fd);
+ iocb_data->fd = -1;
+ iocb_data->server_fd = -1;
+ }
+#endif
+
+ return err;
}
return gpg_error (GPG_ERR_INV_VALUE);
gpgsm->input_cb.data = ciph;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
- map_input_enc (gpgsm->input_cb.data));
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
if (err)
return gpg_error (GPG_ERR_GENERAL); /* FIXME */
gpgsm->output_cb.data = plain;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server, 0);
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, 0);
if (err)
return gpg_error (GPG_ERR_GENERAL); /* FIXME */
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (engine, "DECRYPT");
return err;
}
*linep = '\0';
- _gpgme_io_close (gpgsm->output_cb.fd);
- _gpgme_io_close (gpgsm->input_cb.fd);
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (gpgsm, line);
free (line);
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
gpgsm->input_cb.data = plain;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
- map_input_enc (gpgsm->input_cb.data));
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
gpgsm->output_cb.data = ciph;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
- use_armor ? "--armor" : 0);
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
if (err)
return err;
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = set_recipients (gpgsm, recp);
strcpy (&cmd[7], pattern);
gpgsm->output_cb.data = keydata;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
- use_armor ? "--armor" : 0);
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
if (err)
return err;
- _gpgme_io_close (gpgsm->input_cb.fd);
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (gpgsm, cmd);
free (cmd);
*linep = '\0';
gpgsm->output_cb.data = keydata;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
- use_armor ? "--armor" : 0);
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
if (err)
return err;
- _gpgme_io_close (gpgsm->input_cb.fd);
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (gpgsm, line);
free (line);
return gpg_error (GPG_ERR_INV_VALUE);
gpgsm->input_cb.data = help_data;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
- map_input_enc (gpgsm->input_cb.data));
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
gpgsm->output_cb.data = pubkey;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
- use_armor ? "--armor" : 0);
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
if (err)
return err;
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (gpgsm, "GENKEY");
return err;
return gpg_error (GPG_ERR_INV_VALUE);
gpgsm->input_cb.data = keydata;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
- map_input_enc (gpgsm->input_cb.data));
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
- _gpgme_io_close (gpgsm->output_cb.fd);
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (gpgsm, "IMPORT");
return err;
strcpy (&line[9], pattern);
}
- _gpgme_io_close (gpgsm->input_cb.fd);
- _gpgme_io_close (gpgsm->output_cb.fd);
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (gpgsm, line);
free (line);
linep--;
*linep = '\0';
- _gpgme_io_close (gpgsm->input_cb.fd);
- _gpgme_io_close (gpgsm->output_cb.fd);
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (gpgsm, line);
free (line);
}
gpgsm->input_cb.data = in;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
- map_input_enc (gpgsm->input_cb.data));
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
gpgsm->output_cb.data = out;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
- use_armor ? "--armor" : 0);
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
if (err)
return err;
- _gpgme_io_close (gpgsm->message_cb.fd);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
err = start (gpgsm, mode == GPGME_SIG_MODE_DETACH
? "SIGN --detached" : "SIGN");
return gpg_error (GPG_ERR_INV_VALUE);
gpgsm->input_cb.data = sig;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server,
- map_input_enc (gpgsm->input_cb.data));
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
if (err)
return err;
if (plaintext)
{
/* Normal or cleartext signature. */
gpgsm->output_cb.data = plaintext;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
- 0);
- _gpgme_io_close (gpgsm->message_cb.fd);
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, 0);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
}
else
{
/* Detached signature. */
gpgsm->message_cb.data = signed_text;
- err = gpgsm_set_fd (gpgsm->assuan_ctx, "MESSAGE",
- gpgsm->message_fd_server, 0);
- _gpgme_io_close (gpgsm->output_cb.fd);
+ err = gpgsm_set_fd (gpgsm, MESSAGE_FD, 0);
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
}
if (!err)