Lock scdaemon to CCID if once found.

This solves a problem where ccid was used, the card unplugged and then
scdaemon tries to find a new (plugged in) reader and thus will
eventually try PC/SC over and over again.

Also added an explicit --kill command to gpgconf.
This commit is contained in:
Werner Koch 2011-02-23 10:15:34 +01:00
parent 90dcc0c3ad
commit 7c03c8cc65
7 changed files with 239 additions and 143 deletions

View File

@ -301,10 +301,17 @@ is given, check that file instead.
@item --reload [@var{component}]
@opindex reload
Reload all or the given component. This is basically the sam as sending
Reload all or the given component. This is basically the same as sending
a SIGHUP to the component. Components which don't support reloading are
ignored.
@item --kill [@var{component}]
@opindex kill
Kill the given component. Components which support killing are
gpg-agent and scdaemon. Components which don't support reloading are
ignored. Note that as of now reload and kill have the same effect for
scdaemon.
@end table
@ -1884,4 +1891,3 @@ gpg-zip --list-archive test1
@command{tar}(1),
@end ifset
@include see-also-note.texi

View File

@ -1,3 +1,7 @@
2011-02-23 Werner Koch <wk@g10code.com>
* apdu.c (apdu_open_reader): Lock in to CCID if used once.
2011-01-25 NIIBE Yutaka <gniibe@fsij.org>,
Grant Olson <kgo@grant-olson.net> (wk)

View File

@ -1,5 +1,6 @@
/* apdu.c - ISO 7816 APDU functions and low level I/O
* Copyright (C) 2003, 2004, 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright (C) 2003, 2004, 2008, 2009, 2010,
* 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -2355,12 +2356,25 @@ apdu_open_reader (const char *portstr, int *r_no_service)
#ifdef HAVE_LIBUSB
if (!opt.disable_ccid)
{
static int once_available;
int i;
const char *s;
slot = open_ccid_reader (portstr);
if (slot != -1)
{
once_available = 1;
return slot; /* got one */
}
/* If we ever loaded successfully loaded a CCID reader we never
want to fallback to another driver. This solves a problem
where ccid was used, the card unplugged and then scdaemon
tries to find a new reader and will eventually try PC/SC over
and over again. To reset this flag "gpgconf --kill scdaemon"
can be used. */
if (once_available)
return -1;
/* If a CCID reader specification has been given, the user does
not want a fallback to other drivers. */

View File

@ -1,3 +1,9 @@
2011-02-23 Werner Koch <wk@g10code.com>
* gpgconf.c: Add command --kill.
* gpgconf-comp.c (gc_component_kill): New.
(gpg_agent_runtime_change, scdaemon_runtime_change): Add kill flag.
2011-02-03 Werner Koch <wk@g10code.com>
* watchgnupg.c (print_version): Update copyright year.
@ -1247,7 +1253,7 @@
Copyright 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010 Free Software Foundation, Inc.
2009, 2010, 2011 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without

View File

@ -1,5 +1,6 @@
/* gpgconf-comp.c - Configuration utility for GnuPG.
* Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright (C) 2004, 2007, 2008, 2009, 2010,
* 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -104,8 +105,8 @@ gc_error (int status, int errnum, const char *fmt, ...)
/* Forward declaration. */
static void gpg_agent_runtime_change (void);
static void scdaemon_runtime_change (void);
static void gpg_agent_runtime_change (int killflag);
static void scdaemon_runtime_change (int killflag);
/* Backend configuration. Backends are used to decide how the default
and current value of an option can be determined, and how the
@ -163,8 +164,9 @@ static struct
available. */
char module_name;
/* The runtime change callback. */
void (*runtime_change) (void);
/* The runtime change callback. If KILLFLAG is true the component
is killed and not just reloaded. */
void (*runtime_change) (int killflag);
/* The option name for the configuration filename of this backend.
This must be an absolute filename. It can be an option from a
@ -1047,7 +1049,7 @@ struct error_line_s
/* Engine specific support. */
static void
gpg_agent_runtime_change (void)
gpg_agent_runtime_change (int killflag)
{
gpg_error_t err;
const char *pgmname;
@ -1055,7 +1057,7 @@ gpg_agent_runtime_change (void)
pid_t pid;
pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
argv[0] = "reloadagent";
argv[0] = killflag? "KILLAGENT" : "RELOADAGENT";
argv[1] = NULL;
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
@ -1069,13 +1071,15 @@ gpg_agent_runtime_change (void)
static void
scdaemon_runtime_change (void)
scdaemon_runtime_change (int killflag)
{
gpg_error_t err;
const char *pgmname;
const char *argv[6];
pid_t pid;
(void)killflag; /* For scdaemon kill and reload are synonyms. */
/* We use "GETINFO app_running" to see whether the agent is already
running and kill it only in this case. This avoids an explicit
starting of the agent in case it is not yet running. There is
@ -1099,6 +1103,35 @@ scdaemon_runtime_change (void)
}
/* Unconditionally restart COMPONENT. */
void
gc_component_kill (int component)
{
int runtime[GC_BACKEND_NR];
gc_option_t *option;
gc_backend_t backend;
/* Set a flag for the backends to be reloaded. */
for (backend = 0; backend < GC_BACKEND_NR; backend++)
runtime[backend] = 0;
if (component >= 0)
{
assert (component < GC_COMPONENT_NR);
option = gc_component[component].options;
for (; option && option->name; option++)
runtime[option->backend] = 1;
}
/* Do the restart for the selected backends. */
for (backend = 0; backend < GC_BACKEND_NR; backend++)
{
if (runtime[backend] && gc_backend[backend].runtime_change)
(*gc_backend[backend].runtime_change) (1);
}
}
/* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */
void
gc_component_reload (int component)
@ -1132,7 +1165,7 @@ gc_component_reload (int component)
for (backend = 0; backend < GC_BACKEND_NR; backend++)
{
if (runtime[backend] && gc_backend[backend].runtime_change)
(*gc_backend[backend].runtime_change) ();
(*gc_backend[backend].runtime_change) (0);
}
}
@ -3195,7 +3228,7 @@ gc_component_change_options (int component, estream_t in, estream_t out)
for (backend = 0; backend < GC_BACKEND_NR; backend++)
{
if (runtime[backend] && gc_backend[backend].runtime_change)
(*gc_backend[backend].runtime_change) ();
(*gc_backend[backend].runtime_change) (0);
}
/* Move the per-process backup file into its place. */
@ -3634,7 +3667,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
{
for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
if (runtime[backend_id] && gc_backend[backend_id].runtime_change)
(*gc_backend[backend_id].runtime_change) ();
(*gc_backend[backend_id].runtime_change) (0);
}
}

View File

@ -1,5 +1,5 @@
/* gpgconf.c - Configuration utility for GnuPG
* Copyright (C) 2003, 2007, 2009 Free Software Foundation, Inc.
* Copyright (C) 2003, 2007, 2009, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -49,6 +49,7 @@ enum cmd_and_opt_values
aListConfig,
aCheckConfig,
aListDirs,
aKill,
aReload
};
@ -72,6 +73,7 @@ static ARGPARSE_OPTS opts[] =
{ aCheckConfig, "check-config", 256,
N_("check global configuration file") },
{ aReload, "reload", 256, N_("reload all or a given component")},
{ aKill, "kill", 256, N_("kill a given component")},
{ 301, NULL, 0, N_("@\nOptions:\n ") },
@ -180,6 +182,7 @@ main (int argc, char **argv)
case aListConfig:
case aCheckConfig:
case aReload:
case aKill:
cmd = pargs.r_opt;
break;
@ -240,6 +243,34 @@ main (int argc, char **argv)
}
break;
case aKill:
if (!fname)
{
es_fputs (_("usage: gpgconf [options] "), es_stderr);
es_putc ('\n', es_stderr);
es_fputs (_("Need one component argument"), es_stderr);
es_putc ('\n', es_stderr);
exit (2);
}
else
{
/* Kill a given component. */
int idx;
idx = gc_component_find (fname);
if (idx < 0)
{
es_fputs (_("Component not found"), es_stderr);
es_putc ('\n', es_stderr);
exit (1);
}
else
{
gc_component_kill (idx);
}
}
break;
case aReload:
if (!fname)
{
@ -344,4 +375,3 @@ main (int argc, char **argv)
return 0;
}

View File

@ -44,6 +44,9 @@ char *gc_percent_escape (const char *src);
void gc_error (int status, int errnum, const char *fmt, ...);
/* Kill given component. */
void gc_component_kill (int component);
/* Reload given component. */
void gc_component_reload (int component);