Lock scdaemon to CCID if once found.
authorWerner Koch <wk@gnupg.org>
Wed, 23 Feb 2011 09:15:34 +0000 (10:15 +0100)
committerWerner Koch <wk@gnupg.org>
Wed, 23 Feb 2011 09:15:34 +0000 (10:15 +0100)
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.

doc/tools.texi
scd/ChangeLog
scd/apdu.c
tools/ChangeLog
tools/gpgconf-comp.c
tools/gpgconf.c
tools/gpgconf.h

index c85f9e2..f530c1e 100644 (file)
@@ -61,7 +61,7 @@ watchgnupg --force ~/.gnupg/S.log
 
 @noindent
 This starts it on the current terminal for listening on the socket
-@file{~/.gnupg/S.log}.  
+@file{~/.gnupg/S.log}.
 
 @mansect options
 @noindent
@@ -69,7 +69,7 @@ This starts it on the current terminal for listening on the socket
 
 @table @gnupgtabopt
 
-@item --force 
+@item --force
 @opindex force
 Delete an already existing socket file.
 
@@ -129,9 +129,9 @@ name for remote debugging.
 
 @mansect see also
 @ifset isman
-@command{gpg}(1), 
-@command{gpgsm}(1), 
-@command{gpg-agent}(1), 
+@command{gpg}(1),
+@command{gpgsm}(1),
+@command{gpg-agent}(1),
 @command{scdaemon}(1)
 @end ifset
 @include see-also-note.texi
@@ -150,7 +150,7 @@ name for remote debugging.
 @node addgnupghome
 @section Create .gnupg home directories.
 @ifset manverb
-.B addgnupghome 
+.B addgnupghome
 \- Create .gnupg home directories
 @end ifset
 
@@ -197,7 +197,7 @@ addgnupghome account1 account2 ... accountn
 .br
 .B gpgconf
 .RI [ options ]
-.B \-\-list-options 
+.B \-\-list-options
 .I component
 .br
 .B gpgconf
@@ -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
 
 
@@ -570,7 +577,7 @@ configuration file.  It is @emph{percent-escaped}.
 
 @item line
 If an error occurred in the configuration file, this field has the line
-number of the failing statement in the configuration file.  
+number of the failing statement in the configuration file.
 It is an @emph{unsigned number}.
 
 @item error
@@ -867,7 +874,7 @@ effect.
 @subsection Listing global options
 
 Sometimes it is useful for applications to look at the global options
-file @file{gpgconf.conf}. 
+file @file{gpgconf.conf}.
 The colon separated listing format is record oriented and uses the first
 field to identify the record type:
 
@@ -936,9 +943,9 @@ no feature to change the global option file through @command{gpgconf}.
 
 @mansect see also
 @ifset isman
-@command{gpg}(1), 
-@command{gpgsm}(1), 
-@command{gpg-agent}(1), 
+@command{gpg}(1),
+@command{gpgsm}(1),
+@command{gpg-agent}(1),
 @command{scdaemon}(1),
 @command{dirmngr}(1)
 @end ifset
@@ -989,7 +996,7 @@ applygnupgdefaults
 @ifset manverb
 .B gpgsm-gencert.sh
 \- Generate an X.509 certificate request
-@end ifset 
+@end ifset
 
 @mansect synopsis
 @ifset manverb
@@ -1008,8 +1015,8 @@ which will be printed to stdout.
 
 @mansect see also
 @ifset isman
-@command{gpgsm}(1), 
-@command{gpg-agent}(1), 
+@command{gpgsm}(1),
+@command{gpg-agent}(1),
 @command{scdaemon}(1)
 @end ifset
 @include see-also-note.texi
@@ -1096,7 +1103,7 @@ The following additional options may be used:
 @item -v
 @itemx --verbose
 @opindex verbose
-Output additional information while running.  
+Output additional information while running.
 
 @item -P @var{string}
 @itemx --passphrase @var{string}
@@ -1108,9 +1115,9 @@ for other users.
 
 @mansect see also
 @ifset isman
-@command{gpg}(1), 
-@command{gpgsm}(1), 
-@command{gpg-agent}(1), 
+@command{gpg}(1),
+@command{gpgsm}(1),
+@command{gpg-agent}(1),
 @command{scdaemon}(1)
 @end ifset
 @include see-also-note.texi
@@ -1169,7 +1176,7 @@ The following options may be used:
 @item -v
 @itemx --verbose
 @opindex verbose
-Output additional information while running.  
+Output additional information while running.
 
 @item -q
 @item --quiet
@@ -1186,7 +1193,7 @@ Specify the agent program to be started if none is running.
 
 @item -S
 @itemx --raw-socket @var{name}
-@opindex S        
+@opindex S
 @opindex raw-socket
 Connect to socket @var{name} assuming this is an Assuan style server.
 Do not run any special initializations or environment checks.  This may
@@ -1209,7 +1216,7 @@ connects to the assuan server in extended mode to allow descriptor
 passing.  This option makes it use the old mode.
 
 @item --run @var{file}
-@opindex run 
+@opindex run
 Run the commands from @var{file} at startup and then continue with the
 regular input method.  Note, that commands given on the command line are
 executed after this file.
@@ -1251,7 +1258,7 @@ Variables are referenced by prefixing the name with a dollar sign and
 optionally include the name in curly braces.  The rules for a valid name
 are identically to those of the standard bourne shell.  This is not yet
 enforced but may be in the future.  When used with curly braces no
-leading or trailing white space is allowed. 
+leading or trailing white space is allowed.
 
 If a variable is not found, it is searched in the environment and if
 found copied to the table of variables.
@@ -1264,7 +1271,7 @@ following functions are available:
 @item get
 Return a value described by the argument.  Available arguments are:
 
-@table @code    
+@table @code
 @item cwd
 The current working directory.
 @item homedir
@@ -1431,7 +1438,7 @@ Print a list of available control commands.
 
 @ifset isman
 @mansect see also
-@command{gpg-agent}(1), 
+@command{gpg-agent}(1),
 @command{scdaemon}(1)
 @include see-also-note.texi
 @end ifset
@@ -1452,8 +1459,8 @@ Print a list of available control commands.
 @mansect synopsis
 @ifset manverb
 .B  dirmngr-client
-.RI [ options ]  
-.RI [ certfile | pattern ]  
+.RI [ options ]
+.RI [ certfile | pattern ]
 @end ifset
 
 @mansect description
@@ -1478,7 +1485,7 @@ dirmngr-client <@var{acert}
 @end example
 
 Where @var{acert} is one DER encoded (binary) X.509 certificates to be
-tested. 
+tested.
 @ifclear isman
 The return value of this command is
 @end ifclear
@@ -1489,7 +1496,7 @@ The return value of this command is
 @end ifset
 @table @code
 
-@item 0 
+@item 0
 The certificate under question is valid; i.e. there is a valid CRL
 available and it is not listed tehre or teh OCSP request returned that
 that certificate is valid.
@@ -1673,7 +1680,7 @@ configured with @samp{--enable-symcryptrun} at build time.
 @command{symcryptrun} is invoked this way:
 
 @example
-symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE 
+symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE
    [--decrypt | --encrypt] [inputfile]
 @end example
 @mancont
@@ -1685,12 +1692,12 @@ For decryption vice versa.
 @var{CLASS} describes the calling conventions of the external tool.
 Currently it must be given as @samp{confucius}.  @var{PROGRAM} is
 the full filename of that external tool.
+
 For the class @samp{confucius} the option @option{--keyfile} is
 required; @var{keyfile} is the name of a file containing the secret key,
 which may be protected by a passphrase.  For detailed calling
 conventions, see the source code.
+
 @noindent
 Note, that @command{gpg-agent} must be running before starting
 @command{symcryptrun}.
@@ -1702,7 +1709,7 @@ The following additional options may be used:
 @item -v
 @itemx --verbose
 @opindex verbose
-Output additional information while running.  
+Output additional information while running.
 
 @item -q
 @item --quiet
@@ -1724,22 +1731,22 @@ information to STDERR.
 The possible exit status codes of @command{symcryptrun} are:
 
 @table @code
-@item 0 
+@item 0
         Success.
-@item 1 
+@item 1
         Some error occured.
-@item 2 
+@item 2
         No valid passphrase was provided.
-@item 3 
+@item 3
         The operation was canceled by the user.
 
 @end table
 
 @mansect see also
 @ifset isman
-@command{gpg}(1), 
-@command{gpgsm}(1), 
-@command{gpg-agent}(1), 
+@command{gpg}(1),
+@command{gpgsm}(1),
+@command{gpg-agent}(1),
 @end ifset
 @include see-also-note.texi
 
@@ -1747,8 +1754,8 @@ The possible exit status codes of @command{symcryptrun} are:
 @c
 @c  GPG-ZIP
 @c
-@c The original manpage on which this section is based was written 
-@c by Colin Tuckley  <colin@tuckley.org> and Daniel Leidert 
+@c The original manpage on which this section is based was written
+@c by Colin Tuckley  <colin@tuckley.org> and Daniel Leidert
 @c <daniel.leidert@wgdd.de> for the Debian distribution (but may be used by
 @c others).
 @manpage gpg-zip.1
@@ -1880,8 +1887,7 @@ gpg-zip --list-archive test1
 
 @mansect see also
 @ifset isman
-@command{gpg}(1), 
-@command{tar}(1), 
+@command{gpg}(1),
+@command{tar}(1),
 @end ifset
 @include see-also-note.texi
-
index 0006f74..0a614c8 100644 (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)
 
index 8080b42..176ab91 100644 (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)
-        return slot; /* got one */
+        {
+          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. */
index 79eea39..ae591db 100644 (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.
 
 
  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
index 74feadb..bcdecfd 100644 (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, ...)
 
 \f
 /* 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
@@ -182,13 +184,13 @@ static struct
       NULL, "gpgconf-gpg.conf" },
     { "GPGSM", "gpgsm", GNUPG_MODULE_NAME_GPGSM,
       NULL, "gpgconf-gpgsm.conf" },
-    { "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT, 
+    { "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT,
       gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" },
     { "SCDaemon", "scdaemon", GNUPG_MODULE_NAME_SCDAEMON,
       scdaemon_runtime_change, "gpgconf-scdaemon.conf" },
     { "DirMngr", "dirmngr", GNUPG_MODULE_NAME_DIRMNGR,
       NULL, "gpgconf-dirmngr.conf" },
-    { "DirMngr LDAP Server List", NULL, 0, 
+    { "DirMngr LDAP Server List", NULL, 0,
       NULL, "ldapserverlist-file", "LDAP Server" },
     { "Pinentry", "pinentry", GNUPG_MODULE_NAME_PINENTRY,
       NULL, "gpgconf-pinentry.conf" },
@@ -405,17 +407,17 @@ struct gc_option
   /* A gettext domain in which the following description can be found.
      If this is NULL, then DESC is not translated.  Valid for groups
      and options.
-     
+
      Note that we try to keep the description of groups within the
-     gnupg domain. 
-     
+     gnupg domain.
+
      IMPORTANT: If you add a new domain please make sure to add a code
      set switching call to the function my_dgettext further below.  */
   const char *desc_domain;
 
   /* A gettext description for this group or option.  If it starts
      with a '|', then the string up to the next '|' describes the
-     argument, and the description follows the second '|'. 
+     argument, and the description follows the second '|'.
 
      In general enclosing these description in N_() is not required
      because the description should be identical to the one in the
@@ -516,7 +518,7 @@ static gc_option_t gc_options_gpg_agent[] =
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the security") },
    { "default-cache-ttl", GC_OPT_FLAG_RUNTIME,
-     GC_LEVEL_BASIC, "gnupg", 
+     GC_LEVEL_BASIC, "gnupg",
      "|N|expire cached PINs after N seconds",
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "default-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
@@ -528,7 +530,7 @@ static gc_option_t gc_options_gpg_agent[] =
      N_("|N|set maximum PIN cache lifetime to N seconds"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "max-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
-     GC_LEVEL_EXPERT, "gnupg", 
+     GC_LEVEL_EXPERT, "gnupg",
      N_("|N|set maximum SSH key lifetime to N seconds"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME,
@@ -544,16 +546,16 @@ static gc_option_t gc_options_gpg_agent[] =
    { "Passphrase policy",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Options enforcing a passphrase policy") },
-   { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME, 
-     GC_LEVEL_EXPERT, "gnupg", 
+   { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME,
+     GC_LEVEL_EXPERT, "gnupg",
      N_("do not allow to bypass the passphrase policy"),
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
    { "min-passphrase-len", GC_OPT_FLAG_RUNTIME,
-     GC_LEVEL_ADVANCED, "gnupg", 
+     GC_LEVEL_ADVANCED, "gnupg",
      N_("|N|set minimal required length for new passphrases to N"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME,
-     GC_LEVEL_EXPERT, "gnupg", 
+     GC_LEVEL_EXPERT, "gnupg",
      N_("|N|require at least N non-alpha characters for a new passphrase"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME,
@@ -561,11 +563,11 @@ static gc_option_t gc_options_gpg_agent[] =
      "gnupg", N_("|FILE|check new passphrases against pattern in FILE"),
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
    { "max-passphrase-days", GC_OPT_FLAG_RUNTIME,
-     GC_LEVEL_EXPERT, "gnupg", 
+     GC_LEVEL_EXPERT, "gnupg",
      N_("|N|expire the passphrase after N days"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
-   { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME, 
-     GC_LEVEL_EXPERT, "gnupg", 
+   { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME,
+     GC_LEVEL_EXPERT, "gnupg",
      N_("do not allow the reuse of old passphrases"),
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
 
@@ -686,7 +688,7 @@ static gc_option_t gc_options_gpg[] =
      (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
-   
+
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
@@ -849,7 +851,7 @@ static gc_option_t gc_options_dirmngr[] =
    { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "csh-style command output",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
-   
+
    { "Configuration",
      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
      "gnupg", N_("Options controlling the configuration") },
@@ -1047,17 +1049,17 @@ struct error_line_s
 \f
 /* Engine specific support.  */
 static void
-gpg_agent_runtime_change (void)
+gpg_agent_runtime_change (int killflag)
 {
   gpg_error_t err;
   const char *pgmname;
   const char *argv[2];
   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);
   if (!err)
     err = gnupg_wait_process (pgmname, pid, 1, NULL);
@@ -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
@@ -1088,7 +1092,7 @@ scdaemon_runtime_change (void)
   argv[3] = "scd killscd";
   argv[4] = "/end";
   argv[5] = NULL;
-  
+
   err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
   if (!err)
     err = gnupg_wait_process (pgmname, pid, 1, NULL);
@@ -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)
@@ -1110,7 +1143,7 @@ gc_component_reload (int component)
   /* Set a flag for the backends to be reloaded.  */
   for (backend = 0; backend < GC_BACKEND_NR; backend++)
     runtime[backend] = 0;
-  
+
   if (component == -1)
     {
       for (component = 0; component < GC_COMPONENT_NR; component++)
@@ -1129,10 +1162,10 @@ gc_component_reload (int component)
     }
 
   /* Do the reload for all selected backends.  */
-  for (backend = 0; backend < GC_BACKEND_NR; backend++)  
+  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);
     }
 }
 
@@ -1152,7 +1185,7 @@ my_dgettext (const char *domain, const char *msgid)
     {
       static int switched_codeset;
       char *text;
-      
+
       if (!switched_codeset)
         {
           switched_codeset = 1;
@@ -1172,7 +1205,7 @@ my_dgettext (const char *domain, const char *msgid)
     {
       static int switched_codeset;
       char *text;
-      
+
       if (!switched_codeset)
         {
           switched_codeset = 1;
@@ -1180,7 +1213,7 @@ my_dgettext (const char *domain, const char *msgid)
 
           bindtextdomain ("dirmngr", LOCALEDIR);
           bind_textdomain_codeset ("dirmngr", "utf-8");
-   
+
         }
 
       /* Note: This is a hack to actually use the gnupg2 domain as
@@ -1225,7 +1258,7 @@ gc_percent_escape (const char *src)
          *(dst++) = '%';
          *(dst++) = '2';
          *(dst++) = '5';
-       }         
+       }
       else if (*src == ':')
        {
          /* The colon is used as field separator.  */
@@ -1281,7 +1314,7 @@ percent_deescape (const char *src)
 
          *(dst++) = (char) val;
          src += 3;
-       }         
+       }
       else
        *(dst++) = *(src++);
     }
@@ -1374,7 +1407,7 @@ collect_error_output (estream_t fp, const char *tag)
           buffer[pos - (c == '\n')] = 0;
           if (cont_line)
             ; /*Ignore continuations of previous line. */
-          else if (!strncmp (buffer, tag, taglen) && buffer[taglen] == ':') 
+          else if (!strncmp (buffer, tag, taglen) && buffer[taglen] == ':')
             {
               /* "gpgsm: foo:4: bla" */
               /* Yep, we are interested in this line.  */
@@ -1424,7 +1457,7 @@ collect_error_output (estream_t fp, const char *tag)
           cont_line = (c != '\n');
         }
     }
-  
+
   /* We ignore error lines not terminated by a LF.  */
   return errlines;
 }
@@ -1483,16 +1516,16 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
   else
     argv[i++] = "--gpgconf-test";
   argv[i++] = NULL;
-  
+
   result = 0;
   errlines = NULL;
   err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT, NULL, 0,
                              NULL, NULL, &errfp, &pid);
   if (err)
     result |= 1; /* Program could not be run.  */
-  else 
+  else
     {
-      errlines = collect_error_output (errfp, 
+      errlines = collect_error_output (errfp,
                                       gc_component[component].name);
       if (gnupg_wait_process (pgmname, pid, 1, &exitcode))
        {
@@ -1504,12 +1537,12 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
       gnupg_release_process (pid);
       es_fclose (errfp);
     }
-  
+
   /* If the program could not be run, we can't tell whether
      the config file is good.  */
   if (result & 1)
-    result |= 2;  
-  
+    result |= 2;
+
   if (out)
     {
       const char *desc;
@@ -1617,7 +1650,7 @@ list_one_option (const gc_option_t *option, estream_t out)
   if (opt.verbose)
     {
       es_putc (' ', out);
-         
+
       if (!option->flags)
        es_fprintf (out, "none");
       else
@@ -1649,7 +1682,7 @@ list_one_option (const gc_option_t *option, estream_t out)
 
   /* The description field.  */
   es_fprintf (out, ":%s", desc ? gc_percent_escape (desc) : "");
-  
+
   /* The type field.  */
   es_fprintf (out, ":%u", option->arg_type);
   if (opt.verbose)
@@ -1690,7 +1723,7 @@ list_one_option (const gc_option_t *option, estream_t out)
 /* List all options of the component COMPONENT.  */
 void
 gc_component_list_options (int component, estream_t out)
-{  
+{
   const gc_option_t *option = gc_component[component].options;
 
   while (option && option->name)
@@ -1713,7 +1746,7 @@ gc_component_list_options (int component, estream_t out)
             different active options, and because it is hard to
             maintain manually, we calculate it here.  The value in
             the global static table is ignored.  */
-         
+
          while (group_option->name)
            {
              if (group_option->flags & GC_OPT_FLAG_GROUP)
@@ -1788,7 +1821,7 @@ get_config_filename (gc_component_t component, gc_backend_t backend)
 #if HAVE_W32CE_SYSTEM
   if (!(filename[0] == '/' || filename[0] == '\\'))
 #elif defined(HAVE_DOSISH_SYSTEM)
-  if (!(filename[0] 
+  if (!(filename[0]
         && filename[1] == ':'
         && (filename[2] == '/' || filename[2] == '\\')))
 #else
@@ -1819,8 +1852,8 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
   estream_t config;
   char *config_filename;
 
-  pgmname = (gc_backend[backend].module_name 
-             ? gnupg_module_name (gc_backend[backend].module_name) 
+  pgmname = (gc_backend[backend].module_name
+             ? gnupg_module_name (gc_backend[backend].module_name)
              : gc_backend[backend].program );
   argv[0] = "--gpgconf-list";
   argv[1] = NULL;
@@ -1839,7 +1872,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
       char *linep;
       unsigned long flags = 0;
       char *default_value = NULL;
-      
+
       /* Strip newline and carriage return, if present.  */
       while (length > 0
             && (line[length - 1] == '\n' || line[length - 1] == '\r'))
@@ -1848,7 +1881,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
       linep = strchr (line, ':');
       if (linep)
        *(linep++) = '\0';
-      
+
       /* Extract additional flags.  Default to none.  */
       if (linep)
        {
@@ -1928,7 +1961,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
          char *name;
          char *value;
          gc_option_t *option;
-         
+
          name = line;
          while (*name == ' ' || *name == '\t')
            name++;
@@ -2015,7 +2048,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
 
 
 /* Retrieve the options for the component COMPONENT from backend
-   BACKEND, which we already know is of type file list.  */ 
+   BACKEND, which we already know is of type file list.  */
 static void
 retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
 {
@@ -2115,7 +2148,7 @@ gc_component_retrieve_options (int component)
       component = 0;
       assert (component < GC_COMPONENT_NR);
     }
-      
+
   do
     {
       option = gc_component[component].options;
@@ -2125,16 +2158,16 @@ gc_component_retrieve_options (int component)
           if (!(option->flags & GC_OPT_FLAG_GROUP))
             {
               backend = option->backend;
-              
+
               if (backend_seen[backend])
                 {
                   option++;
                   continue;
                 }
               backend_seen[backend] = 1;
-              
+
               assert (backend != GC_BACKEND_ANY);
-              
+
               if (gc_backend[backend].program)
                 retrieve_options_from_program (component, backend);
               else
@@ -2161,7 +2194,7 @@ option_check_validity (gc_option_t *option, unsigned long flags,
   if (!option->active)
     gc_error (1, 0, "option %s not supported by backend %s",
               option->name, gc_backend[option->backend].name);
-      
+
   if (option->new_flags || option->new_value)
     gc_error (1, 0, "option %s already changed", option->name);
 
@@ -2816,10 +2849,10 @@ change_options_program (gc_component_t component, gc_backend_t backend,
                       == GC_ARG_TYPE_STRING)
                {
                  char *end;
-                 
+
                  assert (*arg == '"');
                  arg++;
-                 
+
                  end = strchr (arg, ',');
                  if (end)
                    *end = '\0';
@@ -3000,16 +3033,16 @@ gc_component_change_options (int component, estream_t in, estream_t out)
           char *linep;
           unsigned long flags = 0;
           char *new_value = "";
-          
+
           /* Strip newline and carriage return, if present.  */
           while (length > 0
                  && (line[length - 1] == '\n' || line[length - 1] == '\r'))
             line[--length] = '\0';
-          
+
           linep = strchr (line, ':');
           if (linep)
             *(linep++) = '\0';
-          
+
           /* Extract additional flags.  Default to none.  */
           if (linep)
             {
@@ -3019,20 +3052,20 @@ gc_component_change_options (int component, estream_t in, estream_t out)
               end = strchr (linep, ':');
               if (end)
                 *(end++) = '\0';
-              
+
               gpg_err_set_errno (0);
               flags = strtoul (linep, &tail, 0);
               if (errno)
                 gc_error (1, errno, "malformed flags in option %s", line);
               if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
                 gc_error (1, 0, "garbage after flags in option %s", line);
-              
+
               linep = end;
             }
 
           /* Don't allow setting of the no change flag.  */
           flags &= ~GC_OPT_FLAG_NO_CHANGE;
-          
+
           /* Extract default value, if present.  Default to empty if not.  */
           if (linep)
             {
@@ -3043,18 +3076,18 @@ gc_component_change_options (int component, estream_t in, estream_t out)
               new_value = linep;
               linep = end;
             }
-          
+
           option = find_option (component, line, GC_BACKEND_ANY);
           if (!option)
             gc_error (1, 0, "unknown option %s", line);
-          
+
           if ((option->flags & GC_OPT_FLAG_NO_CHANGE))
             {
               gc_error (0, 0, "ignoring new value for option %s",
                         option->name);
               continue;
             }
-          
+
           change_one_value (option, runtime, flags, new_value);
         }
     }
@@ -3100,10 +3133,10 @@ gc_component_change_options (int component, estream_t in, estream_t out)
                                   &src_filename[option->backend],
                                   &dest_filename[option->backend],
                                   &orig_filename[option->backend]);
-       
+
       if (err)
        break;
-         
+
       option++;
     }
 
@@ -3192,14 +3225,14 @@ gc_component_change_options (int component, estream_t in, estream_t out)
 
   /* If it all worked, notify the daemons of the changes.  */
   if (opt.runtime)
-    for (backend = 0; backend < GC_BACKEND_NR; backend++)  
+    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.  */
-  for (backend = 0; backend < GC_BACKEND_NR; backend++)  
+  for (backend = 0; backend < GC_BACKEND_NR; backend++)
     if (orig_filename[backend])
       {
        char *backup_filename;
@@ -3236,7 +3269,7 @@ key_matches_user_or_group (char *user)
     *group++ = 0;
 
 #ifdef HAVE_W32_SYSTEM
-  /* Under Windows we don't support groups. */   
+  /* Under Windows we don't support groups. */
   if (group && *group)
     gc_error (0, 0, _("Note that group specifications are ignored\n"));
 #ifndef HAVE_W32CE_SYSTEM
@@ -3384,7 +3417,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
       gc_option_t *option_info = NULL;
       char *p;
       int is_continuation;
-      
+
       lineno++;
       key = line;
       while (*key == ' ' || *key == '\t')
@@ -3549,26 +3582,26 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
                   *group++ = 0;
                   if ((p = strchr (group, ':')))
                     *p = 0; /* We better strip any extra stuff. */
-                }                    
-              
+                }
+
               es_fprintf (listfp, "k:%s:", gc_percent_escape (key));
               es_fprintf (listfp, "%s\n", group? gc_percent_escape (group):"");
             }
 
           /* All other lines are rule records.  */
           es_fprintf (listfp, "r:::%s:%s:%s:",
-                      gc_component[component_id].name,                     
+                      gc_component[component_id].name,
                       option_info->name? option_info->name : "",
                       flags? flags : "");
           if (value != empty)
             es_fprintf (listfp, "\"%s", gc_percent_escape (value));
-          
+
           es_putc ('\n', listfp);
         }
 
       /* Check whether the key matches but do this only if we are not
          running in syntax check mode. */
-      if ( update 
+      if ( update
            && !result && !listfp
            && (got_match || (key && key_matches_user_or_group (key))) )
         {
@@ -3632,9 +3665,9 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
 
       if (opt.runtime)
         {
-          for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)  
+          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);
         }
     }
 
index d6c3337..da10e4d 100644 (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
   };
 
@@ -57,7 +58,7 @@ enum cmd_and_opt_values
 static ARGPARSE_OPTS opts[] =
   {
     { 300, NULL, 0, N_("@Commands:\n ") },
-    
+
     { aListComponents, "list-components", 256, N_("list all components") },
     { aCheckPrograms, "check-programs", 256, N_("check all programs") },
     { aListOptions, "list-options", 256, N_("|COMPONENT|list options") },
@@ -72,9 +73,10 @@ 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 ") },
-    
+
     { oOutput, "output",    2, N_("use as output file") },
     { oVerbose, "verbose",  0, N_("verbose") },
     { oQuiet, "quiet",      0, N_("quiet") },
@@ -180,6 +182,7 @@ main (int argc, char **argv)
         case aListConfig:
         case aCheckConfig:
         case aReload:
+        case aKill:
          cmd = pargs.r_opt;
          break;
 
@@ -189,9 +192,9 @@ main (int argc, char **argv)
 
   if (log_get_errorcount (0))
     exit (2);
-  
+
   fname = argc ? *argv : NULL;
-  
+
   switch (cmd)
     {
     case aListComponents:
@@ -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)
        {
@@ -288,7 +319,7 @@ main (int argc, char **argv)
       if (gc_process_gpgconf_conf (NULL, 1, 1, NULL))
         exit (1);
       break;
-      
+
     case aListDirs:
       /* Show the system configuration directories for gpgconf.  */
       get_outfp (&outfp);
@@ -342,6 +373,5 @@ main (int argc, char **argv)
     if (es_fclose (outfp))
       gc_error (1, errno, "error closing `%s'", opt.outfile);
 
-  return 0; 
+  return 0;
 }
-
index 3b8d80b..9caa0d4 100644 (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);