LCOV - code coverage report
Current view: top level - tools - gpgconf-comp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1262 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 30 0.0 %

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

Generated by: LCOV version 1.11