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

Generated by: LCOV version 1.11