mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
agent: Send PROGRESS status lines to the client.
* agent/gpg-agent.c (struct progress_dispatch_s): New. (progress_dispatch_list): New. (main): Register libgcrypt pogress handler. (agent_libgcrypt_progress_cb): New. (agent_set_progress_cb): New. (unregister_progress_cb): New. (agent_deinit_default_ctrl): Call unregister. * agent/command.c (progress_cb): New. (start_command_handler): Register progress callback. -- Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
039a55716b
commit
ee87c653bf
@ -336,6 +336,9 @@ typedef int (*lookup_ttl_t)(const char *hexgrip);
|
||||
/*-- gpg-agent.c --*/
|
||||
void agent_exit (int rc)
|
||||
GPGRT_ATTR_NORETURN; /* Also implemented in other tools */
|
||||
void agent_set_progress_cb (void (*cb)(ctrl_t ctrl, const char *what,
|
||||
int printchar, int current, int total),
|
||||
ctrl_t ctrl);
|
||||
gpg_error_t agent_copy_startup_env (ctrl_t ctrl);
|
||||
const char *get_agent_socket_name (void);
|
||||
const char *get_agent_ssh_socket_name (void);
|
||||
|
@ -446,6 +446,23 @@ agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid)
|
||||
}
|
||||
|
||||
|
||||
/* An agent progress callback for Libgcrypt. This has been registered
|
||||
* to be called via the progress dispatcher mechanism from
|
||||
* gpg-agent.c */
|
||||
static void
|
||||
progress_cb (ctrl_t ctrl, const char *what, int printchar,
|
||||
int current, int total)
|
||||
{
|
||||
if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
|
||||
;
|
||||
else if (printchar == '\n' && what && !strcmp (what, "primegen"))
|
||||
agent_print_status (ctrl, "PROGRESS", "%.20s X 100 100", what);
|
||||
else
|
||||
agent_print_status (ctrl, "PROGRESS", "%.20s %c %d %d",
|
||||
what, printchar=='\n'?'X':printchar, current, total);
|
||||
}
|
||||
|
||||
|
||||
/* Helper to print a message while leaving a command. */
|
||||
static gpg_error_t
|
||||
leave_cmd (assuan_context_t ctx, gpg_error_t err)
|
||||
@ -3205,6 +3222,7 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
|
||||
ctrl->digest.raw_value = 0;
|
||||
|
||||
assuan_set_io_monitor (ctx, io_monitor, NULL);
|
||||
agent_set_progress_cb (progress_cb, ctrl);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -372,6 +372,32 @@ static pid_t parent_pid = (pid_t)(-1);
|
||||
/* Number of active connections. */
|
||||
static int active_connections;
|
||||
|
||||
/* This object is used to dispatch progress messages from Libgcrypt to
|
||||
* the right thread. Given that we won't have at max a few dozen
|
||||
* connections at the same time using a linked list is the easiest way
|
||||
* to handle this. */
|
||||
struct progress_dispatch_s
|
||||
{
|
||||
struct progress_dispatch_s *next;
|
||||
/* The control object of the connection. If this is NULL no
|
||||
* connection is associated with this item and it is free for reuse
|
||||
* by new connections. */
|
||||
ctrl_t ctrl;
|
||||
|
||||
/* The thread id of (npth_self) of the connection. */
|
||||
npth_t tid;
|
||||
|
||||
/* The callback set by the connection. This is similar to the
|
||||
* Libgcrypt callback but with the control object passed as the
|
||||
* first argument. */
|
||||
void (*cb)(ctrl_t ctrl,
|
||||
const char *what, int printchar,
|
||||
int current, int total);
|
||||
};
|
||||
struct progress_dispatch_s *progress_dispatch_list;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Local prototypes.
|
||||
@ -383,6 +409,9 @@ static gnupg_fd_t create_server_socket (char *name, int primary, int cygwin,
|
||||
assuan_sock_nonce_t *nonce);
|
||||
static void create_directories (void);
|
||||
|
||||
static void agent_libgcrypt_progress_cb (void *data, const char *what,
|
||||
int printchar,
|
||||
int current, int total);
|
||||
static void agent_init_default_ctrl (ctrl_t ctrl);
|
||||
static void agent_deinit_default_ctrl (ctrl_t ctrl);
|
||||
|
||||
@ -760,6 +789,7 @@ main (int argc, char **argv )
|
||||
|
||||
setup_libgcrypt_logging ();
|
||||
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
|
||||
gcry_set_progress_handler (agent_libgcrypt_progress_cb, NULL);
|
||||
|
||||
disable_core_dumps ();
|
||||
|
||||
@ -1445,6 +1475,88 @@ agent_exit (int rc)
|
||||
}
|
||||
|
||||
|
||||
/* This is our callback function for gcrypt progress messages. It is
|
||||
set once at startup and dispatches progress messages to the
|
||||
corresponding threads of the agent. */
|
||||
static void
|
||||
agent_libgcrypt_progress_cb (void *data, const char *what, int printchar,
|
||||
int current, int total)
|
||||
{
|
||||
struct progress_dispatch_s *dispatch;
|
||||
npth_t mytid = npth_self ();
|
||||
|
||||
(void)data;
|
||||
|
||||
for (dispatch = progress_dispatch_list; dispatch; dispatch = dispatch->next)
|
||||
if (dispatch->ctrl && dispatch->tid == mytid)
|
||||
break;
|
||||
if (dispatch && dispatch->cb)
|
||||
dispatch->cb (dispatch->ctrl, what, printchar, current, total);
|
||||
}
|
||||
|
||||
|
||||
/* If a progress dispatcher callback has been associated with the
|
||||
* current connection unregister it. */
|
||||
static void
|
||||
unregister_progress_cb (void)
|
||||
{
|
||||
struct progress_dispatch_s *dispatch;
|
||||
npth_t mytid = npth_self ();
|
||||
|
||||
for (dispatch = progress_dispatch_list; dispatch; dispatch = dispatch->next)
|
||||
if (dispatch->ctrl && dispatch->tid == mytid)
|
||||
break;
|
||||
if (dispatch)
|
||||
{
|
||||
dispatch->ctrl = NULL;
|
||||
dispatch->cb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Setup a progress callback CB for the current connection. Using a
|
||||
* CB of NULL disables the callback. */
|
||||
void
|
||||
agent_set_progress_cb (void (*cb)(ctrl_t ctrl, const char *what,
|
||||
int printchar, int current, int total),
|
||||
ctrl_t ctrl)
|
||||
{
|
||||
struct progress_dispatch_s *dispatch, *firstfree;
|
||||
npth_t mytid = npth_self ();
|
||||
|
||||
firstfree = NULL;
|
||||
for (dispatch = progress_dispatch_list; dispatch; dispatch = dispatch->next)
|
||||
{
|
||||
if (dispatch->ctrl && dispatch->tid == mytid)
|
||||
break;
|
||||
if (!dispatch->ctrl && !firstfree)
|
||||
firstfree = dispatch;
|
||||
}
|
||||
if (!dispatch) /* None allocated: Reuse or allocate a new one. */
|
||||
{
|
||||
if (firstfree)
|
||||
{
|
||||
dispatch = firstfree;
|
||||
}
|
||||
else if ((dispatch = xtrycalloc (1, sizeof *dispatch)))
|
||||
{
|
||||
dispatch->next = progress_dispatch_list;
|
||||
progress_dispatch_list = dispatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error ("error allocating new progress dispatcher slot: %s\n",
|
||||
gpg_strerror (gpg_error_from_syserror ()));
|
||||
return;
|
||||
}
|
||||
dispatch->ctrl = ctrl;
|
||||
dispatch->tid = mytid;
|
||||
}
|
||||
|
||||
dispatch->cb = cb;
|
||||
}
|
||||
|
||||
|
||||
/* Each thread has its own local variables conveyed by a control
|
||||
structure usually identified by an argument named CTRL. This
|
||||
function is called immediately after allocating the control
|
||||
@ -1481,6 +1593,7 @@ agent_init_default_ctrl (ctrl_t ctrl)
|
||||
static void
|
||||
agent_deinit_default_ctrl (ctrl_t ctrl)
|
||||
{
|
||||
unregister_progress_cb ();
|
||||
session_env_release (ctrl->session_env);
|
||||
|
||||
if (ctrl->lc_ctype)
|
||||
|
Loading…
x
Reference in New Issue
Block a user