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