LCOV - code coverage report
Current view: top level - tools - gpgconf-comp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 10 1295 0.8 %
Date: 2016-12-01 18:37:21 Functions: 1 30 3.3 %

          Line data    Source code
       1             : /* gpgconf-comp.c - Configuration utility for GnuPG.
       2             :  * Copyright (C) 2004, 2007, 2008, 2009, 2010,
       3             :  *               2011 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with GnuPG; if not, see <https://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #if HAVE_CONFIG_H
      22             : #include <config.h>
      23             : #endif
      24             : #include <stdlib.h>
      25             : #include <stdio.h>
      26             : #include <string.h>
      27             : #include <fcntl.h>
      28             : #include <unistd.h>
      29             : #include <sys/types.h>
      30             : #include <assert.h>
      31             : #include <errno.h>
      32             : #include <time.h>
      33             : #include <stdarg.h>
      34             : #ifdef HAVE_SIGNAL_H
      35             : # include <signal.h>
      36             : #endif
      37             : #include <ctype.h>
      38             : #ifdef HAVE_W32_SYSTEM
      39             : # define WIN32_LEAN_AND_MEAN 1
      40             : # include <windows.h>
      41             : #else
      42             : # include <pwd.h>
      43             : # include <grp.h>
      44             : #endif
      45             : 
      46             : /* For log_logv(), asctimestamp(), gnupg_get_time ().  */
      47             : #include "util.h"
      48             : #include "i18n.h"
      49             : #include "exechelp.h"
      50             : 
      51             : #include "gc-opt-flags.h"
      52             : #include "gpgconf.h"
      53             : 
      54             : /* There is a problem with gpg 1.4 under Windows: --gpgconf-list
      55             :    returns a plain filename without escaping.  As long as we have not
      56             :    fixed that we need to use gpg2.  */
      57             : #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
      58             : #define GPGNAME "gpg2"
      59             : #else
      60             : #define GPGNAME GPG_NAME
      61             : #endif
      62             : 
      63             : 
      64             : /* TODO:
      65             :    Components: Add more components and their options.
      66             :    Robustness: Do more validation.  Call programs to do validation for us.
      67             :    Add options to change backend binary path.
      68             :    Extract binary path for some backends from gpgsm/gpg config.
      69             : */
      70             : 
      71             : 
      72             : #if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
      73             : void gc_error (int status, int errnum, const char *fmt, ...) \
      74             :   __attribute__ ((format (printf, 3, 4)));
      75             : #endif
      76             : 
      77             : /* Output a diagnostic message.  If ERRNUM is not 0, then the output
      78             :    is followed by a colon, a white space, and the error string for the
      79             :    error number ERRNUM.  In any case the output is finished by a
      80             :    newline.  The message is prepended by the program name, a colon,
      81             :    and a whitespace.  The output may be further formatted or
      82             :    redirected by the jnlib logging facility.  */
      83             : void
      84          48 : gc_error (int status, int errnum, const char *fmt, ...)
      85             : {
      86             :   va_list arg_ptr;
      87             : 
      88          48 :   va_start (arg_ptr, fmt);
      89          48 :   log_logv (GPGRT_LOG_ERROR, fmt, arg_ptr);
      90          48 :   va_end (arg_ptr);
      91             : 
      92          48 :   if (errnum)
      93          48 :     log_printf (": %s\n", strerror (errnum));
      94             :   else
      95           0 :     log_printf ("\n");
      96             : 
      97          48 :   if (status)
      98             :     {
      99          48 :       log_printf (NULL);
     100          48 :       log_printf ("fatal error (exit status %i)\n", status);
     101          48 :       exit (status);
     102             :     }
     103           0 : }
     104             : 
     105             : 
     106             : /* Forward declaration.  */
     107             : static void gpg_agent_runtime_change (int killflag);
     108             : static void scdaemon_runtime_change (int killflag);
     109             : static void dirmngr_runtime_change (int killflag);
     110             : 
     111             : /* Backend configuration.  Backends are used to decide how the default
     112             :    and current value of an option can be determined, and how the
     113             :    option can be changed.  To every option in every component belongs
     114             :    exactly one backend that controls and determines the option.  Some
     115             :    backends are programs from the GPG system.  Others might be
     116             :    implemented by GPGConf itself.  If you change this enum, don't
     117             :    forget to update GC_BACKEND below.  */
     118             : typedef enum
     119             :   {
     120             :     /* Any backend, used for find_option ().  */
     121             :     GC_BACKEND_ANY,
     122             : 
     123             :     /* The Gnu Privacy Guard.  */
     124             :     GC_BACKEND_GPG,
     125             : 
     126             :     /* The Gnu Privacy Guard for S/MIME.  */
     127             :     GC_BACKEND_GPGSM,
     128             : 
     129             :     /* The GPG Agent.  */
     130             :     GC_BACKEND_GPG_AGENT,
     131             : 
     132             :     /* The GnuPG SCDaemon.  */
     133             :     GC_BACKEND_SCDAEMON,
     134             : 
     135             :     /* The GnuPG directory manager.  */
     136             :     GC_BACKEND_DIRMNGR,
     137             : 
     138             :     /* The LDAP server list file for the director manager.  */
     139             :     GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST,
     140             : 
     141             :     /* The Pinentry (not a part of GnuPG, proper).  */
     142             :     GC_BACKEND_PINENTRY,
     143             : 
     144             :     /* The number of the above entries.  */
     145             :     GC_BACKEND_NR
     146             :   } gc_backend_t;
     147             : 
     148             : 
     149             : /* To be able to implement generic algorithms for the various
     150             :    backends, we collect all information about them in this struct.  */
     151             : static struct
     152             : {
     153             :   /* The name of the backend.  */
     154             :   const char *name;
     155             : 
     156             :   /* The name of the program that acts as the backend.  Some backends
     157             :      don't have an associated program, but are implemented directly by
     158             :      GPGConf.  In this case, PROGRAM is NULL.  */
     159             :   char *program;
     160             : 
     161             :   /* The module name (GNUPG_MODULE_NAME_foo) as defined by
     162             :      ../common/util.h.  This value is used to get the actual installed
     163             :      path of the program.  0 is used if no backend program is
     164             :      available. */
     165             :   char module_name;
     166             : 
     167             :   /* The runtime change callback.  If KILLFLAG is true the component
     168             :      is killed and not just reloaded.  */
     169             :   void (*runtime_change) (int killflag);
     170             : 
     171             :   /* The option name for the configuration filename of this backend.
     172             :      This must be an absolute filename.  It can be an option from a
     173             :      different backend (but then ordering of the options might
     174             :      matter).  Note: This must be unique among all components.  */
     175             :   const char *option_config_filename;
     176             : 
     177             :   /* If this is a file backend rather than a program backend, then
     178             :      this is the name of the option associated with the file.  */
     179             :   const char *option_name;
     180             : } gc_backend[GC_BACKEND_NR] =
     181             :   {
     182             :     { NULL },           /* GC_BACKEND_ANY dummy entry.  */
     183             :     { GPG_DISP_NAME, GPGNAME, GNUPG_MODULE_NAME_GPG,
     184             :       NULL, GPGCONF_NAME "-" GPG_NAME ".conf" },
     185             :     { GPGSM_DISP_NAME, GPGSM_NAME, GNUPG_MODULE_NAME_GPGSM,
     186             :       NULL, GPGCONF_NAME "-" GPGSM_NAME ".conf" },
     187             :     { GPG_AGENT_DISP_NAME, GPG_AGENT_NAME, GNUPG_MODULE_NAME_AGENT,
     188             :       gpg_agent_runtime_change, GPGCONF_NAME"-" GPG_AGENT_NAME ".conf" },
     189             :     { SCDAEMON_DISP_NAME, SCDAEMON_NAME, GNUPG_MODULE_NAME_SCDAEMON,
     190             :       scdaemon_runtime_change, GPGCONF_NAME"-" SCDAEMON_NAME ".conf" },
     191             :     { DIRMNGR_DISP_NAME, DIRMNGR_NAME, GNUPG_MODULE_NAME_DIRMNGR,
     192             :       dirmngr_runtime_change, GPGCONF_NAME "-" DIRMNGR_NAME ".conf" },
     193             :     { DIRMNGR_DISP_NAME " LDAP Server List", NULL, 0,
     194             :       NULL, "ldapserverlist-file", "LDAP Server" },
     195             :     { "Pinentry", "pinentry", GNUPG_MODULE_NAME_PINENTRY,
     196             :       NULL, GPGCONF_NAME "-pinentry.conf" },
     197             :   };
     198             : 
     199             : 
     200             : /* Option configuration.  */
     201             : 
     202             : /* An option might take an argument, or not.  Argument types can be
     203             :    basic or complex.  Basic types are generic and easy to validate.
     204             :    Complex types provide more specific information about the intended
     205             :    use, but can be difficult to validate.  If you add to this enum,
     206             :    don't forget to update GC_ARG_TYPE below.  YOU MUST NOT CHANGE THE
     207             :    NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE EXTERNAL
     208             :    INTERFACE.  */
     209             : typedef enum
     210             :   {
     211             :     /* Basic argument types.  */
     212             : 
     213             :     /* No argument.  */
     214             :     GC_ARG_TYPE_NONE = 0,
     215             : 
     216             :     /* A String argument.  */
     217             :     GC_ARG_TYPE_STRING = 1,
     218             : 
     219             :     /* A signed integer argument.  */
     220             :     GC_ARG_TYPE_INT32 = 2,
     221             : 
     222             :     /* An unsigned integer argument.  */
     223             :     GC_ARG_TYPE_UINT32 = 3,
     224             : 
     225             :     /* ADD NEW BASIC TYPE ENTRIES HERE.  */
     226             : 
     227             :     /* Complex argument types.  */
     228             : 
     229             :     /* A complete filename.  */
     230             :     GC_ARG_TYPE_FILENAME = 32,
     231             : 
     232             :     /* An LDAP server in the format
     233             :        HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN.  */
     234             :     GC_ARG_TYPE_LDAP_SERVER = 33,
     235             : 
     236             :     /* A 40 character fingerprint.  */
     237             :     GC_ARG_TYPE_KEY_FPR = 34,
     238             : 
     239             :     /* A user ID or key ID or fingerprint for a certificate.  */
     240             :     GC_ARG_TYPE_PUB_KEY = 35,
     241             : 
     242             :     /* A user ID or key ID or fingerprint for a certificate with a key.  */
     243             :     GC_ARG_TYPE_SEC_KEY = 36,
     244             : 
     245             :     /* A alias list made up of a key, an equal sign and a space
     246             :        separated list of values.  */
     247             :     GC_ARG_TYPE_ALIAS_LIST = 37,
     248             : 
     249             :     /* ADD NEW COMPLEX TYPE ENTRIES HERE.  */
     250             : 
     251             :     /* The number of the above entries.  */
     252             :     GC_ARG_TYPE_NR
     253             :   } gc_arg_type_t;
     254             : 
     255             : 
     256             : /* For every argument, we record some information about it in the
     257             :    following struct.  */
     258             : static struct
     259             : {
     260             :   /* For every argument type exists a basic argument type that can be
     261             :      used as a fallback for input and validation purposes.  */
     262             :   gc_arg_type_t fallback;
     263             : 
     264             :   /* Human-readable name of the type.  */
     265             :   const char *name;
     266             : } gc_arg_type[GC_ARG_TYPE_NR] =
     267             :   {
     268             :     /* The basic argument types have their own types as fallback.  */
     269             :     { GC_ARG_TYPE_NONE, "none" },
     270             :     { GC_ARG_TYPE_STRING, "string" },
     271             :     { GC_ARG_TYPE_INT32, "int32" },
     272             :     { GC_ARG_TYPE_UINT32, "uint32" },
     273             : 
     274             :     /* Reserved basic type entries for future extension.  */
     275             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     276             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     277             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     278             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     279             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     280             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     281             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     282             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     283             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     284             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     285             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     286             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     287             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     288             :     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     289             : 
     290             :     /* The complex argument types have a basic type as fallback.  */
     291             :     { GC_ARG_TYPE_STRING, "filename" },
     292             :     { GC_ARG_TYPE_STRING, "ldap server" },
     293             :     { GC_ARG_TYPE_STRING, "key fpr" },
     294             :     { GC_ARG_TYPE_STRING, "pub key" },
     295             :     { GC_ARG_TYPE_STRING, "sec key" },
     296             :     { GC_ARG_TYPE_STRING, "alias list" },
     297             :   };
     298             : 
     299             : 
     300             : /* Every option has an associated expert level, than can be used to
     301             :    hide advanced and expert options from beginners.  If you add to
     302             :    this list, don't forget to update GC_LEVEL below.  YOU MUST NOT
     303             :    CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE
     304             :    EXTERNAL INTERFACE.  */
     305             : typedef enum
     306             :   {
     307             :     /* The basic options should always be displayed.  */
     308             :     GC_LEVEL_BASIC,
     309             : 
     310             :     /* The advanced options may be hidden from beginners.  */
     311             :     GC_LEVEL_ADVANCED,
     312             : 
     313             :     /* The expert options should only be displayed to experts.  */
     314             :     GC_LEVEL_EXPERT,
     315             : 
     316             :     /* The invisible options should normally never be displayed.  */
     317             :     GC_LEVEL_INVISIBLE,
     318             : 
     319             :     /* The internal options are never exported, they mark options that
     320             :        are recorded for internal use only.  */
     321             :     GC_LEVEL_INTERNAL,
     322             : 
     323             :     /* ADD NEW ENTRIES HERE.  */
     324             : 
     325             :     /* The number of the above entries.  */
     326             :     GC_LEVEL_NR
     327             :   } gc_expert_level_t;
     328             : 
     329             : /* A description for each expert level.  */
     330             : static struct
     331             : {
     332             :   const char *name;
     333             : } gc_level[] =
     334             :   {
     335             :     { "basic" },
     336             :     { "advanced" },
     337             :     { "expert" },
     338             :     { "invisible" },
     339             :     { "internal" }
     340             :   };
     341             : 
     342             : 
     343             : /* Option flags.  The flags which are used by the backends are defined
     344             :    by gc-opt-flags.h, included above.
     345             : 
     346             :    YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING FLAGS, AS THEY ARE
     347             :    PART OF THE EXTERNAL INTERFACE.  */
     348             : 
     349             : /* Some entries in the option list are not options, but mark the
     350             :    beginning of a new group of options.  These entries have the GROUP
     351             :    flag set.  */
     352             : #define GC_OPT_FLAG_GROUP       (1UL << 0)
     353             : /* The ARG_OPT flag for an option indicates that the argument is
     354             :    optional.  This is never set for GC_ARG_TYPE_NONE options.  */
     355             : #define GC_OPT_FLAG_ARG_OPT     (1UL << 1)
     356             : /* The LIST flag for an option indicates that the option can occur
     357             :    several times.  A comma separated list of arguments is used as the
     358             :    argument value.  */
     359             : #define GC_OPT_FLAG_LIST        (1UL << 2)
     360             : 
     361             : 
     362             : /* A human-readable description for each flag.  */
     363             : static struct
     364             : {
     365             :   const char *name;
     366             : } gc_flag[] =
     367             :   {
     368             :     { "group" },
     369             :     { "optional arg" },
     370             :     { "list" },
     371             :     { "runtime" },
     372             :     { "default" },
     373             :     { "default desc" },
     374             :     { "no arg desc" },
     375             :     { "no change" }
     376             :   };
     377             : 
     378             : 
     379             : /* To each option, or group marker, the information in the GC_OPTION
     380             :    struct is provided.  If you change this, don't forget to update the
     381             :    option list of each component.  */
     382             : struct gc_option
     383             : {
     384             :   /* If this is NULL, then this is a terminator in an array of unknown
     385             :      length.  Otherwise, if this entry is a group marker (see FLAGS),
     386             :      then this is the name of the group described by this entry.
     387             :      Otherwise it is the name of the option described by this
     388             :      entry.  The name must not contain a colon.  */
     389             :   const char *name;
     390             : 
     391             :   /* The option flags.  If the GROUP flag is set, then this entry is a
     392             :      group marker, not an option, and only the fields LEVEL,
     393             :      DESC_DOMAIN and DESC are valid.  In all other cases, this entry
     394             :      describes a new option and all fields are valid.  */
     395             :   unsigned long flags;
     396             : 
     397             :   /* The expert level.  This field is valid for options and groups.  A
     398             :      group has the expert level of the lowest-level option in the
     399             :      group.  */
     400             :   gc_expert_level_t level;
     401             : 
     402             :   /* A gettext domain in which the following description can be found.
     403             :      If this is NULL, then DESC is not translated.  Valid for groups
     404             :      and options.
     405             : 
     406             :      Note that we try to keep the description of groups within the
     407             :      gnupg domain.
     408             : 
     409             :      IMPORTANT: If you add a new domain please make sure to add a code
     410             :      set switching call to the function my_dgettext further below.  */
     411             :   const char *desc_domain;
     412             : 
     413             :   /* A gettext description for this group or option.  If it starts
     414             :      with a '|', then the string up to the next '|' describes the
     415             :      argument, and the description follows the second '|'.
     416             : 
     417             :      In general enclosing these description in N_() is not required
     418             :      because the description should be identical to the one in the
     419             :      help menu of the respective program. */
     420             :   const char *desc;
     421             : 
     422             :   /* The following fields are only valid for options.  */
     423             : 
     424             :   /* The type of the option argument.  */
     425             :   gc_arg_type_t arg_type;
     426             : 
     427             :   /* The backend that implements this option.  */
     428             :   gc_backend_t backend;
     429             : 
     430             :   /* The following fields are set to NULL at startup (because all
     431             :      option's are declared as static variables).  They are at the end
     432             :      of the list so that they can be omitted from the option
     433             :      declarations.  */
     434             : 
     435             :   /* This is true if the option is supported by this version of the
     436             :      backend.  */
     437             :   int active;
     438             : 
     439             :   /* The default value for this option.  This is NULL if the option is
     440             :      not present in the backend, the empty string if no default is
     441             :      available, and otherwise a quoted string.  */
     442             :   char *default_value;
     443             : 
     444             :   /* The default argument is only valid if the "optional arg" flag is
     445             :      set, and specifies the default argument (value) that is used if
     446             :      the argument is omitted.  */
     447             :   char *default_arg;
     448             : 
     449             :   /* The current value of this option.  */
     450             :   char *value;
     451             : 
     452             :   /* The new flags for this option.  The only defined flag is actually
     453             :      GC_OPT_FLAG_DEFAULT, and it means that the option should be
     454             :      deleted.  In this case, NEW_VALUE is NULL.  */
     455             :   unsigned long new_flags;
     456             : 
     457             :   /* The new value of this option.  */
     458             :   char *new_value;
     459             : };
     460             : typedef struct gc_option gc_option_t;
     461             : 
     462             : /* Use this macro to terminate an option list.  */
     463             : #define GC_OPTION_NULL { NULL }
     464             : 
     465             : 
     466             : #ifndef BUILD_WITH_AGENT
     467             : #define gc_options_gpg_agent NULL
     468             : #else
     469             : /* The options of the GC_COMPONENT_GPG_AGENT component.  */
     470             : static gc_option_t gc_options_gpg_agent[] =
     471             :  {
     472             :    /* The configuration file to which we write the changes.  */
     473             :    { GPGCONF_NAME"-" GPG_AGENT_NAME ".conf",
     474             :      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
     475             :      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
     476             : 
     477             :    { "Monitor",
     478             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     479             :      "gnupg", N_("Options controlling the diagnostic output") },
     480             :    { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
     481             :      "gnupg", "verbose",
     482             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     483             :    { "quiet", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
     484             :      "gnupg", "be somewhat more quiet",
     485             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     486             :    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     487             :      NULL, NULL,
     488             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     489             : 
     490             :    { "Configuration",
     491             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     492             :      "gnupg", N_("Options controlling the configuration") },
     493             :    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     494             :      "gnupg", "|FILE|read options from FILE",
     495             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
     496             :    { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     497             :      "gnupg", "do not use the SCdaemon",
     498             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     499             :    { "enable-ssh-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     500             :      "gnupg", "enable ssh support",
     501             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     502             :    { "enable-putty-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     503             :      "gnupg", "enable putty support",
     504             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     505             : 
     506             :    { "Debug",
     507             :      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
     508             :      "gnupg", N_("Options useful for debugging") },
     509             :    { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
     510             :      "gnupg", "|LEVEL|set the debugging level to LEVEL",
     511             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT },
     512             :    { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
     513             :      "gnupg", N_("|FILE|write server mode logs to FILE"),
     514             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
     515             :    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     516             :      NULL, NULL,
     517             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     518             : 
     519             :    { "Security",
     520             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     521             :      "gnupg", N_("Options controlling the security") },
     522             :    { "default-cache-ttl", GC_OPT_FLAG_RUNTIME,
     523             :      GC_LEVEL_BASIC, "gnupg",
     524             :      "|N|expire cached PINs after N seconds",
     525             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     526             :    { "default-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
     527             :      GC_LEVEL_ADVANCED, "gnupg",
     528             :      N_("|N|expire SSH keys after N seconds"),
     529             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     530             :    { "max-cache-ttl", GC_OPT_FLAG_RUNTIME,
     531             :      GC_LEVEL_EXPERT, "gnupg",
     532             :      N_("|N|set maximum PIN cache lifetime to N seconds"),
     533             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     534             :    { "max-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
     535             :      GC_LEVEL_EXPERT, "gnupg",
     536             :      N_("|N|set maximum SSH key lifetime to N seconds"),
     537             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     538             :    { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME,
     539             :      GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing",
     540             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     541             :    { "allow-emacs-pinentry", GC_OPT_FLAG_RUNTIME,
     542             :      GC_LEVEL_ADVANCED,
     543             :      "gnupg", "allow passphrase to be prompted through Emacs",
     544             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     545             :    { "no-allow-external-cache", GC_OPT_FLAG_RUNTIME,
     546             :      GC_LEVEL_BASIC, "gnupg", "disallow the use of an external password cache",
     547             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     548             :    { "no-allow-mark-trusted", GC_OPT_FLAG_RUNTIME,
     549             :      GC_LEVEL_ADVANCED, "gnupg", "disallow clients to mark keys as \"trusted\"",
     550             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     551             :    { "no-allow-loopback-pinentry", GC_OPT_FLAG_RUNTIME,
     552             :      GC_LEVEL_EXPERT, "gnupg", "disallow caller to override the pinentry",
     553             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     554             :    { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
     555             :      "gnupg", "do not grab keyboard and mouse",
     556             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     557             : 
     558             :    { "Passphrase policy",
     559             :      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
     560             :      "gnupg", N_("Options enforcing a passphrase policy") },
     561             :    { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME,
     562             :      GC_LEVEL_EXPERT, "gnupg",
     563             :      N_("do not allow bypassing the passphrase policy"),
     564             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     565             :    { "min-passphrase-len", GC_OPT_FLAG_RUNTIME,
     566             :      GC_LEVEL_ADVANCED, "gnupg",
     567             :      N_("|N|set minimal required length for new passphrases to N"),
     568             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     569             :    { "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME,
     570             :      GC_LEVEL_EXPERT, "gnupg",
     571             :      N_("|N|require at least N non-alpha characters for a new passphrase"),
     572             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     573             :    { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME,
     574             :      GC_LEVEL_EXPERT,
     575             :      "gnupg", N_("|FILE|check new passphrases against pattern in FILE"),
     576             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
     577             :    { "max-passphrase-days", GC_OPT_FLAG_RUNTIME,
     578             :      GC_LEVEL_EXPERT, "gnupg",
     579             :      N_("|N|expire the passphrase after N days"),
     580             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     581             :    { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME,
     582             :      GC_LEVEL_EXPERT, "gnupg",
     583             :      N_("do not allow the reuse of old passphrases"),
     584             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
     585             :    { "pinentry-timeout", GC_OPT_FLAG_RUNTIME,
     586             :      GC_LEVEL_ADVANCED, "gnupg",
     587             :      N_("|N|set the Pinentry timeout to N seconds"),
     588             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
     589             : 
     590             :    GC_OPTION_NULL
     591             :  };
     592             : #endif /*BUILD_WITH_AGENT*/
     593             : 
     594             : 
     595             : #ifndef BUILD_WITH_SCDAEMON
     596             : #define gc_options_scdaemon NULL
     597             : #else
     598             : /* The options of the GC_COMPONENT_SCDAEMON component.  */
     599             : static gc_option_t gc_options_scdaemon[] =
     600             :  {
     601             :    /* The configuration file to which we write the changes.  */
     602             :    { GPGCONF_NAME"-"SCDAEMON_NAME".conf",
     603             :      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
     604             :      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
     605             : 
     606             :    { "Monitor",
     607             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     608             :      "gnupg", N_("Options controlling the diagnostic output") },
     609             :    { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
     610             :      "gnupg", "verbose",
     611             :      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
     612             :    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     613             :      "gnupg", "be somewhat more quiet",
     614             :      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
     615             :    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     616             :      NULL, NULL,
     617             :      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
     618             : 
     619             :    { "Configuration",
     620             :      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
     621             :      "gnupg", N_("Options controlling the configuration") },
     622             :    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     623             :      "gnupg", "|FILE|read options from FILE",
     624             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
     625             :    { "reader-port", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
     626             :      "gnupg", "|N|connect to reader at port N",
     627             :      GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
     628             :    { "ctapi-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
     629             :      "gnupg", "|NAME|use NAME as ct-API driver",
     630             :      GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
     631             :    { "pcsc-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
     632             :      "gnupg", "|NAME|use NAME as PC/SC driver",
     633             :      GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
     634             :    { "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
     635             :      "gnupg", "do not use the internal CCID driver",
     636             :      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
     637             :    { "disable-pinpad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
     638             :      "gnupg", "do not use a reader's pinpad",
     639             :      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
     640             :    { "enable-pinpad-varlen",
     641             :      GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
     642             :      "gnupg", "use variable length input for pinpad",
     643             :      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
     644             :    { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
     645             :      "gnupg", "|N|disconnect the card after N seconds of inactivity",
     646             :      GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON },
     647             : 
     648             :    { "Debug",
     649             :      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
     650             :      "gnupg", N_("Options useful for debugging") },
     651             :    { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
     652             :      "gnupg", "|LEVEL|set the debugging level to LEVEL",
     653             :      GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
     654             :    { "log-file", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
     655             :      "gnupg", N_("|FILE|write a log to FILE"),
     656             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
     657             : 
     658             :    { "Security",
     659             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     660             :      "gnupg", N_("Options controlling the security") },
     661             :    { "deny-admin", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
     662             :      "gnupg", "deny the use of admin card commands",
     663             :      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
     664             : 
     665             : 
     666             :    GC_OPTION_NULL
     667             :  };
     668             : #endif /*BUILD_WITH_SCDAEMON*/
     669             : 
     670             : #ifndef BUILD_WITH_GPG
     671             : #define gc_options_gpg NULL
     672             : #else
     673             : /* The options of the GC_COMPONENT_GPG component.  */
     674             : static gc_option_t gc_options_gpg[] =
     675             :  {
     676             :    /* The configuration file to which we write the changes.  */
     677             :    { GPGCONF_NAME"-"GPG_NAME".conf",
     678             :      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
     679             :      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
     680             : 
     681             :    { "Monitor",
     682             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     683             :      "gnupg", N_("Options controlling the diagnostic output") },
     684             :    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
     685             :      "gnupg", "verbose",
     686             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
     687             :    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     688             :      "gnupg", "be somewhat more quiet",
     689             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
     690             :    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     691             :      NULL, NULL,
     692             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
     693             : 
     694             :    { "Configuration",
     695             :      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
     696             :      "gnupg", N_("Options controlling the configuration") },
     697             :    { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     698             :      "gnupg", N_("|NAME|use NAME as default secret key"),
     699             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
     700             :    { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     701             :      "gnupg", N_("|NAME|encrypt to user ID NAME as well"),
     702             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
     703             :    { "group", GC_OPT_FLAG_LIST, GC_LEVEL_ADVANCED,
     704             :      "gnupg", N_("|SPEC|set up email aliases"),
     705             :      GC_ARG_TYPE_ALIAS_LIST, GC_BACKEND_GPG },
     706             :    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     707             :      "gnupg", "|FILE|read options from FILE",
     708             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
     709             :    { "default_pubkey_algo",
     710             :      (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
     711             :      NULL, NULL,
     712             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
     713             : 
     714             : 
     715             :    { "Debug",
     716             :      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
     717             :      "gnupg", N_("Options useful for debugging") },
     718             :    { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
     719             :      "gnupg", "|LEVEL|set the debugging level to LEVEL",
     720             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
     721             :    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     722             :      "gnupg", N_("|FILE|write server mode logs to FILE"),
     723             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
     724             : /*    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, */
     725             : /*      NULL, NULL, */
     726             : /*      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG }, */
     727             : 
     728             :    { "Keyserver",
     729             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     730             :      "gnupg", N_("Configuration for Keyservers") },
     731             :    { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     732             :      "gnupg", N_("|URL|use keyserver at URL"), /* Deprecated - use dirmngr */
     733             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
     734             :    { "allow-pka-lookup", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     735             :      "gnupg", N_("allow PKA lookups (DNS requests)"),
     736             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
     737             :    { "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     738             :      "gnupg", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address"),
     739             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
     740             : 
     741             : 
     742             :    GC_OPTION_NULL
     743             :  };
     744             : #endif /*BUILD_WITH_GPG*/
     745             : 
     746             : 
     747             : #ifndef BUILD_WITH_GPGSM
     748             : #define gc_options_gpgsm NULL
     749             : #else
     750             : /* The options of the GC_COMPONENT_GPGSM component.  */
     751             : static gc_option_t gc_options_gpgsm[] =
     752             :  {
     753             :    /* The configuration file to which we write the changes.  */
     754             :    { GPGCONF_NAME"-"GPGSM_NAME".conf",
     755             :      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
     756             :      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
     757             : 
     758             :    { "Monitor",
     759             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     760             :      "gnupg", N_("Options controlling the diagnostic output") },
     761             :    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
     762             :      "gnupg", "verbose",
     763             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     764             :    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     765             :      "gnupg", "be somewhat more quiet",
     766             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     767             :    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     768             :      NULL, NULL,
     769             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     770             : 
     771             :    { "Configuration",
     772             :      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
     773             :      "gnupg", N_("Options controlling the configuration") },
     774             :    { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     775             :      "gnupg", N_("|NAME|use NAME as default secret key"),
     776             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
     777             :    { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     778             :      "gnupg", N_("|NAME|encrypt to user ID NAME as well"),
     779             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
     780             :    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     781             :      "gnupg", "|FILE|read options from FILE",
     782             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
     783             :    { "prefer-system-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     784             :      "gnupg", "use system's dirmngr if available",
     785             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     786             :    { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     787             :      "gnupg", N_("disable all access to the dirmngr"),
     788             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     789             :    { "p12-charset", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     790             :      "gnupg", N_("|NAME|use encoding NAME for PKCS#12 passphrases"),
     791             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
     792             :    { "keyserver", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
     793             :      "gnupg", N_("|SPEC|use this keyserver to lookup keys"),
     794             :      GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_GPGSM },
     795             :    { "default_pubkey_algo",
     796             :      (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
     797             :      NULL, NULL,
     798             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
     799             : 
     800             :    { "Debug",
     801             :      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
     802             :      "gnupg", N_("Options useful for debugging") },
     803             :    { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
     804             :      "gnupg", "|LEVEL|set the debugging level to LEVEL",
     805             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
     806             :    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     807             :      "gnupg", N_("|FILE|write server mode logs to FILE"),
     808             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
     809             :    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     810             :      NULL, NULL,
     811             :      GC_ARG_TYPE_UINT32, GC_BACKEND_GPGSM },
     812             : 
     813             :    { "Security",
     814             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     815             :      "gnupg", N_("Options controlling the security") },
     816             :    { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     817             :      "gnupg", "never consult a CRL",
     818             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     819             :    { "disable-trusted-cert-crl-check", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     820             :      "gnupg", N_("do not check CRLs for root certificates"),
     821             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     822             :    { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     823             :      "gnupg", "check validity using OCSP",
     824             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     825             :    { "include-certs", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     826             :      "gnupg", "|N|number of certificates to include",
     827             :      GC_ARG_TYPE_INT32, GC_BACKEND_GPGSM },
     828             :    { "disable-policy-checks", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     829             :      "gnupg", "do not check certificate policies",
     830             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     831             :    { "auto-issuer-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     832             :      "gnupg", "fetch missing issuer certificates",
     833             :      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
     834             :    { "cipher-algo", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     835             :      "gnupg", "|NAME|use cipher algorithm NAME",
     836             :      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
     837             : 
     838             :    GC_OPTION_NULL
     839             :  };
     840             : #endif /*BUILD_WITH_GPGSM*/
     841             : 
     842             : 
     843             : #ifndef BUILD_WITH_DIRMNGR
     844             : #define gc_options_dirmngr NULL
     845             : #else
     846             : /* The options of the GC_COMPONENT_DIRMNGR component.  */
     847             : static gc_option_t gc_options_dirmngr[] =
     848             :  {
     849             :    /* The configuration file to which we write the changes.  */
     850             :    { GPGCONF_NAME"-"DIRMNGR_NAME".conf",
     851             :      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
     852             :      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
     853             : 
     854             :    { "Monitor",
     855             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     856             :      "gnupg", N_("Options controlling the diagnostic output") },
     857             :    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
     858             :      "dirmngr", "verbose",
     859             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     860             :    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     861             :      "dirmngr", "be somewhat more quiet",
     862             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     863             :    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     864             :      NULL, NULL,
     865             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     866             : 
     867             :    { "Format",
     868             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     869             :      "gnupg", N_("Options controlling the format of the output") },
     870             :    { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     871             :      "dirmngr", "sh-style command output",
     872             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     873             :    { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     874             :      "dirmngr", "csh-style command output",
     875             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     876             : 
     877             :    { "Configuration",
     878             :      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
     879             :      "gnupg", N_("Options controlling the configuration") },
     880             :    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
     881             :      "dirmngr", "|FILE|read options from FILE",
     882             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
     883             : 
     884             :    { "Debug",
     885             :      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
     886             :      "gnupg", N_("Options useful for debugging") },
     887             :    { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
     888             :      "dirmngr", "|LEVEL|set the debugging level to LEVEL",
     889             :      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
     890             :    { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     891             :      "dirmngr", "do not detach from the console",
     892             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     893             :    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     894             :      "dirmngr", N_("|FILE|write server mode logs to FILE"),
     895             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
     896             :    { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     897             :      NULL, NULL,
     898             :      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
     899             :    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
     900             :      NULL, NULL,
     901             :      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
     902             : 
     903             :    { "Enforcement",
     904             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     905             :      "gnupg", N_("Options controlling the interactivity and enforcement") },
     906             :    { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     907             :      "dirmngr", "run without asking a user",
     908             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     909             :    { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     910             :      "dirmngr", "force loading of outdated CRLs",
     911             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     912             :    { "allow-version-check", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     913             :      "dirmngr", "allow online software version check",
     914             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     915             : 
     916             :    { "Tor",
     917             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     918             :      "gnupg", N_("Options controlling the use of Tor") },
     919             :    { "use-tor", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     920             :      "dirmngr", "route all network traffic via TOR",
     921             :       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     922             : 
     923             :    { "Keyserver",
     924             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     925             :      "gnupg", N_("Configuration for Keyservers") },
     926             :    { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     927             :      "gnupg", N_("|URL|use keyserver at URL"),
     928             :      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
     929             : 
     930             :    { "HTTP",
     931             :      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
     932             :      "gnupg", N_("Configuration for HTTP servers") },
     933             :    { "disable-http", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     934             :      "dirmngr", "inhibit the use of HTTP",
     935             :       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     936             :    { "ignore-http-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     937             :      "dirmngr", "ignore HTTP CRL distribution points",
     938             :       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     939             :    { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     940             :      "dirmngr", "|URL|redirect all HTTP requests to URL",
     941             :      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
     942             :    { "honor-http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     943             :      "gnupg", N_("use system's HTTP proxy setting"),
     944             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     945             : 
     946             :    { "LDAP",
     947             :      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
     948             :      "gnupg", N_("Configuration of LDAP servers to use") },
     949             :    { "disable-ldap", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     950             :      "dirmngr", "inhibit the use of LDAP",
     951             :       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     952             :    { "ignore-ldap-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     953             :      "dirmngr", "ignore LDAP CRL distribution points",
     954             :       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     955             :    { "ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     956             :      "dirmngr", "|HOST|use HOST for LDAP queries",
     957             :      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
     958             :    { "only-ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     959             :      "dirmngr", "do not use fallback hosts with --ldap-proxy",
     960             :       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     961             :    { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     962             :      "dirmngr", "add new servers discovered in CRL distribution points"
     963             :      " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     964             :    { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     965             :      "dirmngr", "|N|set LDAP timeout to N seconds",
     966             :      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
     967             :    /* The following entry must not be removed, as it is required for
     968             :       the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST.  */
     969             :    { "ldapserverlist-file",
     970             :      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
     971             :      "dirmngr", "|FILE|read LDAP server list from FILE",
     972             :      GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
     973             :    /* This entry must come after at least one entry for
     974             :       GC_BACKEND_DIRMNGR in this component, so that the entry for
     975             :       "ldapserverlist-file will be initialized before this one.  */
     976             :    { "LDAP Server", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
     977             :      "gnupg", N_("LDAP server list"),
     978             :      GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST },
     979             :    { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     980             :      "dirmngr", "|N|do not return more than N items in one query",
     981             :      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
     982             : 
     983             :    { "OCSP",
     984             :      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
     985             :      "gnupg", N_("Configuration for OCSP") },
     986             :    { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
     987             :      "dirmngr", "allow sending OCSP requests",
     988             :      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     989             :    { "ignore-ocsp-service-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     990             :      "dirmngr", "ignore certificate contained OCSP service URLs",
     991             :       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
     992             :    { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     993             :      "dirmngr", "|URL|use OCSP responder at URL",
     994             :      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
     995             :    { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
     996             :      "dirmngr", "|FPR|OCSP response signed by FPR",
     997             :      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
     998             : 
     999             : 
    1000             :    GC_OPTION_NULL
    1001             :  };
    1002             : #endif /*BUILD_WITH_DIRMNGR*/
    1003             : 
    1004             : 
    1005             : /* The options of the GC_COMPONENT_PINENTRY component.  */
    1006             : static gc_option_t gc_options_pinentry[] =
    1007             :  {
    1008             :    /* A dummy option to allow gc_component_list_components to find the
    1009             :       pinentry backend.  Needs to be a conf file. */
    1010             :    { GPGCONF_NAME"-pinentry.conf",
    1011             :      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
    1012             :      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_PINENTRY },
    1013             : 
    1014             :    GC_OPTION_NULL
    1015             :  };
    1016             : 
    1017             : 
    1018             : 
    1019             : /* Component system.  Each component is a set of options that can be
    1020             :    configured at the same time.  If you change this, don't forget to
    1021             :    update GC_COMPONENT below.  */
    1022             : typedef enum
    1023             :   {
    1024             :     /* The classic GPG for OpenPGP.  */
    1025             :     GC_COMPONENT_GPG,
    1026             : 
    1027             :     /* The GPG Agent.  */
    1028             :     GC_COMPONENT_GPG_AGENT,
    1029             : 
    1030             :     /* The Smardcard Daemon.  */
    1031             :     GC_COMPONENT_SCDAEMON,
    1032             : 
    1033             :     /* GPG for S/MIME.  */
    1034             :     GC_COMPONENT_GPGSM,
    1035             : 
    1036             :     /* The LDAP Directory Manager for CRLs.  */
    1037             :     GC_COMPONENT_DIRMNGR,
    1038             : 
    1039             :     /* The external Pinentry.  */
    1040             :     GC_COMPONENT_PINENTRY,
    1041             : 
    1042             :     /* The number of components.  */
    1043             :     GC_COMPONENT_NR
    1044             :   } gc_component_t;
    1045             : 
    1046             : 
    1047             : /* The information associated with each component.  */
    1048             : static struct
    1049             : {
    1050             :   /* The name of this component.  Must not contain a colon (':')
    1051             :      character.  */
    1052             :   const char *name;
    1053             : 
    1054             :   /* The gettext domain for the description DESC.  If this is NULL,
    1055             :      then the description is not translated.  */
    1056             :   const char *desc_domain;
    1057             : 
    1058             :   /* The description for this domain.  */
    1059             :   const char *desc;
    1060             : 
    1061             :   /* The list of options for this component, terminated by
    1062             :      GC_OPTION_NULL.  */
    1063             :   gc_option_t *options;
    1064             : } gc_component[] =
    1065             :   {
    1066             :     { "gpg",      "gnupg", N_("OpenPGP"), gc_options_gpg },
    1067             :     { "gpg-agent","gnupg", N_("Private Keys"), gc_options_gpg_agent },
    1068             :     { "scdaemon", "gnupg", N_("Smartcards"), gc_options_scdaemon },
    1069             :     { "gpgsm",    "gnupg", N_("S/MIME"), gc_options_gpgsm },
    1070             :     { "dirmngr",  "gnupg", N_("Network"), gc_options_dirmngr },
    1071             :     { "pinentry", "gnupg", N_("Passphrase Entry"), gc_options_pinentry }
    1072             :   };
    1073             : 
    1074             : 
    1075             : 
    1076             : /* Structure used to collect error output of the backend programs.  */
    1077             : struct error_line_s;
    1078             : typedef struct error_line_s *error_line_t;
    1079             : struct error_line_s
    1080             : {
    1081             :   error_line_t next;   /* Link to next item.  */
    1082             :   const char *fname;   /* Name of the config file (points into BUFFER).  */
    1083             :   unsigned int lineno; /* Line number of the config file.  */
    1084             :   const char *errtext; /* Text of the error message (points into BUFFER).  */
    1085             :   char buffer[1];  /* Helper buffer.  */
    1086             : };
    1087             : 
    1088             : 
    1089             : 
    1090             : /* Engine specific support.  */
    1091             : static void
    1092           0 : gpg_agent_runtime_change (int killflag)
    1093             : {
    1094           0 :   gpg_error_t err = 0;
    1095             :   const char *pgmname;
    1096             :   const char *argv[5];
    1097             :   pid_t pid;
    1098           0 :   char *abs_homedir = NULL;
    1099           0 :   int i = 0;
    1100             : 
    1101           0 :   pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
    1102           0 :   if (!gnupg_default_homedir_p ())
    1103             :     {
    1104           0 :       abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
    1105           0 :       if (!abs_homedir)
    1106           0 :         err = gpg_error_from_syserror ();
    1107             : 
    1108           0 :       argv[i++] = "--homedir";
    1109           0 :       argv[i++] = abs_homedir;
    1110             :     }
    1111           0 :   argv[i++] = "--no-autostart";
    1112           0 :   argv[i++] = killflag? "KILLAGENT" : "RELOADAGENT";
    1113           0 :   argv[i++] = NULL;
    1114             : 
    1115           0 :   if (!err)
    1116           0 :     err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
    1117           0 :   if (!err)
    1118           0 :     err = gnupg_wait_process (pgmname, pid, 1, NULL);
    1119           0 :   if (err)
    1120           0 :     gc_error (0, 0, "error running '%s %s': %s",
    1121             :               pgmname, argv[1], gpg_strerror (err));
    1122           0 :   gnupg_release_process (pid);
    1123           0 :   xfree (abs_homedir);
    1124           0 : }
    1125             : 
    1126             : 
    1127             : static void
    1128           0 : scdaemon_runtime_change (int killflag)
    1129             : {
    1130           0 :   gpg_error_t err = 0;
    1131             :   const char *pgmname;
    1132             :   const char *argv[9];
    1133             :   pid_t pid;
    1134           0 :   char *abs_homedir = NULL;
    1135           0 :   int i = 0;
    1136             : 
    1137             :   (void)killflag;  /* For scdaemon kill and reload are synonyms.  */
    1138             : 
    1139             :   /* We use "GETINFO app_running" to see whether the agent is already
    1140             :      running and kill it only in this case.  This avoids an explicit
    1141             :      starting of the agent in case it is not yet running.  There is
    1142             :      obviously a race condition but that should not harm too much.  */
    1143             : 
    1144           0 :   pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
    1145           0 :   if (!gnupg_default_homedir_p ())
    1146             :     {
    1147           0 :       abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
    1148           0 :       if (!abs_homedir)
    1149           0 :         err = gpg_error_from_syserror ();
    1150             : 
    1151           0 :       argv[i++] = "--homedir";
    1152           0 :       argv[i++] = abs_homedir;
    1153             :     }
    1154           0 :   argv[i++] = "-s";
    1155           0 :   argv[i++] = "--no-autostart";
    1156           0 :   argv[i++] = "GETINFO scd_running";
    1157           0 :   argv[i++] = "/if ${! $?}";
    1158           0 :   argv[i++] = "scd killscd";
    1159           0 :   argv[i++] = "/end";
    1160           0 :   argv[i++] = NULL;
    1161             : 
    1162           0 :   if (!err)
    1163           0 :     err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
    1164           0 :   if (!err)
    1165           0 :     err = gnupg_wait_process (pgmname, pid, 1, NULL);
    1166           0 :   if (err)
    1167           0 :     gc_error (0, 0, "error running '%s %s': %s",
    1168             :               pgmname, argv[4], gpg_strerror (err));
    1169           0 :   gnupg_release_process (pid);
    1170           0 :   xfree (abs_homedir);
    1171           0 : }
    1172             : 
    1173             : 
    1174             : static void
    1175           0 : dirmngr_runtime_change (int killflag)
    1176             : {
    1177           0 :   gpg_error_t err = 0;
    1178             :   const char *pgmname;
    1179             :   const char *argv[6];
    1180             :   pid_t pid;
    1181           0 :   char *abs_homedir = NULL;
    1182             : 
    1183           0 :   pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
    1184           0 :   argv[0] = "--no-autostart";
    1185           0 :   argv[1] = "--dirmngr";
    1186           0 :   argv[2] = killflag? "KILLDIRMNGR" : "RELOADDIRMNGR";
    1187           0 :   if (gnupg_default_homedir_p ())
    1188           0 :     argv[3] = NULL;
    1189             :   else
    1190             :     {
    1191           0 :       abs_homedir = make_absfilename_try (gnupg_homedir (), NULL);
    1192           0 :       if (!abs_homedir)
    1193           0 :         err = gpg_error_from_syserror ();
    1194             : 
    1195           0 :       argv[3] = "--homedir";
    1196           0 :       argv[4] = abs_homedir;
    1197           0 :       argv[5] = NULL;
    1198             :     }
    1199             : 
    1200           0 :   if (!err)
    1201           0 :     err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
    1202           0 :   if (!err)
    1203           0 :     err = gnupg_wait_process (pgmname, pid, 1, NULL);
    1204           0 :   if (err)
    1205           0 :     gc_error (0, 0, "error running '%s %s': %s",
    1206             :               pgmname, argv[2], gpg_strerror (err));
    1207           0 :   gnupg_release_process (pid);
    1208           0 :   xfree (abs_homedir);
    1209           0 : }
    1210             : 
    1211             : 
    1212             : /* Launch the gpg-agent or the dirmngr if not already running.  */
    1213             : gpg_error_t
    1214           0 : gc_component_launch (int component)
    1215             : {
    1216             :   gpg_error_t err;
    1217             :   const char *pgmname;
    1218             :   const char *argv[3];
    1219             :   int i;
    1220             :   pid_t pid;
    1221             : 
    1222           0 :   if (!(component == GC_COMPONENT_GPG_AGENT
    1223             :         || component == GC_COMPONENT_DIRMNGR))
    1224             :     {
    1225           0 :       es_fputs (_("Component not suitable for launching"), es_stderr);
    1226           0 :       es_putc ('\n', es_stderr);
    1227           0 :       exit (1);
    1228             :     }
    1229             : 
    1230           0 :   pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
    1231           0 :   i = 0;
    1232           0 :   if (component == GC_COMPONENT_DIRMNGR)
    1233           0 :     argv[i++] = "--dirmngr";
    1234           0 :   argv[i++] = "NOP";
    1235           0 :   argv[i] = NULL;
    1236             : 
    1237           0 :   err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
    1238           0 :   if (!err)
    1239           0 :     err = gnupg_wait_process (pgmname, pid, 1, NULL);
    1240           0 :   if (err)
    1241           0 :     gc_error (0, 0, "error running '%s%s%s': %s",
    1242             :               pgmname,
    1243             :               component == GC_COMPONENT_DIRMNGR? " --dirmngr":"",
    1244             :               " NOP",
    1245             :               gpg_strerror (err));
    1246           0 :   gnupg_release_process (pid);
    1247           0 :   return err;
    1248             : }
    1249             : 
    1250             : 
    1251             : /* Unconditionally restart COMPONENT.  */
    1252             : void
    1253           0 : gc_component_kill (int component)
    1254             : {
    1255             :   int runtime[GC_BACKEND_NR];
    1256             :   gc_option_t *option;
    1257             :   gc_backend_t backend;
    1258             : 
    1259             :   /* Set a flag for the backends to be reloaded.  */
    1260           0 :   for (backend = 0; backend < GC_BACKEND_NR; backend++)
    1261           0 :     runtime[backend] = 0;
    1262             : 
    1263           0 :   if (component >= 0)
    1264             :     {
    1265           0 :       assert (component < GC_COMPONENT_NR);
    1266           0 :       option = gc_component[component].options;
    1267           0 :       for (; option && option->name; option++)
    1268           0 :         runtime[option->backend] = 1;
    1269             :     }
    1270             : 
    1271             :   /* Do the restart for the selected backends.  */
    1272           0 :   for (backend = 0; backend < GC_BACKEND_NR; backend++)
    1273             :     {
    1274           0 :       if (runtime[backend] && gc_backend[backend].runtime_change)
    1275           0 :         (*gc_backend[backend].runtime_change) (1);
    1276             :     }
    1277           0 : }
    1278             : 
    1279             : 
    1280             : /* Unconditionally reload COMPONENT or all components if COMPONENT is -1.  */
    1281             : void
    1282           0 : gc_component_reload (int component)
    1283             : {
    1284             :   int runtime[GC_BACKEND_NR];
    1285             :   gc_option_t *option;
    1286             :   gc_backend_t backend;
    1287             : 
    1288             :   /* Set a flag for the backends to be reloaded.  */
    1289           0 :   for (backend = 0; backend < GC_BACKEND_NR; backend++)
    1290           0 :     runtime[backend] = 0;
    1291             : 
    1292           0 :   if (component == -1)
    1293             :     {
    1294           0 :       for (component = 0; component < GC_COMPONENT_NR; component++)
    1295             :         {
    1296           0 :           option = gc_component[component].options;
    1297           0 :           for (; option && option->name; option++)
    1298           0 :             runtime[option->backend] = 1;
    1299             :         }
    1300             :     }
    1301             :   else
    1302             :     {
    1303           0 :       assert (component < GC_COMPONENT_NR);
    1304           0 :       option = gc_component[component].options;
    1305           0 :       for (; option && option->name; option++)
    1306           0 :         runtime[option->backend] = 1;
    1307             :     }
    1308             : 
    1309             :   /* Do the reload for all selected backends.  */
    1310           0 :   for (backend = 0; backend < GC_BACKEND_NR; backend++)
    1311             :     {
    1312           0 :       if (runtime[backend] && gc_backend[backend].runtime_change)
    1313           0 :         (*gc_backend[backend].runtime_change) (0);
    1314             :     }
    1315           0 : }
    1316             : 
    1317             : 
    1318             : 
    1319             : /* More or less Robust version of dgettext.  It has the side effect of
    1320             :    switching the codeset to utf-8 because this is what we want to
    1321             :    output.  In theory it is posible to keep the original code set and
    1322             :    switch back for regular disgnostic output (redefine "_(" for that)
    1323             :    but given the natur of this tool, being something invoked from
    1324             :    other pograms, it does not make much sense.  */
    1325             : static const char *
    1326           0 : my_dgettext (const char *domain, const char *msgid)
    1327             : {
    1328             : #ifdef USE_SIMPLE_GETTEXT
    1329             :   if (domain)
    1330             :     {
    1331             :       static int switched_codeset;
    1332             :       char *text;
    1333             : 
    1334             :       if (!switched_codeset)
    1335             :         {
    1336             :           switched_codeset = 1;
    1337             :           gettext_use_utf8 (1);
    1338             :         }
    1339             : 
    1340             :       if (!strcmp (domain, "gnupg"))
    1341             :         domain = PACKAGE_GT;
    1342             : 
    1343             :       /* FIXME: we have no dgettext, thus we can't switch.  */
    1344             : 
    1345             :       text = (char*)gettext (msgid);
    1346             :       return text ? text : msgid;
    1347             :     }
    1348             :   else
    1349             :     return msgid;
    1350             : #elif defined(ENABLE_NLS)
    1351           0 :   if (domain)
    1352             :     {
    1353             :       static int switched_codeset;
    1354             :       char *text;
    1355             : 
    1356           0 :       if (!switched_codeset)
    1357             :         {
    1358           0 :           switched_codeset = 1;
    1359           0 :           bind_textdomain_codeset (PACKAGE_GT, "utf-8");
    1360             : 
    1361           0 :           bindtextdomain (DIRMNGR_NAME, LOCALEDIR);
    1362           0 :           bind_textdomain_codeset (DIRMNGR_NAME, "utf-8");
    1363             : 
    1364             :         }
    1365             : 
    1366             :       /* Note: This is a hack to actually use the gnupg2 domain as
    1367             :          long we are in a transition phase where gnupg 1.x and 1.9 may
    1368             :          coexist. */
    1369           0 :       if (!strcmp (domain, "gnupg"))
    1370           0 :         domain = PACKAGE_GT;
    1371             : 
    1372           0 :       text = dgettext (domain, msgid);
    1373           0 :       return text ? text : msgid;
    1374             :     }
    1375             :   else
    1376           0 :     return msgid;
    1377             : #else
    1378             :   (void)domain;
    1379             :   return msgid;
    1380             : #endif
    1381             : }
    1382             : 
    1383             : 
    1384             : /* Percent-Escape special characters.  The string is valid until the
    1385             :    next invocation of the function.  */
    1386             : char *
    1387           0 : gc_percent_escape (const char *src)
    1388             : {
    1389             :   static char *esc_str;
    1390             :   static int esc_str_len;
    1391           0 :   int new_len = 3 * strlen (src) + 1;
    1392             :   char *dst;
    1393             : 
    1394           0 :   if (esc_str_len < new_len)
    1395             :     {
    1396           0 :       char *new_esc_str = realloc (esc_str, new_len);
    1397           0 :       if (!new_esc_str)
    1398           0 :         gc_error (1, errno, "can not escape string");
    1399           0 :       esc_str = new_esc_str;
    1400           0 :       esc_str_len = new_len;
    1401             :     }
    1402             : 
    1403           0 :   dst = esc_str;
    1404           0 :   while (*src)
    1405             :     {
    1406           0 :       if (*src == '%')
    1407             :         {
    1408           0 :           *(dst++) = '%';
    1409           0 :           *(dst++) = '2';
    1410           0 :           *(dst++) = '5';
    1411             :         }
    1412           0 :       else if (*src == ':')
    1413             :         {
    1414             :           /* The colon is used as field separator.  */
    1415           0 :           *(dst++) = '%';
    1416           0 :           *(dst++) = '3';
    1417           0 :           *(dst++) = 'a';
    1418             :         }
    1419           0 :       else if (*src == ',')
    1420             :         {
    1421             :           /* The comma is used as list separator.  */
    1422           0 :           *(dst++) = '%';
    1423           0 :           *(dst++) = '2';
    1424           0 :           *(dst++) = 'c';
    1425             :         }
    1426             :       else
    1427           0 :         *(dst++) = *(src);
    1428           0 :       src++;
    1429             :     }
    1430           0 :   *dst = '\0';
    1431           0 :   return esc_str;
    1432             : }
    1433             : 
    1434             : 
    1435             : 
    1436             : /* Percent-Deescape special characters.  The string is valid until the
    1437             :    next invocation of the function.  */
    1438             : static char *
    1439           0 : percent_deescape (const char *src)
    1440             : {
    1441             :   static char *str;
    1442             :   static int str_len;
    1443           0 :   int new_len = 3 * strlen (src) + 1;
    1444             :   char *dst;
    1445             : 
    1446           0 :   if (str_len < new_len)
    1447             :     {
    1448           0 :       char *new_str = realloc (str, new_len);
    1449           0 :       if (!new_str)
    1450           0 :         gc_error (1, errno, "can not deescape string");
    1451           0 :       str = new_str;
    1452           0 :       str_len = new_len;
    1453             :     }
    1454             : 
    1455           0 :   dst = str;
    1456           0 :   while (*src)
    1457             :     {
    1458           0 :       if (*src == '%')
    1459             :         {
    1460           0 :           int val = hextobyte (src + 1);
    1461             : 
    1462           0 :           if (val < 0)
    1463           0 :             gc_error (1, 0, "malformed end of string %s", src);
    1464             : 
    1465           0 :           *(dst++) = (char) val;
    1466           0 :           src += 3;
    1467             :         }
    1468             :       else
    1469           0 :         *(dst++) = *(src++);
    1470             :     }
    1471           0 :   *dst = '\0';
    1472           0 :   return str;
    1473             : }
    1474             : 
    1475             : 
    1476             : /* List all components that are available.  */
    1477             : void
    1478           0 : gc_component_list_components (estream_t out)
    1479             : {
    1480             :   gc_component_t component;
    1481             :   gc_option_t *option;
    1482             :   gc_backend_t backend;
    1483             :   int backend_seen[GC_BACKEND_NR];
    1484             :   const char *desc;
    1485             :   const char *pgmname;
    1486             : 
    1487           0 :   for (component = 0; component < GC_COMPONENT_NR; component++)
    1488             :     {
    1489           0 :       option = gc_component[component].options;
    1490           0 :       if (option)
    1491             :         {
    1492           0 :           for (backend = 0; backend < GC_BACKEND_NR; backend++)
    1493           0 :             backend_seen[backend] = 0;
    1494             : 
    1495           0 :           pgmname = "";
    1496           0 :           for (; option && option->name; option++)
    1497             :             {
    1498           0 :               if ((option->flags & GC_OPT_FLAG_GROUP))
    1499           0 :                 continue;
    1500           0 :               backend = option->backend;
    1501           0 :               if (backend_seen[backend])
    1502           0 :                 continue;
    1503           0 :               backend_seen[backend] = 1;
    1504           0 :               assert (backend != GC_BACKEND_ANY);
    1505           0 :               if (gc_backend[backend].program
    1506           0 :                   && !gc_backend[backend].module_name)
    1507           0 :                 continue;
    1508           0 :               pgmname = gnupg_module_name (gc_backend[backend].module_name);
    1509           0 :               break;
    1510             :             }
    1511             : 
    1512           0 :           desc = gc_component[component].desc;
    1513           0 :           desc = my_dgettext (gc_component[component].desc_domain, desc);
    1514           0 :           es_fprintf (out, "%s:%s:",
    1515             :                       gc_component[component].name,  gc_percent_escape (desc));
    1516           0 :           es_fprintf (out, "%s\n",  gc_percent_escape (pgmname));
    1517             :         }
    1518             :     }
    1519           0 : }
    1520             : 
    1521             : 
    1522             : 
    1523             : static int
    1524           0 : all_digits_p (const char *p, size_t len)
    1525             : {
    1526           0 :   if (!len)
    1527           0 :     return 0; /* No. */
    1528           0 :   for (; len; len--, p++)
    1529           0 :     if (!isascii (*p) || !isdigit (*p))
    1530           0 :       return 0; /* No.  */
    1531           0 :   return 1; /* Yes.  */
    1532             : }
    1533             : 
    1534             : 
    1535             : /* Collect all error lines from stream FP. Only lines prefixed with
    1536             :    TAG are considered.  Returns a list of error line items (which may
    1537             :    be empty).  There is no error return.  */
    1538             : static error_line_t
    1539           0 : collect_error_output (estream_t fp, const char *tag)
    1540             : {
    1541             :   char buffer[1024];
    1542             :   char *p, *p2, *p3;
    1543             :   int c, cont_line;
    1544             :   unsigned int pos;
    1545             :   error_line_t eitem, errlines, *errlines_tail;
    1546           0 :   size_t taglen = strlen (tag);
    1547             : 
    1548           0 :   errlines = NULL;
    1549           0 :   errlines_tail = &errlines;
    1550           0 :   pos = 0;
    1551           0 :   cont_line = 0;
    1552           0 :   while ((c=es_getc (fp)) != EOF)
    1553             :     {
    1554           0 :       buffer[pos++] = c;
    1555           0 :       if (pos >= sizeof buffer - 5 || c == '\n')
    1556             :         {
    1557           0 :           buffer[pos - (c == '\n')] = 0;
    1558           0 :           if (cont_line)
    1559             :             ; /*Ignore continuations of previous line. */
    1560           0 :           else if (!strncmp (buffer, tag, taglen) && buffer[taglen] == ':')
    1561             :             {
    1562             :               /* "gpgsm: foo:4: bla" */
    1563             :               /* Yep, we are interested in this line.  */
    1564           0 :               p = buffer + taglen + 1;
    1565           0 :               while (*p == ' ' || *p == '\t')
    1566           0 :                 p++;
    1567           0 :               trim_trailing_spaces (p); /* Get rid of extra CRs.  */
    1568           0 :               if (!*p)
    1569             :                 ; /* Empty lines are ignored.  */
    1570           0 :               else if ( (p2 = strchr (p, ':')) && (p3 = strchr (p2+1, ':'))
    1571           0 :                         && all_digits_p (p2+1, p3 - (p2+1)))
    1572             :                 {
    1573             :                   /* Line in standard compiler format.  */
    1574           0 :                   p3++;
    1575           0 :                   while (*p3 == ' ' || *p3 == '\t')
    1576           0 :                     p3++;
    1577           0 :                   eitem = xmalloc (sizeof *eitem + strlen (p));
    1578           0 :                   eitem->next = NULL;
    1579           0 :                   strcpy (eitem->buffer, p);
    1580           0 :                   eitem->fname = eitem->buffer;
    1581           0 :                   eitem->buffer[p2-p] = 0;
    1582           0 :                   eitem->errtext = eitem->buffer + (p3 - p);
    1583             :                   /* (we already checked that there are only ascii
    1584             :                      digits followed by a colon) */
    1585           0 :                   eitem->lineno = 0;
    1586           0 :                   for (p2++; isdigit (*p2); p2++)
    1587           0 :                     eitem->lineno = eitem->lineno*10 + (*p2 - '0');
    1588           0 :                   *errlines_tail = eitem;
    1589           0 :                   errlines_tail = &eitem->next;
    1590             :                 }
    1591             :               else
    1592             :                 {
    1593             :                   /* Other error output.  */
    1594           0 :                   eitem = xmalloc (sizeof *eitem + strlen (p));
    1595           0 :                   eitem->next = NULL;
    1596           0 :                   strcpy (eitem->buffer, p);
    1597           0 :                   eitem->fname = NULL;
    1598           0 :                   eitem->errtext = eitem->buffer;
    1599           0 :                   eitem->lineno = 0;
    1600           0 :                   *errlines_tail = eitem;
    1601           0 :                   errlines_tail = &eitem->next;
    1602             :                 }
    1603             :             }
    1604           0 :           pos = 0;
    1605             :           /* If this was not a complete line mark that we are in a
    1606             :              continuation.  */
    1607           0 :           cont_line = (c != '\n');
    1608             :         }
    1609             :     }
    1610             : 
    1611             :   /* We ignore error lines not terminated by a LF.  */
    1612           0 :   return errlines;
    1613             : }
    1614             : 
    1615             : 
    1616             : /* Check the options of a single component.  Returns 0 if everything
    1617             :    is OK.  */
    1618             : int
    1619           0 : gc_component_check_options (int component, estream_t out, const char *conf_file)
    1620             : {
    1621             :   gpg_error_t err;
    1622             :   unsigned int result;
    1623             :   int backend_seen[GC_BACKEND_NR];
    1624             :   gc_backend_t backend;
    1625             :   gc_option_t *option;
    1626             :   const char *pgmname;
    1627             :   const char *argv[4];
    1628             :   int i;
    1629             :   pid_t pid;
    1630             :   int exitcode;
    1631             :   estream_t errfp;
    1632             :   error_line_t errlines;
    1633             : 
    1634           0 :   for (backend = 0; backend < GC_BACKEND_NR; backend++)
    1635           0 :     backend_seen[backend] = 0;
    1636             : 
    1637           0 :   option = gc_component[component].options;
    1638           0 :   for (; option && option->name; option++)
    1639             :     {
    1640           0 :       if ((option->flags & GC_OPT_FLAG_GROUP))
    1641           0 :         continue;
    1642           0 :       backend = option->backend;
    1643           0 :       if (backend_seen[backend])
    1644           0 :         continue;
    1645           0 :       backend_seen[backend] = 1;
    1646           0 :       assert (backend != GC_BACKEND_ANY);
    1647           0 :       if (!gc_backend[backend].program)
    1648           0 :         continue;
    1649           0 :       if (!gc_backend[backend].module_name)
    1650           0 :         continue;
    1651             : 
    1652           0 :       break;
    1653             :     }
    1654           0 :   if (! option || ! option->name)
    1655           0 :     return 0;
    1656             : 
    1657           0 :   pgmname = gnupg_module_name (gc_backend[backend].module_name);
    1658           0 :   i = 0;
    1659           0 :   if (conf_file)
    1660             :     {
    1661           0 :       argv[i++] = "--options";
    1662           0 :       argv[i++] = conf_file;
    1663             :     }
    1664           0 :   if (component == GC_COMPONENT_PINENTRY)
    1665           0 :     argv[i++] = "--version";
    1666             :   else
    1667           0 :     argv[i++] = "--gpgconf-test";
    1668           0 :   argv[i++] = NULL;
    1669             : 
    1670           0 :   result = 0;
    1671           0 :   errlines = NULL;
    1672           0 :   err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0,
    1673             :                              NULL, NULL, &errfp, &pid);
    1674           0 :   if (err)
    1675           0 :     result |= 1; /* Program could not be run.  */
    1676             :   else
    1677             :     {
    1678           0 :       errlines = collect_error_output (errfp,
    1679             :                                        gc_component[component].name);
    1680           0 :       if (gnupg_wait_process (pgmname, pid, 1, &exitcode))
    1681             :         {
    1682           0 :           if (exitcode == -1)
    1683           0 :             result |= 1; /* Program could not be run or it
    1684             :                             terminated abnormally.  */
    1685           0 :           result |= 2; /* Program returned an error.  */
    1686             :         }
    1687           0 :       gnupg_release_process (pid);
    1688           0 :       es_fclose (errfp);
    1689             :     }
    1690             : 
    1691             :   /* If the program could not be run, we can't tell whether
    1692             :      the config file is good.  */
    1693           0 :   if (result & 1)
    1694           0 :     result |= 2;
    1695             : 
    1696           0 :   if (out)
    1697             :     {
    1698             :       const char *desc;
    1699             :       error_line_t errptr;
    1700             : 
    1701           0 :       desc = gc_component[component].desc;
    1702           0 :       desc = my_dgettext (gc_component[component].desc_domain, desc);
    1703           0 :       es_fprintf (out, "%s:%s:",
    1704             :                   gc_component[component].name, gc_percent_escape (desc));
    1705           0 :       es_fputs (gc_percent_escape (pgmname), out);
    1706           0 :       es_fprintf (out, ":%d:%d:", !(result & 1), !(result & 2));
    1707           0 :       for (errptr = errlines; errptr; errptr = errptr->next)
    1708             :         {
    1709           0 :           if (errptr != errlines)
    1710           0 :             es_fputs ("\n:::::", out); /* Continuation line.  */
    1711           0 :           if (errptr->fname)
    1712           0 :             es_fputs (gc_percent_escape (errptr->fname), out);
    1713           0 :           es_putc (':', out);
    1714           0 :           if (errptr->fname)
    1715           0 :             es_fprintf (out, "%u", errptr->lineno);
    1716           0 :           es_putc (':', out);
    1717           0 :           es_fputs (gc_percent_escape (errptr->errtext), out);
    1718           0 :           es_putc (':', out);
    1719             :         }
    1720           0 :       es_putc ('\n', out);
    1721             :     }
    1722             : 
    1723           0 :   while (errlines)
    1724             :     {
    1725           0 :       error_line_t tmp = errlines->next;
    1726           0 :       xfree (errlines);
    1727           0 :       errlines = tmp;
    1728             :     }
    1729             : 
    1730           0 :   return result;
    1731             : }
    1732             : 
    1733             : 
    1734             : 
    1735             : /* Check all components that are available.  */
    1736             : void
    1737           0 : gc_check_programs (estream_t out)
    1738             : {
    1739             :   gc_component_t component;
    1740             : 
    1741           0 :   for (component = 0; component < GC_COMPONENT_NR; component++)
    1742           0 :     gc_component_check_options (component, out, NULL);
    1743           0 : }
    1744             : 
    1745             : 
    1746             : 
    1747             : /* Find the component with the name NAME.  Returns -1 if not
    1748             :    found.  */
    1749             : int
    1750           0 : gc_component_find (const char *name)
    1751             : {
    1752             :   gc_component_t idx;
    1753             : 
    1754           0 :   for (idx = 0; idx < GC_COMPONENT_NR; idx++)
    1755             :     {
    1756           0 :       if (gc_component[idx].options
    1757           0 :           && !strcmp (name, gc_component[idx].name))
    1758           0 :         return idx;
    1759             :     }
    1760           0 :   return -1;
    1761             : }
    1762             : 
    1763             : 
    1764             : /* List the option OPTION.  */
    1765             : static void
    1766           0 : list_one_option (const gc_option_t *option, estream_t out)
    1767             : {
    1768           0 :   const char *desc = NULL;
    1769           0 :   char *arg_name = NULL;
    1770             : 
    1771           0 :   if (option->desc)
    1772             :     {
    1773           0 :       desc = my_dgettext (option->desc_domain, option->desc);
    1774             : 
    1775           0 :       if (*desc == '|')
    1776             :         {
    1777           0 :           const char *arg_tail = strchr (&desc[1], '|');
    1778             : 
    1779           0 :           if (arg_tail)
    1780             :             {
    1781           0 :               int arg_len = arg_tail - &desc[1];
    1782           0 :               arg_name = xmalloc (arg_len + 1);
    1783           0 :               memcpy (arg_name, &desc[1], arg_len);
    1784           0 :               arg_name[arg_len] = '\0';
    1785           0 :               desc = arg_tail + 1;
    1786             :             }
    1787             :         }
    1788             :     }
    1789             : 
    1790             : 
    1791             :   /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR ORDER IS
    1792             :      PART OF THE EXTERNAL INTERFACE.  YOU MUST NOT REMOVE ANY
    1793             :      FIELDS.  */
    1794             : 
    1795             :   /* The name field.  */
    1796           0 :   es_fprintf (out, "%s", option->name);
    1797             : 
    1798             :   /* The flags field.  */
    1799           0 :   es_fprintf (out, ":%lu", option->flags);
    1800           0 :   if (opt.verbose)
    1801             :     {
    1802           0 :       es_putc (' ', out);
    1803             : 
    1804           0 :       if (!option->flags)
    1805           0 :         es_fprintf (out, "none");
    1806             :       else
    1807             :         {
    1808           0 :           unsigned long flags = option->flags;
    1809           0 :           unsigned long flag = 0;
    1810           0 :           unsigned long first = 1;
    1811             : 
    1812           0 :           while (flags)
    1813             :             {
    1814           0 :               if (flags & 1)
    1815             :                 {
    1816           0 :                   if (first)
    1817           0 :                     first = 0;
    1818             :                   else
    1819           0 :                     es_putc (',', out);
    1820           0 :                   es_fprintf (out, "%s", gc_flag[flag].name);
    1821             :                 }
    1822           0 :               flags >>= 1;
    1823           0 :               flag++;
    1824             :             }
    1825             :         }
    1826             :     }
    1827             : 
    1828             :   /* The level field.  */
    1829           0 :   es_fprintf (out, ":%u", option->level);
    1830           0 :   if (opt.verbose)
    1831           0 :     es_fprintf (out, " %s", gc_level[option->level].name);
    1832             : 
    1833             :   /* The description field.  */
    1834           0 :   es_fprintf (out, ":%s", desc ? gc_percent_escape (desc) : "");
    1835             : 
    1836             :   /* The type field.  */
    1837           0 :   es_fprintf (out, ":%u", option->arg_type);
    1838           0 :   if (opt.verbose)
    1839           0 :     es_fprintf (out, " %s", gc_arg_type[option->arg_type].name);
    1840             : 
    1841             :   /* The alternate type field.  */
    1842           0 :   es_fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback);
    1843           0 :   if (opt.verbose)
    1844           0 :     es_fprintf (out, " %s",
    1845           0 :                 gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
    1846             : 
    1847             :   /* The argument name field.  */
    1848           0 :   es_fprintf (out, ":%s", arg_name ? gc_percent_escape (arg_name) : "");
    1849           0 :   xfree (arg_name);
    1850             : 
    1851             :   /* The default value field.  */
    1852           0 :   es_fprintf (out, ":%s", option->default_value ? option->default_value : "");
    1853             : 
    1854             :   /* The default argument field.  */
    1855           0 :   es_fprintf (out, ":%s", option->default_arg ? option->default_arg : "");
    1856             : 
    1857             :   /* The value field.  */
    1858           0 :   if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
    1859           0 :       && (option->flags & GC_OPT_FLAG_LIST)
    1860           0 :       && option->value)
    1861             :     /* The special format "1,1,1,1,...,1" is converted to a number
    1862             :        here.  */
    1863           0 :     es_fprintf (out, ":%u", (unsigned int)((strlen (option->value) + 1) / 2));
    1864             :   else
    1865           0 :     es_fprintf (out, ":%s", option->value ? option->value : "");
    1866             : 
    1867             :   /* ADD NEW FIELDS HERE.  */
    1868             : 
    1869           0 :   es_putc ('\n', out);
    1870           0 : }
    1871             : 
    1872             : 
    1873             : /* List all options of the component COMPONENT.  */
    1874             : void
    1875           0 : gc_component_list_options (int component, estream_t out)
    1876             : {
    1877           0 :   const gc_option_t *option = gc_component[component].options;
    1878             : 
    1879           0 :   while (option && option->name)
    1880             :     {
    1881             :       /* Do not output unknown or internal options.  */
    1882           0 :       if (!(option->flags & GC_OPT_FLAG_GROUP)
    1883           0 :           && (!option->active || option->level == GC_LEVEL_INTERNAL))
    1884             :         {
    1885           0 :           option++;
    1886           0 :           continue;
    1887             :         }
    1888             : 
    1889           0 :       if (option->flags & GC_OPT_FLAG_GROUP)
    1890             :         {
    1891           0 :           const gc_option_t *group_option = option + 1;
    1892           0 :           gc_expert_level_t level = GC_LEVEL_NR;
    1893             : 
    1894             :           /* The manual states that the group level is always the
    1895             :              minimum of the levels of all contained options.  Due to
    1896             :              different active options, and because it is hard to
    1897             :              maintain manually, we calculate it here.  The value in
    1898             :              the global static table is ignored.  */
    1899             : 
    1900           0 :           while (group_option->name)
    1901             :             {
    1902           0 :               if (group_option->flags & GC_OPT_FLAG_GROUP)
    1903           0 :                 break;
    1904           0 :               if (group_option->level < level)
    1905           0 :                 level = group_option->level;
    1906           0 :               group_option++;
    1907             :             }
    1908             : 
    1909             :           /* Check if group is empty.  */
    1910           0 :           if (level != GC_LEVEL_NR)
    1911             :             {
    1912             :               gc_option_t opt_copy;
    1913             : 
    1914             :               /* Fix up the group level.  */
    1915           0 :               memcpy (&opt_copy, option, sizeof (opt_copy));
    1916           0 :               opt_copy.level = level;
    1917           0 :               list_one_option (&opt_copy, out);
    1918             :             }
    1919             :         }
    1920             :       else
    1921           0 :         list_one_option (option, out);
    1922             : 
    1923           0 :       option++;
    1924             :     }
    1925           0 : }
    1926             : 
    1927             : 
    1928             : /* Find the option NAME in component COMPONENT, for the backend
    1929             :    BACKEND.  If BACKEND is GC_BACKEND_ANY, any backend will match.  */
    1930             : static gc_option_t *
    1931           0 : find_option (gc_component_t component, const char *name,
    1932             :              gc_backend_t backend)
    1933             : {
    1934           0 :   gc_option_t *option = gc_component[component].options;
    1935           0 :   while (option->name)
    1936             :     {
    1937           0 :       if (!(option->flags & GC_OPT_FLAG_GROUP)
    1938           0 :           && !strcmp (option->name, name)
    1939           0 :           && (backend == GC_BACKEND_ANY || option->backend == backend))
    1940             :         break;
    1941           0 :       option++;
    1942             :     }
    1943           0 :   return option->name ? option : NULL;
    1944             : }
    1945             : 
    1946             : 
    1947             : /* Determine the configuration filename for the component COMPONENT
    1948             :    and backend BACKEND.  */
    1949             : static char *
    1950           0 : get_config_filename (gc_component_t component, gc_backend_t backend)
    1951             : {
    1952           0 :   char *filename = NULL;
    1953           0 :   gc_option_t *option = find_option
    1954             :     (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
    1955           0 :   assert (option);
    1956           0 :   assert (option->arg_type == GC_ARG_TYPE_FILENAME);
    1957           0 :   assert (!(option->flags & GC_OPT_FLAG_LIST));
    1958             : 
    1959           0 :   if (!option->active || !option->default_value)
    1960           0 :     gc_error (1, 0, "Option %s, needed by backend %s, was not initialized",
    1961             :               gc_backend[backend].option_config_filename,
    1962             :               gc_backend[backend].name);
    1963             : 
    1964           0 :   if (option->value && *option->value)
    1965           0 :     filename = percent_deescape (&option->value[1]);
    1966           0 :   else if (option->default_value && *option->default_value)
    1967           0 :     filename = percent_deescape (&option->default_value[1]);
    1968             :   else
    1969           0 :     filename = "";
    1970             : 
    1971             : #if HAVE_W32CE_SYSTEM
    1972             :   if (!(filename[0] == '/' || filename[0] == '\\'))
    1973             : #elif defined(HAVE_DOSISH_SYSTEM)
    1974             :   if (!(filename[0]
    1975             :         && filename[1] == ':'
    1976             :         && (filename[2] == '/' || filename[2] == '\\')))
    1977             : #else
    1978           0 :   if (filename[0] != '/')
    1979             : #endif
    1980           0 :     gc_error (1, 0, "Option %s, needed by backend %s, is not absolute",
    1981             :               gc_backend[backend].option_config_filename,
    1982             :               gc_backend[backend].name);
    1983             : 
    1984           0 :   return filename;
    1985             : }
    1986             : 
    1987             : 
    1988             : /* Retrieve the options for the component COMPONENT from backend
    1989             :    BACKEND, which we already know is a program-type backend.  */
    1990             : static void
    1991           0 : retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
    1992             : {
    1993             :   gpg_error_t err;
    1994             :   const char *pgmname;
    1995             :   const char *argv[2];
    1996             :   estream_t outfp;
    1997             :   int exitcode;
    1998             :   pid_t pid;
    1999           0 :   char *line = NULL;
    2000           0 :   size_t line_len = 0;
    2001             :   ssize_t length;
    2002             :   estream_t config;
    2003             :   char *config_filename;
    2004             : 
    2005           0 :   pgmname = (gc_backend[backend].module_name
    2006           0 :              ? gnupg_module_name (gc_backend[backend].module_name)
    2007           0 :              : gc_backend[backend].program );
    2008           0 :   argv[0] = "--gpgconf-list";
    2009           0 :   argv[1] = NULL;
    2010             : 
    2011           0 :   err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0,
    2012             :                              NULL, &outfp, NULL, &pid);
    2013           0 :   if (err)
    2014             :     {
    2015           0 :       gc_error (1, 0, "could not gather active options from '%s': %s",
    2016             :                 pgmname, gpg_strerror (err));
    2017             :     }
    2018             : 
    2019           0 :   while ((length = es_read_line (outfp, &line, &line_len, NULL)) > 0)
    2020             :     {
    2021             :       gc_option_t *option;
    2022             :       char *linep;
    2023           0 :       unsigned long flags = 0;
    2024           0 :       char *default_value = NULL;
    2025             : 
    2026             :       /* Strip newline and carriage return, if present.  */
    2027           0 :       while (length > 0
    2028           0 :              && (line[length - 1] == '\n' || line[length - 1] == '\r'))
    2029           0 :         line[--length] = '\0';
    2030             : 
    2031           0 :       linep = strchr (line, ':');
    2032           0 :       if (linep)
    2033           0 :         *(linep++) = '\0';
    2034             : 
    2035             :       /* Extract additional flags.  Default to none.  */
    2036           0 :       if (linep)
    2037             :         {
    2038             :           char *end;
    2039             :           char *tail;
    2040             : 
    2041           0 :           end = strchr (linep, ':');
    2042           0 :           if (end)
    2043           0 :             *(end++) = '\0';
    2044             : 
    2045           0 :           gpg_err_set_errno (0);
    2046           0 :           flags = strtoul (linep, &tail, 0);
    2047           0 :           if (errno)
    2048           0 :             gc_error (1, errno, "malformed flags in option %s from %s",
    2049             :                       line, pgmname);
    2050           0 :           if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
    2051           0 :             gc_error (1, 0, "garbage after flags in option %s from %s",
    2052             :                       line, pgmname);
    2053             : 
    2054           0 :           linep = end;
    2055             :         }
    2056             : 
    2057             :       /* Extract default value, if present.  Default to empty if
    2058             :          not.  */
    2059           0 :       if (linep)
    2060             :         {
    2061             :           char *end;
    2062             : 
    2063           0 :           end = strchr (linep, ':');
    2064           0 :           if (end)
    2065           0 :             *(end++) = '\0';
    2066             : 
    2067           0 :           if (flags & GC_OPT_FLAG_DEFAULT)
    2068           0 :             default_value = linep;
    2069             : 
    2070           0 :           linep = end;
    2071             :         }
    2072             : 
    2073             :       /* Look up the option in the component and install the
    2074             :          configuration data.  */
    2075           0 :       option = find_option (component, line, backend);
    2076           0 :       if (option)
    2077             :         {
    2078           0 :           if (option->active)
    2079           0 :             gc_error (1, errno, "option %s returned twice from %s",
    2080             :                       line, pgmname);
    2081           0 :           option->active = 1;
    2082             : 
    2083           0 :           option->flags |= flags;
    2084           0 :           if (default_value && *default_value)
    2085           0 :             option->default_value = xstrdup (default_value);
    2086             :         }
    2087             :     }
    2088           0 :   if (length < 0 || es_ferror (outfp))
    2089           0 :     gc_error (1, errno, "error reading from %s", pgmname);
    2090           0 :   if (es_fclose (outfp))
    2091           0 :     gc_error (1, errno, "error closing %s", pgmname);
    2092             : 
    2093           0 :   err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
    2094           0 :   if (err)
    2095           0 :     gc_error (1, 0, "running %s failed (exitcode=%d): %s",
    2096             :               pgmname, exitcode, gpg_strerror (err));
    2097           0 :   gnupg_release_process (pid);
    2098             : 
    2099             : 
    2100             :   /* At this point, we can parse the configuration file.  */
    2101           0 :   config_filename = get_config_filename (component, backend);
    2102             : 
    2103           0 :   config = es_fopen (config_filename, "r");
    2104           0 :   if (!config)
    2105           0 :     gc_error (0, errno, "warning: can not open config file %s",
    2106             :               config_filename);
    2107             :   else
    2108             :     {
    2109           0 :       while ((length = es_read_line (config, &line, &line_len, NULL)) > 0)
    2110             :         {
    2111             :           char *name;
    2112             :           char *value;
    2113             :           gc_option_t *option;
    2114             : 
    2115           0 :           name = line;
    2116           0 :           while (*name == ' ' || *name == '\t')
    2117           0 :             name++;
    2118           0 :           if (!*name || *name == '#' || *name == '\r' || *name == '\n')
    2119           0 :             continue;
    2120             : 
    2121           0 :           value = name;
    2122           0 :           while (*value && *value != ' ' && *value != '\t'
    2123           0 :                  && *value != '#' && *value != '\r' && *value != '\n')
    2124           0 :             value++;
    2125           0 :           if (*value == ' ' || *value == '\t')
    2126           0 :             {
    2127             :               char *end;
    2128             : 
    2129           0 :               *(value++) = '\0';
    2130           0 :               while (*value == ' ' || *value == '\t')
    2131           0 :                 value++;
    2132             : 
    2133           0 :               end = value;
    2134           0 :               while (*end && *end != '#' && *end != '\r' && *end != '\n')
    2135           0 :                 end++;
    2136           0 :               while (end > value && (end[-1] == ' ' || end[-1] == '\t'))
    2137           0 :                 end--;
    2138           0 :               *end = '\0';
    2139             :             }
    2140             :           else
    2141           0 :             *value = '\0';
    2142             : 
    2143             :           /* Look up the option in the component and install the
    2144             :              configuration data.  */
    2145           0 :           option = find_option (component, line, backend);
    2146           0 :           if (option)
    2147             :             {
    2148             :               char *opt_value;
    2149             : 
    2150           0 :               if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
    2151             :                 {
    2152           0 :                   if (*value)
    2153           0 :                     gc_error (0, 0,
    2154             :                               "warning: ignoring argument %s for option %s",
    2155             :                               value, name);
    2156           0 :                   opt_value = xstrdup ("1");
    2157             :                 }
    2158           0 :               else if (gc_arg_type[option->arg_type].fallback
    2159             :                        == GC_ARG_TYPE_STRING)
    2160           0 :                 opt_value = xasprintf ("\"%s", gc_percent_escape (value));
    2161             :               else
    2162             :                 {
    2163             :                   /* FIXME: Verify that the number is sane.  */
    2164           0 :                   opt_value = xstrdup (value);
    2165             :                 }
    2166             : 
    2167             :               /* Now enter the option into the table.  */
    2168           0 :               if (!(option->flags & GC_OPT_FLAG_LIST))
    2169             :                 {
    2170           0 :                   if (option->value)
    2171           0 :                     free (option->value);
    2172           0 :                   option->value = opt_value;
    2173             :                 }
    2174             :               else
    2175             :                 {
    2176           0 :                   if (!option->value)
    2177           0 :                     option->value = opt_value;
    2178             :                   else
    2179             :                     {
    2180           0 :                       char *opt_val = opt_value;
    2181             : 
    2182           0 :                       option->value = xasprintf ("%s,%s", option->value,
    2183             :                                                  opt_val);
    2184           0 :                       xfree (opt_value);
    2185             :                     }
    2186             :                 }
    2187             :             }
    2188             :         }
    2189             : 
    2190           0 :       if (length < 0 || es_ferror (config))
    2191           0 :         gc_error (1, errno, "error reading from %s", config_filename);
    2192           0 :       if (es_fclose (config))
    2193           0 :         gc_error (1, errno, "error closing %s", config_filename);
    2194             :     }
    2195             : 
    2196           0 :   xfree (line);
    2197           0 : }
    2198             : 
    2199             : 
    2200             : /* Retrieve the options for the component COMPONENT from backend
    2201             :    BACKEND, which we already know is of type file list.  */
    2202             : static void
    2203           0 : retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
    2204             : {
    2205             :   gc_option_t *list_option;
    2206             :   gc_option_t *config_option;
    2207             :   char *list_filename;
    2208             :   FILE *list_file;
    2209           0 :   char *line = NULL;
    2210           0 :   size_t line_len = 0;
    2211             :   ssize_t length;
    2212           0 :   char *list = NULL;
    2213             : 
    2214           0 :   list_option = find_option (component,
    2215             :                              gc_backend[backend].option_name, GC_BACKEND_ANY);
    2216           0 :   assert (list_option);
    2217           0 :   assert (!list_option->active);
    2218             : 
    2219           0 :   list_filename = get_config_filename (component, backend);
    2220           0 :   list_file = fopen (list_filename, "r");
    2221           0 :   if (!list_file)
    2222           0 :     gc_error (0, errno, "warning: can not open list file %s", list_filename);
    2223             :   else
    2224             :     {
    2225             : 
    2226           0 :       while ((length = read_line (list_file, &line, &line_len, NULL)) > 0)
    2227             :         {
    2228             :           char *start;
    2229             :           char *end;
    2230             :           char *new_list;
    2231             : 
    2232           0 :           start = line;
    2233           0 :           while (*start == ' ' || *start == '\t')
    2234           0 :             start++;
    2235           0 :           if (!*start || *start == '#' || *start == '\r' || *start == '\n')
    2236           0 :             continue;
    2237             : 
    2238           0 :           end = start;
    2239           0 :           while (*end && *end != '#' && *end != '\r' && *end != '\n')
    2240           0 :             end++;
    2241             :           /* Walk back to skip trailing white spaces.  Looks evil, but
    2242             :              works because of the conditions on START and END imposed
    2243             :              at this point (END is at least START + 1, and START is
    2244             :              not a whitespace character).  */
    2245           0 :           while (*(end - 1) == ' ' || *(end - 1) == '\t')
    2246           0 :             end--;
    2247           0 :           *end = '\0';
    2248             :           /* FIXME: Oh, no!  This is so lame!  Should use realloc and
    2249             :              really append.  */
    2250           0 :           if (list)
    2251             :             {
    2252           0 :               new_list = xasprintf ("%s,\"%s", list, gc_percent_escape (start));
    2253           0 :               xfree (list);
    2254           0 :               list = new_list;
    2255             :             }
    2256             :           else
    2257           0 :             list = xasprintf ("\"%s", gc_percent_escape (start));
    2258             :         }
    2259           0 :       if (length < 0 || ferror (list_file))
    2260           0 :         gc_error (1, errno, "can not read list file %s", list_filename);
    2261             :     }
    2262             : 
    2263           0 :   list_option->active = 1;
    2264           0 :   list_option->value = list;
    2265             : 
    2266             :   /* Fix up the read-only flag.  */
    2267           0 :   config_option = find_option
    2268             :     (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
    2269           0 :   if (config_option->flags & GC_OPT_FLAG_NO_CHANGE)
    2270           0 :     list_option->flags |= GC_OPT_FLAG_NO_CHANGE;
    2271             : 
    2272           0 :   if (list_file && fclose (list_file))
    2273           0 :     gc_error (1, errno, "error closing %s", list_filename);
    2274           0 :   xfree (line);
    2275           0 : }
    2276             : 
    2277             : 
    2278             : /* Retrieve the currently active options and their defaults from all
    2279             :    involved backends for this component.  Using -1 for component will
    2280             :    retrieve all options from all components. */
    2281             : void
    2282           0 : gc_component_retrieve_options (int component)
    2283             : {
    2284           0 :   int process_all = 0;
    2285             :   int backend_seen[GC_BACKEND_NR];
    2286             :   gc_backend_t backend;
    2287             :   gc_option_t *option;
    2288             : 
    2289           0 :   if (component == GC_COMPONENT_PINENTRY)
    2290           0 :     return; /* Dummy module for now.  */
    2291             : 
    2292           0 :   for (backend = 0; backend < GC_BACKEND_NR; backend++)
    2293           0 :     backend_seen[backend] = 0;
    2294             : 
    2295           0 :   if (component == -1)
    2296             :     {
    2297           0 :       process_all = 1;
    2298           0 :       component = 0;
    2299           0 :       assert (component < GC_COMPONENT_NR);
    2300             :     }
    2301             : 
    2302             :   do
    2303             :     {
    2304           0 :       option = gc_component[component].options;
    2305             : 
    2306           0 :       while (option && option->name)
    2307             :         {
    2308           0 :           if (!(option->flags & GC_OPT_FLAG_GROUP))
    2309             :             {
    2310           0 :               backend = option->backend;
    2311             : 
    2312           0 :               if (backend_seen[backend])
    2313             :                 {
    2314           0 :                   option++;
    2315           0 :                   continue;
    2316             :                 }
    2317           0 :               backend_seen[backend] = 1;
    2318             : 
    2319           0 :               assert (backend != GC_BACKEND_ANY);
    2320             : 
    2321           0 :               if (gc_backend[backend].program)
    2322           0 :                 retrieve_options_from_program (component, backend);
    2323             :               else
    2324           0 :                 retrieve_options_from_file (component, backend);
    2325             :             }
    2326           0 :           option++;
    2327             :         }
    2328             :     }
    2329           0 :   while (process_all && ++component < GC_COMPONENT_NR);
    2330             : 
    2331             : }
    2332             : 
    2333             : 
    2334             : 
    2335             : /* Perform a simple validity check based on the type.  Return in
    2336             :    NEW_VALUE_NR the value of the number in NEW_VALUE if OPTION is of
    2337             :    type GC_ARG_TYPE_NONE.  */
    2338             : static void
    2339           0 : option_check_validity (gc_option_t *option, unsigned long flags,
    2340             :                        char *new_value, unsigned long *new_value_nr)
    2341             : {
    2342             :   char *arg;
    2343             : 
    2344           0 :   if (!option->active)
    2345           0 :     gc_error (1, 0, "option %s not supported by backend %s",
    2346           0 :               option->name, gc_backend[option->backend].name);
    2347             : 
    2348           0 :   if (option->new_flags || option->new_value)
    2349           0 :     gc_error (1, 0, "option %s already changed", option->name);
    2350             : 
    2351           0 :   if (flags & GC_OPT_FLAG_DEFAULT)
    2352             :     {
    2353           0 :       if (*new_value)
    2354           0 :         gc_error (1, 0, "argument %s provided for deleted option %s",
    2355             :                   new_value, option->name);
    2356             : 
    2357           0 :       return;
    2358             :     }
    2359             : 
    2360             :   /* GC_ARG_TYPE_NONE options have special list treatment.  */
    2361           0 :   if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
    2362             :     {
    2363             :       char *tail;
    2364             : 
    2365           0 :       gpg_err_set_errno (0);
    2366           0 :       *new_value_nr = strtoul (new_value, &tail, 0);
    2367             : 
    2368           0 :       if (errno)
    2369           0 :         gc_error (1, errno, "invalid argument for option %s",
    2370             :                   option->name);
    2371           0 :       if (*tail)
    2372           0 :         gc_error (1, 0, "garbage after argument for option %s",
    2373             :                       option->name);
    2374             : 
    2375           0 :       if (!(option->flags & GC_OPT_FLAG_LIST))
    2376             :         {
    2377           0 :           if (*new_value_nr != 1)
    2378           0 :             gc_error (1, 0, "argument for non-list option %s of type 0 "
    2379             :                       "(none) must be 1", option->name);
    2380             :         }
    2381             :       else
    2382             :         {
    2383           0 :           if (*new_value_nr == 0)
    2384           0 :             gc_error (1, 0, "argument for option %s of type 0 (none) "
    2385             :                       "must be positive", option->name);
    2386             :         }
    2387             : 
    2388           0 :       return;
    2389             :     }
    2390             : 
    2391           0 :   arg = new_value;
    2392             :   do
    2393             :     {
    2394           0 :       if (*arg == '\0' || *arg == ',')
    2395             :         {
    2396           0 :           if (!(option->flags & GC_OPT_FLAG_ARG_OPT))
    2397           0 :             gc_error (1, 0, "argument required for option %s", option->name);
    2398             : 
    2399           0 :           if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST))
    2400           0 :             gc_error (1, 0, "list found for non-list option %s", option->name);
    2401             :         }
    2402           0 :       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
    2403             :         {
    2404           0 :           if (*arg != '"')
    2405           0 :             gc_error (1, 0, "string argument for option %s must begin "
    2406             :                       "with a quote (\") character", option->name);
    2407             : 
    2408             :           /* FIXME: We do not allow empty string arguments for now, as
    2409             :              we do not quote arguments in configuration files, and
    2410             :              thus no argument is indistinguishable from the empty
    2411             :              string.  */
    2412           0 :           if (arg[1] == '\0' || arg[1] == ',')
    2413           0 :             gc_error (1, 0, "empty string argument for option %s is "
    2414             :                       "currently not allowed.  Please report this!",
    2415             :                       option->name);
    2416             :         }
    2417           0 :       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
    2418             :         {
    2419             :           long res;
    2420             : 
    2421           0 :           gpg_err_set_errno (0);
    2422           0 :           res = strtol (arg, &arg, 0);
    2423             :           (void) res;
    2424             : 
    2425           0 :           if (errno)
    2426           0 :             gc_error (1, errno, "invalid argument for option %s",
    2427             :                       option->name);
    2428             : 
    2429           0 :           if (*arg != '\0' && *arg != ',')
    2430           0 :             gc_error (1, 0, "garbage after argument for option %s",
    2431             :                       option->name);
    2432             :         }
    2433           0 :       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_UINT32)
    2434             :         {
    2435             :           unsigned long res;
    2436             : 
    2437           0 :           gpg_err_set_errno (0);
    2438           0 :           res = strtoul (arg, &arg, 0);
    2439             :           (void) res;
    2440             : 
    2441           0 :           if (errno)
    2442           0 :             gc_error (1, errno, "invalid argument for option %s",
    2443             :                       option->name);
    2444             : 
    2445           0 :           if (*arg != '\0' && *arg != ',')
    2446           0 :             gc_error (1, 0, "garbage after argument for option %s",
    2447             :                       option->name);
    2448             :         }
    2449           0 :       arg = strchr (arg, ',');
    2450           0 :       if (arg)
    2451           0 :         arg++;
    2452             :     }
    2453           0 :   while (arg && *arg);
    2454             : }
    2455             : 
    2456             : #ifdef HAVE_W32_SYSTEM
    2457             : int
    2458             : copy_file (const char *src_name, const char *dst_name)
    2459             : {
    2460             : #define BUF_LEN 4096
    2461             :   char buffer[BUF_LEN];
    2462             :   int len;
    2463             :   FILE *src;
    2464             :   FILE *dst;
    2465             : 
    2466             :   src = fopen (src_name, "r");
    2467             :   if (src == NULL)
    2468             :     return -1;
    2469             : 
    2470             :   dst = fopen (dst_name, "w");
    2471             :   if (dst == NULL)
    2472             :     {
    2473             :       int saved_err = errno;
    2474             :       fclose (src);
    2475             :       gpg_err_set_errno (saved_err);
    2476             :       return -1;
    2477             :     }
    2478             : 
    2479             :   do
    2480             :     {
    2481             :       int written;
    2482             : 
    2483             :       len = fread (buffer, 1, BUF_LEN, src);
    2484             :       if (len == 0)
    2485             :         break;
    2486             :       written = fwrite (buffer, 1, len, dst);
    2487             :       if (written != len)
    2488             :         break;
    2489             :     }
    2490             :   while (!feof (src) && !ferror (src) && !ferror (dst));
    2491             : 
    2492             :   if (ferror (src) || ferror (dst) || !feof (src))
    2493             :     {
    2494             :       int saved_errno = errno;
    2495             :       fclose (src);
    2496             :       fclose (dst);
    2497             :       unlink (dst_name);
    2498             :       gpg_err_set_errno (saved_errno);
    2499             :       return -1;
    2500             :     }
    2501             : 
    2502             :   if (fclose (dst))
    2503             :     gc_error (1, errno, "error closing %s", dst_name);
    2504             :   if (fclose (src))
    2505             :     gc_error (1, errno, "error closing %s", src_name);
    2506             : 
    2507             :   return 0;
    2508             : }
    2509             : #endif /* HAVE_W32_SYSTEM */
    2510             : 
    2511             : 
    2512             : /* Create and verify the new configuration file for the specified
    2513             :    backend and component.  Returns 0 on success and -1 on error.  */
    2514             : static int
    2515           0 : change_options_file (gc_component_t component, gc_backend_t backend,
    2516             :                      char **src_filenamep, char **dest_filenamep,
    2517             :                      char **orig_filenamep)
    2518             : {
    2519             :   static const char marker[] = "###+++--- " GPGCONF_DISP_NAME " ---+++###";
    2520             :   /* True if we are within the marker in the config file.  */
    2521           0 :   int in_marker = 0;
    2522             :   gc_option_t *option;
    2523           0 :   char *line = NULL;
    2524             :   size_t line_len;
    2525             :   ssize_t length;
    2526             :   int res;
    2527             :   int fd;
    2528           0 :   FILE *src_file = NULL;
    2529           0 :   FILE *dest_file = NULL;
    2530             :   char *src_filename;
    2531             :   char *dest_filename;
    2532             :   char *orig_filename;
    2533             :   char *arg;
    2534           0 :   char *cur_arg = NULL;
    2535             : 
    2536           0 :   option = find_option (component,
    2537             :                         gc_backend[backend].option_name, GC_BACKEND_ANY);
    2538           0 :   assert (option);
    2539           0 :   assert (option->active);
    2540           0 :   assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE);
    2541             : 
    2542             :   /* FIXME.  Throughout the function, do better error reporting.  */
    2543             :   /* Note that get_config_filename() calls percent_deescape(), so we
    2544             :      call this before processing the arguments.  */
    2545           0 :   dest_filename = xstrdup (get_config_filename (component, backend));
    2546           0 :   src_filename = xasprintf ("%s.%s.%i.new",
    2547             :                             dest_filename, GPGCONF_NAME, (int)getpid ());
    2548           0 :   orig_filename = xasprintf ("%s.%s.%i.bak",
    2549             :                              dest_filename, GPGCONF_NAME, (int)getpid ());
    2550             : 
    2551           0 :   arg = option->new_value;
    2552           0 :   if (arg && arg[0] == '\0')
    2553           0 :     arg = NULL;
    2554           0 :   else if (arg)
    2555             :     {
    2556             :       char *end;
    2557             : 
    2558           0 :       arg++;
    2559           0 :       end = strchr (arg, ',');
    2560           0 :       if (end)
    2561           0 :         *end = '\0';
    2562             : 
    2563           0 :       cur_arg = percent_deescape (arg);
    2564           0 :       if (end)
    2565             :         {
    2566           0 :           *end = ',';
    2567           0 :           arg = end + 1;
    2568             :         }
    2569             :       else
    2570           0 :         arg = NULL;
    2571             :     }
    2572             : 
    2573             : #ifdef HAVE_W32_SYSTEM
    2574             :   res = copy_file (dest_filename, orig_filename);
    2575             : #else
    2576           0 :   res = link (dest_filename, orig_filename);
    2577             : #endif
    2578           0 :   if (res < 0 && errno != ENOENT)
    2579             :     {
    2580           0 :       xfree (dest_filename);
    2581           0 :       return -1;
    2582             :     }
    2583           0 :   if (res < 0)
    2584             :     {
    2585           0 :       xfree (orig_filename);
    2586           0 :       orig_filename = NULL;
    2587             :     }
    2588             : 
    2589             :   /* We now initialize the return strings, so the caller can do the
    2590             :      cleanup for us.  */
    2591           0 :   *src_filenamep = src_filename;
    2592           0 :   *dest_filenamep = dest_filename;
    2593           0 :   *orig_filenamep = orig_filename;
    2594             : 
    2595             :   /* Use open() so that we can use O_EXCL.  */
    2596           0 :   fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
    2597           0 :   if (fd < 0)
    2598           0 :     return -1;
    2599           0 :   src_file = fdopen (fd, "w");
    2600           0 :   res = errno;
    2601           0 :   if (!src_file)
    2602             :     {
    2603           0 :       gpg_err_set_errno (res);
    2604           0 :       return -1;
    2605             :     }
    2606             : 
    2607             :   /* Only if ORIG_FILENAME is not NULL did the configuration file
    2608             :      exist already.  In this case, we will copy its content into the
    2609             :      new configuration file, changing it to our liking in the
    2610             :      process.  */
    2611           0 :   if (orig_filename)
    2612             :     {
    2613           0 :       dest_file = fopen (dest_filename, "r");
    2614           0 :       if (!dest_file)
    2615           0 :         goto change_file_one_err;
    2616             : 
    2617           0 :       while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
    2618             :         {
    2619           0 :           int disable = 0;
    2620             :           char *start;
    2621             : 
    2622           0 :           if (!strncmp (marker, line, sizeof (marker) - 1))
    2623             :             {
    2624           0 :               if (!in_marker)
    2625           0 :                 in_marker = 1;
    2626             :               else
    2627           0 :                 break;
    2628             :             }
    2629             : 
    2630           0 :           start = line;
    2631           0 :           while (*start == ' ' || *start == '\t')
    2632           0 :             start++;
    2633           0 :           if (*start && *start != '\r' && *start != '\n' && *start != '#')
    2634             :             {
    2635             :               char *end;
    2636             :               char *endp;
    2637             :               char saved_end;
    2638             : 
    2639           0 :               endp = start;
    2640           0 :               end = endp;
    2641             : 
    2642             :               /* Search for the end of the line.  */
    2643           0 :               while (*endp && *endp != '#' && *endp != '\r' && *endp != '\n')
    2644             :                 {
    2645           0 :                   endp++;
    2646           0 :                   if (*endp && *endp != ' ' && *endp != '\t'
    2647           0 :                       && *endp != '\r' && *endp != '\n' && *endp != '#')
    2648           0 :                     end = endp + 1;
    2649             :                 }
    2650           0 :               saved_end = *end;
    2651           0 :               *end = '\0';
    2652             : 
    2653           0 :               if ((option->new_flags & GC_OPT_FLAG_DEFAULT)
    2654           0 :                   || !cur_arg || strcmp (start, cur_arg))
    2655           0 :                 disable = 1;
    2656             :               else
    2657             :                 {
    2658             :                   /* Find next argument.  */
    2659           0 :                   if (arg)
    2660             :                     {
    2661             :                       char *arg_end;
    2662             : 
    2663           0 :                       arg++;
    2664           0 :                       arg_end = strchr (arg, ',');
    2665           0 :                       if (arg_end)
    2666           0 :                         *arg_end = '\0';
    2667             : 
    2668           0 :                       cur_arg = percent_deescape (arg);
    2669           0 :                       if (arg_end)
    2670             :                         {
    2671           0 :                           *arg_end = ',';
    2672           0 :                           arg = arg_end + 1;
    2673             :                         }
    2674             :                       else
    2675           0 :                         arg = NULL;
    2676             :                     }
    2677             :                   else
    2678           0 :                     cur_arg = NULL;
    2679             :                 }
    2680             : 
    2681           0 :               *end = saved_end;
    2682             :             }
    2683             : 
    2684           0 :           if (disable)
    2685             :             {
    2686           0 :               if (!in_marker)
    2687             :                 {
    2688           0 :                   fprintf (src_file,
    2689             :                            "# %s disabled this option here at %s\n",
    2690           0 :                            GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ()));
    2691           0 :                   if (ferror (src_file))
    2692           0 :                     goto change_file_one_err;
    2693           0 :                   fprintf (src_file, "# %s", line);
    2694           0 :                   if (ferror (src_file))
    2695           0 :                     goto change_file_one_err;
    2696             :                 }
    2697             :             }
    2698             :           else
    2699             :             {
    2700           0 :               fprintf (src_file, "%s", line);
    2701           0 :               if (ferror (src_file))
    2702           0 :                 goto change_file_one_err;
    2703             :             }
    2704             :         }
    2705           0 :       if (length < 0 || ferror (dest_file))
    2706             :         goto change_file_one_err;
    2707             :     }
    2708             : 
    2709           0 :   if (!in_marker)
    2710             :     {
    2711             :       /* There was no marker.  This is the first time we edit the
    2712             :          file.  We add our own marker at the end of the file and
    2713             :          proceed.  Note that we first write a newline, this guards us
    2714             :          against files which lack the newline at the end of the last
    2715             :          line, while it doesn't hurt us in all other cases.  */
    2716           0 :       fprintf (src_file, "\n%s\n", marker);
    2717           0 :       if (ferror (src_file))
    2718           0 :         goto change_file_one_err;
    2719             :     }
    2720             : 
    2721             :   /* At this point, we have copied everything up to the end marker
    2722             :      into the new file, except for the arguments we are going to add.
    2723             :      Now, dump the new arguments and write the end marker, possibly
    2724             :      followed by the rest of the original file.  */
    2725           0 :   while (cur_arg)
    2726             :     {
    2727           0 :       fprintf (src_file, "%s\n", cur_arg);
    2728             : 
    2729             :       /* Find next argument.  */
    2730           0 :       if (arg)
    2731             :         {
    2732             :           char *end;
    2733             : 
    2734           0 :           arg++;
    2735           0 :           end = strchr (arg, ',');
    2736           0 :           if (end)
    2737           0 :             *end = '\0';
    2738             : 
    2739           0 :           cur_arg = percent_deescape (arg);
    2740           0 :           if (end)
    2741             :             {
    2742           0 :               *end = ',';
    2743           0 :               arg = end + 1;
    2744             :             }
    2745             :           else
    2746           0 :             arg = NULL;
    2747             :         }
    2748             :       else
    2749           0 :         cur_arg = NULL;
    2750             :     }
    2751             : 
    2752           0 :   fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
    2753           0 :   if (ferror (src_file))
    2754           0 :     goto change_file_one_err;
    2755             : 
    2756           0 :   if (!in_marker)
    2757             :     {
    2758           0 :       fprintf (src_file, "# %s edited this configuration file.\n",
    2759             :                GPGCONF_DISP_NAME);
    2760           0 :       if (ferror (src_file))
    2761           0 :         goto change_file_one_err;
    2762           0 :       fprintf (src_file, "# It will disable options before this marked "
    2763             :                "block, but it will\n");
    2764           0 :       if (ferror (src_file))
    2765           0 :         goto change_file_one_err;
    2766           0 :       fprintf (src_file, "# never change anything below these lines.\n");
    2767           0 :       if (ferror (src_file))
    2768           0 :         goto change_file_one_err;
    2769             :     }
    2770           0 :   if (dest_file)
    2771             :     {
    2772           0 :       while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
    2773             :         {
    2774           0 :           fprintf (src_file, "%s", line);
    2775           0 :           if (ferror (src_file))
    2776           0 :             goto change_file_one_err;
    2777             :         }
    2778           0 :       if (length < 0 || ferror (dest_file))
    2779             :         goto change_file_one_err;
    2780             :     }
    2781           0 :   xfree (line);
    2782           0 :   line = NULL;
    2783             : 
    2784           0 :   res = fclose (src_file);
    2785           0 :   if (res)
    2786             :     {
    2787           0 :       res = errno;
    2788           0 :       close (fd);
    2789           0 :       if (dest_file)
    2790           0 :         fclose (dest_file);
    2791           0 :       gpg_err_set_errno (res);
    2792           0 :       return -1;
    2793             :     }
    2794           0 :   close (fd);
    2795           0 :   if (dest_file)
    2796             :     {
    2797           0 :       res = fclose (dest_file);
    2798           0 :       if (res)
    2799           0 :         return -1;
    2800             :     }
    2801           0 :   return 0;
    2802             : 
    2803             :  change_file_one_err:
    2804           0 :   xfree (line);
    2805           0 :   res = errno;
    2806           0 :   if (src_file)
    2807             :     {
    2808           0 :       fclose (src_file);
    2809           0 :       close (fd);
    2810             :     }
    2811           0 :   if (dest_file)
    2812           0 :     fclose (dest_file);
    2813           0 :   gpg_err_set_errno (res);
    2814           0 :   return -1;
    2815             : }
    2816             : 
    2817             : 
    2818             : /* Create and verify the new configuration file for the specified
    2819             :    backend and component.  Returns 0 on success and -1 on error.  */
    2820             : static int
    2821           0 : change_options_program (gc_component_t component, gc_backend_t backend,
    2822             :                         char **src_filenamep, char **dest_filenamep,
    2823             :                         char **orig_filenamep)
    2824             : {
    2825             :   static const char marker[] = "###+++--- " GPGCONF_DISP_NAME " ---+++###";
    2826             :   /* True if we are within the marker in the config file.  */
    2827           0 :   int in_marker = 0;
    2828             :   gc_option_t *option;
    2829           0 :   char *line = NULL;
    2830             :   size_t line_len;
    2831             :   ssize_t length;
    2832             :   int res;
    2833             :   int fd;
    2834           0 :   FILE *src_file = NULL;
    2835           0 :   FILE *dest_file = NULL;
    2836             :   char *src_filename;
    2837             :   char *dest_filename;
    2838             :   char *orig_filename;
    2839             :   /* Special hack for gpg, see below.  */
    2840           0 :   int utf8strings_seen = 0;
    2841             : 
    2842             :   /* FIXME.  Throughout the function, do better error reporting.  */
    2843           0 :   dest_filename = xstrdup (get_config_filename (component, backend));
    2844           0 :   src_filename = xasprintf ("%s.%s.%i.new",
    2845             :                             dest_filename, GPGCONF_NAME, (int)getpid ());
    2846           0 :   orig_filename = xasprintf ("%s.%s.%i.bak",
    2847             :                              dest_filename, GPGCONF_NAME, (int)getpid ());
    2848             : 
    2849             : #ifdef HAVE_W32_SYSTEM
    2850             :   res = copy_file (dest_filename, orig_filename);
    2851             : #else
    2852           0 :   res = link (dest_filename, orig_filename);
    2853             : #endif
    2854           0 :   if (res < 0 && errno != ENOENT)
    2855           0 :     return -1;
    2856           0 :   if (res < 0)
    2857             :     {
    2858           0 :       xfree (orig_filename);
    2859           0 :       orig_filename = NULL;
    2860             :     }
    2861             : 
    2862             :   /* We now initialize the return strings, so the caller can do the
    2863             :      cleanup for us.  */
    2864           0 :   *src_filenamep = src_filename;
    2865           0 :   *dest_filenamep = dest_filename;
    2866           0 :   *orig_filenamep = orig_filename;
    2867             : 
    2868             :   /* Use open() so that we can use O_EXCL.  */
    2869           0 :   fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
    2870           0 :   if (fd < 0)
    2871           0 :     return -1;
    2872           0 :   src_file = fdopen (fd, "w");
    2873           0 :   res = errno;
    2874           0 :   if (!src_file)
    2875             :     {
    2876           0 :       gpg_err_set_errno (res);
    2877           0 :       return -1;
    2878             :     }
    2879             : 
    2880             :   /* Only if ORIG_FILENAME is not NULL did the configuration file
    2881             :      exist already.  In this case, we will copy its content into the
    2882             :      new configuration file, changing it to our liking in the
    2883             :      process.  */
    2884           0 :   if (orig_filename)
    2885             :     {
    2886           0 :       dest_file = fopen (dest_filename, "r");
    2887           0 :       if (!dest_file)
    2888           0 :         goto change_one_err;
    2889             : 
    2890           0 :       while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
    2891             :         {
    2892           0 :           int disable = 0;
    2893             :           char *start;
    2894             : 
    2895           0 :           if (!strncmp (marker, line, sizeof (marker) - 1))
    2896             :             {
    2897           0 :               if (!in_marker)
    2898           0 :                 in_marker = 1;
    2899             :               else
    2900           0 :                 break;
    2901             :             }
    2902           0 :           else if (backend == GC_BACKEND_GPG && in_marker
    2903           0 :                    && ! strcmp ("utf8-strings\n", line))
    2904             :             {
    2905             :               /* Strip duplicated entries.  */
    2906           0 :               if (utf8strings_seen)
    2907           0 :                 disable = 1;
    2908             :               else
    2909           0 :                 utf8strings_seen = 1;
    2910             :             }
    2911             : 
    2912           0 :           start = line;
    2913           0 :           while (*start == ' ' || *start == '\t')
    2914           0 :             start++;
    2915           0 :           if (*start && *start != '\r' && *start != '\n' && *start != '#')
    2916             :             {
    2917             :               char *end;
    2918             :               char saved_end;
    2919             : 
    2920           0 :               end = start;
    2921           0 :               while (*end && *end != ' ' && *end != '\t'
    2922           0 :                      && *end != '\r' && *end != '\n' && *end != '#')
    2923           0 :                 end++;
    2924           0 :               saved_end = *end;
    2925           0 :               *end = '\0';
    2926             : 
    2927           0 :               option = find_option (component, start, backend);
    2928           0 :               *end = saved_end;
    2929           0 :               if (option && ((option->new_flags & GC_OPT_FLAG_DEFAULT)
    2930           0 :                              || option->new_value))
    2931           0 :                 disable = 1;
    2932             :             }
    2933           0 :           if (disable)
    2934             :             {
    2935           0 :               if (!in_marker)
    2936             :                 {
    2937           0 :                   fprintf (src_file,
    2938             :                            "# %s disabled this option here at %s\n",
    2939           0 :                            GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ()));
    2940           0 :                   if (ferror (src_file))
    2941           0 :                     goto change_one_err;
    2942           0 :                   fprintf (src_file, "# %s", line);
    2943           0 :                   if (ferror (src_file))
    2944           0 :                     goto change_one_err;
    2945             :                 }
    2946             :             }
    2947             :           else
    2948             :             {
    2949           0 :               fprintf (src_file, "%s", line);
    2950           0 :               if (ferror (src_file))
    2951           0 :                 goto change_one_err;
    2952             :             }
    2953             :         }
    2954           0 :       if (length < 0 || ferror (dest_file))
    2955             :         goto change_one_err;
    2956             :     }
    2957             : 
    2958           0 :   if (!in_marker)
    2959             :     {
    2960             :       /* There was no marker.  This is the first time we edit the
    2961             :          file.  We add our own marker at the end of the file and
    2962             :          proceed.  Note that we first write a newline, this guards us
    2963             :          against files which lack the newline at the end of the last
    2964             :          line, while it doesn't hurt us in all other cases.  */
    2965           0 :       fprintf (src_file, "\n%s\n", marker);
    2966           0 :       if (ferror (src_file))
    2967           0 :         goto change_one_err;
    2968             :     }
    2969             :   /* At this point, we have copied everything up to the end marker
    2970             :      into the new file, except for the options we are going to change.
    2971             :      Now, dump the changed options (except for those we are going to
    2972             :      revert to their default), and write the end marker, possibly
    2973             :      followed by the rest of the original file.  */
    2974             : 
    2975             :   /* We have to turn on UTF8 strings for GnuPG.  */
    2976           0 :   if (backend == GC_BACKEND_GPG && ! utf8strings_seen)
    2977           0 :     fprintf (src_file, "utf8-strings\n");
    2978             : 
    2979           0 :   option = gc_component[component].options;
    2980           0 :   while (option->name)
    2981             :     {
    2982           0 :       if (!(option->flags & GC_OPT_FLAG_GROUP)
    2983           0 :           && option->backend == backend
    2984           0 :           && option->new_value)
    2985             :         {
    2986           0 :           char *arg = option->new_value;
    2987             : 
    2988             :           do
    2989             :             {
    2990           0 :               if (*arg == '\0' || *arg == ',')
    2991             :                 {
    2992           0 :                   fprintf (src_file, "%s\n", option->name);
    2993           0 :                   if (ferror (src_file))
    2994           0 :                     goto change_one_err;
    2995             :                 }
    2996           0 :               else if (gc_arg_type[option->arg_type].fallback
    2997             :                        == GC_ARG_TYPE_NONE)
    2998             :                 {
    2999           0 :                   assert (*arg == '1');
    3000           0 :                   fprintf (src_file, "%s\n", option->name);
    3001           0 :                   if (ferror (src_file))
    3002           0 :                     goto change_one_err;
    3003             : 
    3004           0 :                   arg++;
    3005             :                 }
    3006           0 :               else if (gc_arg_type[option->arg_type].fallback
    3007             :                        == GC_ARG_TYPE_STRING)
    3008             :                 {
    3009             :                   char *end;
    3010             : 
    3011           0 :                   assert (*arg == '"');
    3012           0 :                   arg++;
    3013             : 
    3014           0 :                   end = strchr (arg, ',');
    3015           0 :                   if (end)
    3016           0 :                     *end = '\0';
    3017             : 
    3018           0 :                   fprintf (src_file, "%s %s\n", option->name,
    3019             :                            percent_deescape (arg));
    3020           0 :                   if (ferror (src_file))
    3021           0 :                     goto change_one_err;
    3022             : 
    3023           0 :                   if (end)
    3024           0 :                     *end = ',';
    3025           0 :                   arg = end;
    3026             :                 }
    3027             :               else
    3028             :                 {
    3029             :                   char *end;
    3030             : 
    3031           0 :                   end = strchr (arg, ',');
    3032           0 :                   if (end)
    3033           0 :                     *end = '\0';
    3034             : 
    3035           0 :                   fprintf (src_file, "%s %s\n", option->name, arg);
    3036           0 :                   if (ferror (src_file))
    3037           0 :                     goto change_one_err;
    3038             : 
    3039           0 :                   if (end)
    3040           0 :                     *end = ',';
    3041           0 :                   arg = end;
    3042             :                 }
    3043             : 
    3044           0 :               assert (arg == NULL || *arg == '\0' || *arg == ',');
    3045           0 :               if (arg && *arg == ',')
    3046           0 :                 arg++;
    3047             :             }
    3048           0 :           while (arg && *arg);
    3049             :         }
    3050           0 :       option++;
    3051             :     }
    3052             : 
    3053           0 :   fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
    3054           0 :   if (ferror (src_file))
    3055           0 :     goto change_one_err;
    3056             : 
    3057           0 :   if (!in_marker)
    3058             :     {
    3059           0 :       fprintf (src_file, "# %s edited this configuration file.\n",
    3060             :                GPGCONF_DISP_NAME);
    3061           0 :       if (ferror (src_file))
    3062           0 :         goto change_one_err;
    3063           0 :       fprintf (src_file, "# It will disable options before this marked "
    3064             :                "block, but it will\n");
    3065           0 :       if (ferror (src_file))
    3066           0 :         goto change_one_err;
    3067           0 :       fprintf (src_file, "# never change anything below these lines.\n");
    3068           0 :       if (ferror (src_file))
    3069           0 :         goto change_one_err;
    3070             :     }
    3071           0 :   if (dest_file)
    3072             :     {
    3073           0 :       while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
    3074             :         {
    3075           0 :           fprintf (src_file, "%s", line);
    3076           0 :           if (ferror (src_file))
    3077           0 :             goto change_one_err;
    3078             :         }
    3079           0 :       if (length < 0 || ferror (dest_file))
    3080             :         goto change_one_err;
    3081             :     }
    3082           0 :   xfree (line);
    3083           0 :   line = NULL;
    3084             : 
    3085           0 :   res = fclose (src_file);
    3086           0 :   if (res)
    3087             :     {
    3088           0 :       res = errno;
    3089           0 :       close (fd);
    3090           0 :       if (dest_file)
    3091           0 :         fclose (dest_file);
    3092           0 :       gpg_err_set_errno (res);
    3093           0 :       return -1;
    3094             :     }
    3095           0 :   close (fd);
    3096           0 :   if (dest_file)
    3097             :     {
    3098           0 :       res = fclose (dest_file);
    3099           0 :       if (res)
    3100           0 :         return -1;
    3101             :     }
    3102           0 :   return 0;
    3103             : 
    3104             :  change_one_err:
    3105           0 :   xfree (line);
    3106           0 :   res = errno;
    3107           0 :   if (src_file)
    3108             :     {
    3109           0 :       fclose (src_file);
    3110           0 :       close (fd);
    3111             :     }
    3112           0 :   if (dest_file)
    3113           0 :     fclose (dest_file);
    3114           0 :   gpg_err_set_errno (res);
    3115           0 :   return -1;
    3116             : }
    3117             : 
    3118             : 
    3119             : /* Common code for gc_component_change_options and
    3120             :    gc_process_gpgconf_conf.  */
    3121             : static void
    3122           0 : change_one_value (gc_option_t *option, int *runtime,
    3123             :                   unsigned long flags, char *new_value)
    3124             : {
    3125           0 :   unsigned long new_value_nr = 0;
    3126             : 
    3127           0 :   option_check_validity (option, flags, new_value, &new_value_nr);
    3128             : 
    3129           0 :   if (option->flags & GC_OPT_FLAG_RUNTIME)
    3130           0 :     runtime[option->backend] = 1;
    3131             : 
    3132           0 :   option->new_flags = flags;
    3133           0 :   if (!(flags & GC_OPT_FLAG_DEFAULT))
    3134             :     {
    3135           0 :       if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
    3136           0 :           && (option->flags & GC_OPT_FLAG_LIST))
    3137           0 :         {
    3138             :           char *str;
    3139             : 
    3140             :           /* We convert the number to a list of 1's for convenient
    3141             :              list handling.  */
    3142           0 :           assert (new_value_nr > 0);
    3143           0 :           option->new_value = xmalloc ((2 * (new_value_nr - 1) + 1) + 1);
    3144           0 :           str = option->new_value;
    3145           0 :           *(str++) = '1';
    3146           0 :           while (--new_value_nr > 0)
    3147             :             {
    3148           0 :               *(str++) = ',';
    3149           0 :               *(str++) = '1';
    3150             :             }
    3151           0 :           *(str++) = '\0';
    3152             :         }
    3153             :       else
    3154           0 :         option->new_value = xstrdup (new_value);
    3155             :     }
    3156           0 : }
    3157             : 
    3158             : 
    3159             : /* Read the modifications from IN and apply them.  If IN is NULL the
    3160             :    modifications are expected to already have been set to the global
    3161             :    table. */
    3162             : void
    3163           0 : gc_component_change_options (int component, estream_t in, estream_t out)
    3164             : {
    3165           0 :   int err = 0;
    3166             :   int runtime[GC_BACKEND_NR];
    3167             :   char *src_filename[GC_BACKEND_NR];
    3168             :   char *dest_filename[GC_BACKEND_NR];
    3169             :   char *orig_filename[GC_BACKEND_NR];
    3170             :   gc_backend_t backend;
    3171             :   gc_option_t *option;
    3172           0 :   char *line = NULL;
    3173           0 :   size_t line_len = 0;
    3174             :   ssize_t length;
    3175             : 
    3176           0 :   if (component == GC_COMPONENT_PINENTRY)
    3177           0 :     return; /* Dummy component for now.  */
    3178             : 
    3179           0 :   for (backend = 0; backend < GC_BACKEND_NR; backend++)
    3180             :     {
    3181           0 :       runtime[backend] = 0;
    3182           0 :       src_filename[backend] = NULL;
    3183           0 :       dest_filename[backend] = NULL;
    3184           0 :       orig_filename[backend] = NULL;
    3185             :     }
    3186             : 
    3187           0 :   if (in)
    3188             :     {
    3189             :       /* Read options from the file IN.  */
    3190           0 :       while ((length = es_read_line (in, &line, &line_len, NULL)) > 0)
    3191             :         {
    3192             :           char *linep;
    3193           0 :           unsigned long flags = 0;
    3194           0 :           char *new_value = "";
    3195             : 
    3196             :           /* Strip newline and carriage return, if present.  */
    3197           0 :           while (length > 0
    3198           0 :                  && (line[length - 1] == '\n' || line[length - 1] == '\r'))
    3199           0 :             line[--length] = '\0';
    3200             : 
    3201           0 :           linep = strchr (line, ':');
    3202           0 :           if (linep)
    3203           0 :             *(linep++) = '\0';
    3204             : 
    3205             :           /* Extract additional flags.  Default to none.  */
    3206           0 :           if (linep)
    3207             :             {
    3208             :               char *end;
    3209             :               char *tail;
    3210             : 
    3211           0 :               end = strchr (linep, ':');
    3212           0 :               if (end)
    3213           0 :                 *(end++) = '\0';
    3214             : 
    3215           0 :               gpg_err_set_errno (0);
    3216           0 :               flags = strtoul (linep, &tail, 0);
    3217           0 :               if (errno)
    3218           0 :                 gc_error (1, errno, "malformed flags in option %s", line);
    3219           0 :               if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
    3220           0 :                 gc_error (1, 0, "garbage after flags in option %s", line);
    3221             : 
    3222           0 :               linep = end;
    3223             :             }
    3224             : 
    3225             :           /* Don't allow setting of the no change flag.  */
    3226           0 :           flags &= ~GC_OPT_FLAG_NO_CHANGE;
    3227             : 
    3228             :           /* Extract default value, if present.  Default to empty if not.  */
    3229           0 :           if (linep)
    3230             :             {
    3231             :               char *end;
    3232           0 :               end = strchr (linep, ':');
    3233           0 :               if (end)
    3234           0 :                 *(end++) = '\0';
    3235           0 :               new_value = linep;
    3236           0 :               linep = end;
    3237             :             }
    3238             : 
    3239           0 :           option = find_option (component, line, GC_BACKEND_ANY);
    3240           0 :           if (!option)
    3241           0 :             gc_error (1, 0, "unknown option %s", line);
    3242             : 
    3243           0 :           if ((option->flags & GC_OPT_FLAG_NO_CHANGE))
    3244             :             {
    3245           0 :               gc_error (0, 0, "ignoring new value for option %s",
    3246             :                         option->name);
    3247           0 :               continue;
    3248             :             }
    3249             : 
    3250           0 :           change_one_value (option, runtime, flags, new_value);
    3251             :         }
    3252             :     }
    3253             : 
    3254             :   /* Now that we have collected and locally verified the changes,
    3255             :      write them out to new configuration files, verify them
    3256             :      externally, and then commit them.  */
    3257           0 :   option = gc_component[component].options;
    3258           0 :   while (option && option->name)
    3259             :     {
    3260             :       /* Go on if we have already seen this backend, or if there is
    3261             :          nothing to do.  */
    3262           0 :       if (src_filename[option->backend]
    3263           0 :           || !(option->new_flags || option->new_value))
    3264             :         {
    3265           0 :           option++;
    3266           0 :           continue;
    3267             :         }
    3268             : 
    3269           0 :       if (gc_backend[option->backend].program)
    3270             :         {
    3271           0 :           err = change_options_program (component, option->backend,
    3272           0 :                                         &src_filename[option->backend],
    3273           0 :                                         &dest_filename[option->backend],
    3274           0 :                                         &orig_filename[option->backend]);
    3275           0 :           if (! err)
    3276             :             {
    3277             :               /* External verification.  */
    3278           0 :               err = gc_component_check_options (component, out,
    3279           0 :                                                 src_filename[option->backend]);
    3280           0 :               if (err)
    3281             :                 {
    3282           0 :                   gc_error (0, 0,
    3283           0 :                             _("External verification of component %s failed"),
    3284             :                             gc_component[component].name);
    3285           0 :                   gpg_err_set_errno (EINVAL);
    3286             :                 }
    3287             :             }
    3288             : 
    3289             :         }
    3290             :       else
    3291           0 :         err = change_options_file (component, option->backend,
    3292           0 :                                    &src_filename[option->backend],
    3293           0 :                                    &dest_filename[option->backend],
    3294           0 :                                    &orig_filename[option->backend]);
    3295             : 
    3296           0 :       if (err)
    3297           0 :         break;
    3298             : 
    3299           0 :       option++;
    3300             :     }
    3301             : 
    3302           0 :   if (! err && ! opt.dry_run)
    3303             :     {
    3304             :       int i;
    3305             : 
    3306           0 :       for (i = 0; i < GC_BACKEND_NR; i++)
    3307             :         {
    3308           0 :           if (src_filename[i])
    3309             :             {
    3310             :               /* FIXME: Make a verification here.  */
    3311             : 
    3312           0 :               assert (dest_filename[i]);
    3313             : 
    3314           0 :               if (orig_filename[i])
    3315             :                 {
    3316             : #ifdef HAVE_W32_SYSTEM
    3317             :                   /* There is no atomic update on W32.  */
    3318             :                   err = unlink (dest_filename[i]);
    3319             : #endif /* HAVE_W32_SYSTEM */
    3320           0 :                   if (!err)
    3321           0 :                     err = rename (src_filename[i], dest_filename[i]);
    3322             :                 }
    3323             :               else
    3324             :                 {
    3325             : #ifdef HAVE_W32_SYSTEM
    3326             :                   /* We skip the unlink if we expect the file not to
    3327             :                      be there.  */
    3328             :                   err = rename (src_filename[i], dest_filename[i]);
    3329             : #else /* HAVE_W32_SYSTEM */
    3330             :                   /* This is a bit safer than rename() because we
    3331             :                      expect DEST_FILENAME not to be there.  If it
    3332             :                      happens to be there, this will fail.  */
    3333           0 :                   err = link (src_filename[i], dest_filename[i]);
    3334           0 :                   if (!err)
    3335           0 :                     err = unlink (src_filename[i]);
    3336             : #endif /* !HAVE_W32_SYSTEM */
    3337             :                 }
    3338           0 :               if (err)
    3339           0 :                 break;
    3340           0 :               src_filename[i] = NULL;
    3341             :             }
    3342             :         }
    3343             :     }
    3344             : 
    3345           0 :   if (err || opt.dry_run)
    3346             :     {
    3347             :       int i;
    3348           0 :       int saved_errno = errno;
    3349             : 
    3350             :       /* An error occurred or a dry-run is requested.  */
    3351           0 :       for (i = 0; i < GC_BACKEND_NR; i++)
    3352             :         {
    3353           0 :           if (src_filename[i])
    3354             :             {
    3355             :               /* The change was not yet committed.  */
    3356           0 :               unlink (src_filename[i]);
    3357           0 :               if (orig_filename[i])
    3358           0 :                 unlink (orig_filename[i]);
    3359             :             }
    3360             :           else
    3361             :             {
    3362             :               /* The changes were already committed.  FIXME: This is a
    3363             :                  tad dangerous, as we don't know if we don't overwrite
    3364             :                  a version of the file that is even newer than the one
    3365             :                  we just installed.  */
    3366           0 :               if (orig_filename[i])
    3367             :                 {
    3368             : #ifdef HAVE_W32_SYSTEM
    3369             :                   /* There is no atomic update on W32.  */
    3370             :                   unlink (dest_filename[i]);
    3371             : #endif /* HAVE_W32_SYSTEM */
    3372           0 :                   rename (orig_filename[i], dest_filename[i]);
    3373             :                 }
    3374             :               else
    3375           0 :                 unlink (dest_filename[i]);
    3376             :             }
    3377             :         }
    3378           0 :       if (err)
    3379           0 :         gc_error (1, saved_errno, "could not commit changes");
    3380             : 
    3381             :       /* Fall-through for dry run.  */
    3382           0 :       goto leave;
    3383             :     }
    3384             : 
    3385             :   /* If it all worked, notify the daemons of the changes.  */
    3386           0 :   if (opt.runtime)
    3387           0 :     for (backend = 0; backend < GC_BACKEND_NR; backend++)
    3388             :       {
    3389           0 :         if (runtime[backend] && gc_backend[backend].runtime_change)
    3390           0 :           (*gc_backend[backend].runtime_change) (0);
    3391             :       }
    3392             : 
    3393             :   /* Move the per-process backup file into its place.  */
    3394           0 :   for (backend = 0; backend < GC_BACKEND_NR; backend++)
    3395           0 :     if (orig_filename[backend])
    3396             :       {
    3397             :         char *backup_filename;
    3398             : 
    3399           0 :         assert (dest_filename[backend]);
    3400             : 
    3401           0 :         backup_filename = xasprintf ("%s.%s.bak",
    3402             :                                      dest_filename[backend], GPGCONF_NAME);
    3403             : 
    3404             : #ifdef HAVE_W32_SYSTEM
    3405             :         /* There is no atomic update on W32.  */
    3406             :         unlink (backup_filename);
    3407             : #endif /* HAVE_W32_SYSTEM */
    3408           0 :         rename (orig_filename[backend], backup_filename);
    3409             :       }
    3410             : 
    3411             :  leave:
    3412           0 :   xfree (line);
    3413             : }
    3414             : 
    3415             : 
    3416             : /* Check whether USER matches the current user of one of its group.
    3417             :    This function may change USER.  Returns true is there is a
    3418             :    match.  */
    3419             : static int
    3420           0 : key_matches_user_or_group (char *user)
    3421             : {
    3422             :   char *group;
    3423             : 
    3424           0 :   if (*user == '*' && user[1] == 0)
    3425           0 :     return 1; /* A single asterisk matches all users.  */
    3426             : 
    3427           0 :   group = strchr (user, ':');
    3428           0 :   if (group)
    3429           0 :     *group++ = 0;
    3430             : 
    3431             : #ifdef HAVE_W32_SYSTEM
    3432             :   /* Under Windows we don't support groups. */
    3433             :   if (group && *group)
    3434             :     gc_error (0, 0, _("Note that group specifications are ignored\n"));
    3435             : #ifndef HAVE_W32CE_SYSTEM
    3436             :   if (*user)
    3437             :     {
    3438             :       static char *my_name;
    3439             : 
    3440             :       if (!my_name)
    3441             :         {
    3442             :           char tmp[1];
    3443             :           DWORD size = 1;
    3444             : 
    3445             :           GetUserNameA (tmp, &size);
    3446             :           my_name = xmalloc (size);
    3447             :           if (!GetUserNameA (my_name, &size))
    3448             :             gc_error (1,0, "error getting current user name: %s",
    3449             :                       w32_strerror (-1));
    3450             :         }
    3451             : 
    3452             :       if (!strcmp (user, my_name))
    3453             :         return 1; /* Found.  */
    3454             :     }
    3455             : #endif /*HAVE_W32CE_SYSTEM*/
    3456             : #else /*!HAVE_W32_SYSTEM*/
    3457             :   /* First check whether the user matches.  */
    3458           0 :   if (*user)
    3459             :     {
    3460             :       static char *my_name;
    3461             : 
    3462           0 :       if (!my_name)
    3463             :         {
    3464           0 :           struct passwd *pw = getpwuid ( getuid () );
    3465           0 :           if (!pw)
    3466           0 :             gc_error (1, errno, "getpwuid failed for current user");
    3467           0 :           my_name = xstrdup (pw->pw_name);
    3468             :         }
    3469           0 :       if (!strcmp (user, my_name))
    3470           0 :         return 1; /* Found.  */
    3471             :     }
    3472             : 
    3473             :   /* If that failed, check whether a group matches.  */
    3474           0 :   if (group && *group)
    3475             :     {
    3476             :       static char *my_group;
    3477             :       static char **my_supgroups;
    3478             :       int n;
    3479             : 
    3480           0 :       if (!my_group)
    3481             :         {
    3482           0 :           struct group *gr = getgrgid ( getgid () );
    3483           0 :           if (!gr)
    3484           0 :             gc_error (1, errno, "getgrgid failed for current user");
    3485           0 :           my_group = xstrdup (gr->gr_name);
    3486             :         }
    3487           0 :       if (!strcmp (group, my_group))
    3488           0 :         return 1; /* Found.  */
    3489             : 
    3490           0 :       if (!my_supgroups)
    3491             :         {
    3492             :           int ngids;
    3493             :           gid_t *gids;
    3494             : 
    3495           0 :           ngids = getgroups (0, NULL);
    3496           0 :           gids  = xcalloc (ngids+1, sizeof *gids);
    3497           0 :           ngids = getgroups (ngids, gids);
    3498           0 :           if (ngids < 0)
    3499           0 :             gc_error (1, errno, "getgroups failed for current user");
    3500           0 :           my_supgroups = xcalloc (ngids+1, sizeof *my_supgroups);
    3501           0 :           for (n=0; n < ngids; n++)
    3502             :             {
    3503           0 :               struct group *gr = getgrgid ( gids[n] );
    3504           0 :               if (!gr)
    3505           0 :                 gc_error (1, errno, "getgrgid failed for supplementary group");
    3506           0 :               my_supgroups[n] = xstrdup (gr->gr_name);
    3507             :             }
    3508           0 :           xfree (gids);
    3509             :         }
    3510             : 
    3511           0 :       for (n=0; my_supgroups[n]; n++)
    3512           0 :         if (!strcmp (group, my_supgroups[n]))
    3513           0 :           return 1; /* Found.  */
    3514             :     }
    3515             : #endif /*!HAVE_W32_SYSTEM*/
    3516           0 :   return 0; /* No match.  */
    3517             : }
    3518             : 
    3519             : 
    3520             : 
    3521             : /* Read and process the global configuration file for gpgconf.  This
    3522             :    optional file is used to update our internal tables at runtime and
    3523             :    may also be used to set new default values.  If FNAME is NULL the
    3524             :    default name will be used.  With UPDATE set to true the internal
    3525             :    tables are actually updated; if not set, only a syntax check is
    3526             :    done.  If DEFAULTS is true the global options are written to the
    3527             :    configuration files.  If LISTFP is set, no changes are done but the
    3528             :    configuration file is printed to LISTFP in a colon separated format.
    3529             : 
    3530             :    Returns 0 on success or if the config file is not present; -1 is
    3531             :    returned on error. */
    3532             : int
    3533           0 : gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
    3534             :                          estream_t listfp)
    3535             : {
    3536           0 :   int result = 0;
    3537           0 :   char *line = NULL;
    3538           0 :   size_t line_len = 0;
    3539             :   ssize_t length;
    3540             :   FILE *config;
    3541           0 :   int lineno = 0;
    3542           0 :   int in_rule = 0;
    3543           0 :   int got_match = 0;
    3544             :   int runtime[GC_BACKEND_NR];
    3545             :   int backend_id, component_id;
    3546             :   char *fname;
    3547             : 
    3548           0 :   if (fname_arg)
    3549           0 :     fname = xstrdup (fname_arg);
    3550             :   else
    3551           0 :     fname = make_filename (gnupg_sysconfdir (), GPGCONF_NAME EXTSEP_S "conf",
    3552             :                            NULL);
    3553             : 
    3554           0 :   for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
    3555           0 :     runtime[backend_id] = 0;
    3556             : 
    3557           0 :   config = fopen (fname, "r");
    3558           0 :   if (!config)
    3559             :     {
    3560             :       /* Do not print an error if the file is not available, except
    3561             :          when running in syntax check mode.  */
    3562           0 :       if (errno != ENOENT || !update)
    3563             :         {
    3564           0 :           gc_error (0, errno, "can not open global config file '%s'", fname);
    3565           0 :           result = -1;
    3566             :         }
    3567           0 :       xfree (fname);
    3568           0 :       return result;
    3569             :     }
    3570             : 
    3571           0 :   while ((length = read_line (config, &line, &line_len, NULL)) > 0)
    3572             :     {
    3573             :       char *key, *component, *option, *flags, *value;
    3574             :       char *empty;
    3575           0 :       gc_option_t *option_info = NULL;
    3576             :       char *p;
    3577             :       int is_continuation;
    3578             : 
    3579           0 :       lineno++;
    3580           0 :       key = line;
    3581           0 :       while (*key == ' ' || *key == '\t')
    3582           0 :         key++;
    3583           0 :       if (!*key || *key == '#' || *key == '\r' || *key == '\n')
    3584           0 :         continue;
    3585             : 
    3586           0 :       is_continuation = (key != line);
    3587             : 
    3588             :       /* Parse the key field.  */
    3589           0 :       if (!is_continuation && got_match)
    3590             :         break;  /* Finish after the first match.  */
    3591           0 :       else if (!is_continuation)
    3592             :         {
    3593           0 :           in_rule = 0;
    3594           0 :           for (p=key+1; *p && !strchr (" \t\r\n", *p); p++)
    3595             :             ;
    3596           0 :           if (!*p)
    3597             :             {
    3598           0 :               gc_error (0, 0, "missing rule at '%s', line %d", fname, lineno);
    3599           0 :               result = -1;
    3600           0 :               continue;
    3601             :             }
    3602           0 :           *p++ = 0;
    3603           0 :           component = p;
    3604             :         }
    3605           0 :       else if (!in_rule)
    3606             :         {
    3607           0 :           gc_error (0, 0, "continuation but no rule at '%s', line %d",
    3608             :                     fname, lineno);
    3609           0 :           result = -1;
    3610           0 :           continue;
    3611             :         }
    3612             :       else
    3613             :         {
    3614           0 :           component = key;
    3615           0 :           key = NULL;
    3616             :         }
    3617             : 
    3618           0 :       in_rule = 1;
    3619             : 
    3620             :       /* Parse the component.  */
    3621           0 :       while (*component == ' ' || *component == '\t')
    3622           0 :         component++;
    3623           0 :       for (p=component; *p && !strchr (" \t\r\n", *p); p++)
    3624             :         ;
    3625           0 :       if (p == component)
    3626             :         {
    3627           0 :           gc_error (0, 0, "missing component at '%s', line %d",
    3628             :                     fname, lineno);
    3629           0 :           result = -1;
    3630           0 :           continue;
    3631             :         }
    3632           0 :       empty = p;
    3633           0 :       *p++ = 0;
    3634           0 :       option = p;
    3635           0 :       component_id = gc_component_find (component);
    3636           0 :       if (component_id < 0)
    3637             :         {
    3638           0 :           gc_error (0, 0, "unknown component at '%s', line %d",
    3639             :                     fname, lineno);
    3640           0 :           result = -1;
    3641             :         }
    3642             : 
    3643             :       /* Parse the option name.  */
    3644           0 :       while (*option == ' ' || *option == '\t')
    3645           0 :         option++;
    3646           0 :       for (p=option; *p && !strchr (" \t\r\n", *p); p++)
    3647             :         ;
    3648           0 :       if (p == option)
    3649             :         {
    3650           0 :           gc_error (0, 0, "missing option at '%s', line %d",
    3651             :                     fname, lineno);
    3652           0 :           result = -1;
    3653           0 :           continue;
    3654             :         }
    3655           0 :       *p++ = 0;
    3656           0 :       flags = p;
    3657           0 :       if ( component_id != -1)
    3658             :         {
    3659           0 :           option_info = find_option (component_id, option, GC_BACKEND_ANY);
    3660           0 :           if (!option_info)
    3661             :             {
    3662           0 :               gc_error (0, 0, "unknown option at '%s', line %d",
    3663             :                         fname, lineno);
    3664           0 :               result = -1;
    3665             :             }
    3666             :         }
    3667             : 
    3668             : 
    3669             :       /* Parse the optional flags.  */
    3670           0 :       while (*flags == ' ' || *flags == '\t')
    3671           0 :         flags++;
    3672           0 :       if (*flags == '[')
    3673             :         {
    3674           0 :           flags++;
    3675           0 :           p = strchr (flags, ']');
    3676           0 :           if (!p)
    3677             :             {
    3678           0 :               gc_error (0, 0, "syntax error in rule at '%s', line %d",
    3679             :                         fname, lineno);
    3680           0 :               result = -1;
    3681           0 :               continue;
    3682             :             }
    3683           0 :           *p++ = 0;
    3684           0 :           value = p;
    3685             :         }
    3686             :       else  /* No flags given.  */
    3687             :         {
    3688           0 :           value = flags;
    3689           0 :           flags = NULL;
    3690             :         }
    3691             : 
    3692             :       /* Parse the optional value.  */
    3693           0 :       while (*value == ' ' || *value == '\t')
    3694           0 :        value++;
    3695           0 :       for (p=value; *p && !strchr ("\r\n", *p); p++)
    3696             :         ;
    3697           0 :       if (p == value)
    3698           0 :         value = empty; /* No value given; let it point to an empty string.  */
    3699             :       else
    3700             :         {
    3701             :           /* Strip trailing white space.  */
    3702           0 :           *p = 0;
    3703           0 :           for (p--; p > value && (*p == ' ' || *p == '\t'); p--)
    3704           0 :             *p = 0;
    3705             :         }
    3706             : 
    3707             :       /* Check flag combinations.  */
    3708           0 :       if (!flags)
    3709             :         ;
    3710           0 :       else if (!strcmp (flags, "default"))
    3711             :         {
    3712           0 :           if (*value)
    3713             :             {
    3714           0 :               gc_error (0, 0, "flag \"default\" may not be combined "
    3715             :                         "with a value at '%s', line %d",
    3716             :                         fname, lineno);
    3717           0 :               result = -1;
    3718             :             }
    3719             :         }
    3720           0 :       else if (!strcmp (flags, "change"))
    3721             :         ;
    3722           0 :       else if (!strcmp (flags, "no-change"))
    3723             :         ;
    3724             :       else
    3725             :         {
    3726           0 :           gc_error (0, 0, "unknown flag at '%s', line %d",
    3727             :                     fname, lineno);
    3728           0 :           result = -1;
    3729             :         }
    3730             : 
    3731             :       /* In list mode we print out all records.  */
    3732           0 :       if (listfp && !result)
    3733             :         {
    3734             :           /* If this is a new ruleset, print a key record.  */
    3735           0 :           if (!is_continuation)
    3736             :             {
    3737           0 :               char *group = strchr (key, ':');
    3738           0 :               if (group)
    3739             :                 {
    3740           0 :                   *group++ = 0;
    3741           0 :                   if ((p = strchr (group, ':')))
    3742           0 :                     *p = 0; /* We better strip any extra stuff. */
    3743             :                 }
    3744             : 
    3745           0 :               es_fprintf (listfp, "k:%s:", gc_percent_escape (key));
    3746           0 :               es_fprintf (listfp, "%s\n", group? gc_percent_escape (group):"");
    3747             :             }
    3748             : 
    3749             :           /* All other lines are rule records.  */
    3750           0 :           es_fprintf (listfp, "r:::%s:%s:%s:",
    3751             :                       gc_component[component_id].name,
    3752           0 :                       option_info->name? option_info->name : "",
    3753             :                       flags? flags : "");
    3754           0 :           if (value != empty)
    3755           0 :             es_fprintf (listfp, "\"%s", gc_percent_escape (value));
    3756             : 
    3757           0 :           es_putc ('\n', listfp);
    3758             :         }
    3759             : 
    3760             :       /* Check whether the key matches but do this only if we are not
    3761             :          running in syntax check mode. */
    3762           0 :       if ( update
    3763           0 :            && !result && !listfp
    3764           0 :            && (got_match || (key && key_matches_user_or_group (key))) )
    3765             :         {
    3766           0 :           int newflags = 0;
    3767             : 
    3768           0 :           got_match = 1;
    3769             : 
    3770             :           /* Apply the flags from gpgconf.conf.  */
    3771           0 :           if (!flags)
    3772             :             ;
    3773           0 :           else if (!strcmp (flags, "default"))
    3774           0 :             newflags |= GC_OPT_FLAG_DEFAULT;
    3775           0 :           else if (!strcmp (flags, "no-change"))
    3776           0 :             option_info->flags |= GC_OPT_FLAG_NO_CHANGE;
    3777           0 :           else if (!strcmp (flags, "change"))
    3778           0 :             option_info->flags &= ~GC_OPT_FLAG_NO_CHANGE;
    3779             : 
    3780           0 :           if (defaults)
    3781             :             {
    3782             :               /* Here we explicitly allow updating the value again.  */
    3783           0 :               if (newflags)
    3784             :                 {
    3785           0 :                   option_info->new_flags = 0;
    3786             :                 }
    3787           0 :               if (*value)
    3788             :                 {
    3789           0 :                   xfree (option_info->new_value);
    3790           0 :                   option_info->new_value = NULL;
    3791             :                 }
    3792           0 :               change_one_value (option_info, runtime, newflags, value);
    3793             :             }
    3794             :         }
    3795             :     }
    3796             : 
    3797           0 :   if (length < 0 || ferror (config))
    3798             :     {
    3799           0 :       gc_error (0, errno, "error reading from '%s'", fname);
    3800           0 :       result = -1;
    3801             :     }
    3802           0 :   if (fclose (config))
    3803           0 :     gc_error (0, errno, "error closing '%s'", fname);
    3804             : 
    3805           0 :   xfree (line);
    3806             : 
    3807             :   /* If it all worked, process the options. */
    3808           0 :   if (!result && update && defaults && !listfp)
    3809             :     {
    3810             :       /* We need to switch off the runtime update, so that we can do
    3811             :          it later all at once. */
    3812           0 :       int save_opt_runtime = opt.runtime;
    3813           0 :       opt.runtime = 0;
    3814             : 
    3815           0 :       for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++)
    3816             :         {
    3817           0 :           gc_component_change_options (component_id, NULL, NULL);
    3818             :         }
    3819           0 :       opt.runtime = save_opt_runtime;
    3820             : 
    3821           0 :       if (opt.runtime)
    3822             :         {
    3823           0 :           for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
    3824           0 :             if (runtime[backend_id] && gc_backend[backend_id].runtime_change)
    3825           0 :               (*gc_backend[backend_id].runtime_change) (0);
    3826             :         }
    3827             :     }
    3828             : 
    3829           0 :   xfree (fname);
    3830           0 :   return result;
    3831             : }

Generated by: LCOV version 1.11