2004-02-26 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / tools / gpgconf-comp.c
1 /* gpgconf-comp.c - Configuration utility for GnuPG.
2    Copyright (C) 2004 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 2 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, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
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 /* FIXME use gettext.h */
27 #include <libintl.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <stdarg.h>
35
36 /* For log_logv(), asctimestamp(), gnupg_get_time ().  */
37 #define JNLIB_NEED_LOG_LOGV
38 #include "util.h"
39
40 #include "gpgconf.h"
41
42 \f
43 /* TODO:
44    Portability - Add gnulib replacements for getline, etc.
45    Backend: File backend must be able to write out changes !!!
46    Components: Add more components and their options.
47    Robustness: Do more validation.  Call programs to do validation for us.
48    Don't use popen, as this will not tell us if the program had a
49    non-zero exit code.
50    Add options to change backend binary path.
51    Extract binary path for some backends from gpgsm/gpg config.
52 */
53
54 \f
55 #if defined (__riscos__) \
56     || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
57 void gc_error (int status, int errnum, const char *fmt, ...) \
58   __attribute__ ((format (printf, 3, 4)));
59 #endif
60
61 /* Output a diagnostic message.  If ERRNUM is not 0, then the output
62    is followed by a colon, a white space, and the error string for the
63    error number ERRNUM.  In any case the output is finished by a
64    newline.  The message is prepended by the program name, a colon,
65    and a whitespace.  The output may be further formatted or
66    redirected by the jnlib logging facility.  */
67 void
68 gc_error (int status, int errnum, const char *fmt, ...)
69 {
70   va_list arg_ptr;
71
72   va_start (arg_ptr, fmt);
73   log_logv (JNLIB_LOG_ERROR, fmt, arg_ptr);
74   va_end (arg_ptr);
75
76   if (errnum)
77     log_printf (": %s\n", strerror (errnum));
78   else
79     log_printf ("\n");
80
81   if (status)
82     {
83       log_printf (NULL);
84       log_printf ("fatal error (exit status %i)\n", status);
85       exit (status);
86     }
87 }
88
89 \f
90 /* Backend configuration.  Backends are used to decide how the default
91    and current value of an option can be determined, and how the
92    option can be changed.  To every option in every component belongs
93    exactly one backend that controls and determines the option.  Some
94    backends are programs from the GPG system.  Others might be
95    implemented by GPGConf itself.  If you change this enum, don't
96    forget to update GC_BACKEND below.  */
97 typedef enum
98   {
99     /* Any backend, used for find_option ().  */
100     GC_BACKEND_ANY,
101
102     /* The Gnu Privacy Guard.  */
103     GC_BACKEND_GPG,
104
105     /* The Gnu Privacy Guard for S/MIME.  */
106     GC_BACKEND_GPGSM,
107
108     /* The GPG Agent.  */
109     GC_BACKEND_GPG_AGENT,
110
111     /* The Aegypten directory manager.  */
112     GC_BACKEND_DIRMNGR,
113
114     /* The LDAP server list file for the Aegypten director manager.  */
115     GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST,
116
117     /* The number of the above entries.  */
118     GC_BACKEND_NR
119   } gc_backend_t;
120
121
122 /* To be able to implement generic algorithms for the various
123    backends, we collect all information about them in this struct.  */
124 static struct
125 {
126   /* The name of the backend.  */
127   const char *name;
128
129   /* The name of the program that acts as the backend.  Some backends
130      don't have an associated program, but are implemented directly by
131      GPGConf.  In this case, PROGRAM is NULL.  */
132   char *program;
133
134   /* The option name for the configuration filename of this backend.
135      This must be an absolute pathname.  It can be an option from a
136      different backend (but then ordering of the options might
137      matter).  */
138   const char *option_config_filename;
139
140   /* If this is a file backend rather than a program backend, then
141      this is the name of the option associated with the file.  */
142   const char *option_name;
143 } gc_backend[GC_BACKEND_NR] =
144   {
145     { NULL, NULL, NULL },               /* GC_BACKEND_ANY dummy entry.  */
146     { "GnuPG", "gpg", "gpgconf-gpg.conf" },
147     { "GPGSM", "gpgsm", "gpgconf-gpgsm.conf" },
148     { "GPG Agent", "gpg-agent", "gpgconf-gpg-agent.conf" },
149     { "DirMngr", "dirmngr", "gpgconf-dirmngr.conf" },
150     { "DirMngr LDAP Server List", NULL, "ldapserverlist-file", "LDAP Server" },
151   };
152
153 \f
154 /* Option configuration.  */
155
156 /* An option might take an argument, or not.  Argument types can be
157    basic or complex.  Basic types are generic and easy to validate.
158    Complex types provide more specific information about the intended
159    use, but can be difficult to validate.  If you add to this enum,
160    don't forget to update GC_ARG_TYPE below.  YOU MUST NOT CHANGE THE
161    NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE EXTERNAL
162    INTERFACE.  */
163 typedef enum
164   {
165     /* Basic argument types.  */
166
167     /* No argument.  */
168     GC_ARG_TYPE_NONE = 0,
169
170     /* A String argument.  */
171     GC_ARG_TYPE_STRING = 1,
172
173     /* A signed integer argument.  */
174     GC_ARG_TYPE_INT32 = 2,
175
176     /* An unsigned integer argument.  */
177     GC_ARG_TYPE_UINT32 = 3,
178
179     /* ADD NEW BASIC TYPE ENTRIES HERE.  */
180
181     /* Complex argument types.  */
182
183     /* A complete pathname.  */
184     GC_ARG_TYPE_PATHNAME = 32,
185
186     /* An LDAP server in the format
187        HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN.  */
188     GC_ARG_TYPE_LDAP_SERVER = 33,
189
190     /* A 40 character fingerprint.  */
191     GC_ARG_TYPE_KEY_FPR = 34,
192
193     /* ADD NEW COMPLEX TYPE ENTRIES HERE.  */
194
195     /* The number of the above entries.  */
196     GC_ARG_TYPE_NR
197   } gc_arg_type_t;
198
199
200 /* For every argument, we record some information about it in the
201    following struct.  */
202 static struct
203 {
204   /* For every argument type exists a basic argument type that can be
205      used as a fallback for input and validation purposes.  */
206   gc_arg_type_t fallback;
207
208   /* Human-readable name of the type.  */
209   const char *name;
210 } gc_arg_type[GC_ARG_TYPE_NR] =
211   {
212     /* The basic argument types have their own types as fallback.  */
213     { GC_ARG_TYPE_NONE, "none" },
214     { GC_ARG_TYPE_STRING, "string" },
215     { GC_ARG_TYPE_INT32, "int32" },
216     { GC_ARG_TYPE_UINT32, "uint32" },
217
218     /* Reserved basic type entries for future extension.  */
219     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
220     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
221     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
222     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
223     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
224     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
225     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
226     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
227     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
228     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
229     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
230     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
231     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
232     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
233
234     /* The complex argument types have a basic type as fallback.  */
235     { GC_ARG_TYPE_STRING, "pathname" },
236     { GC_ARG_TYPE_STRING, "ldap server" },
237     { GC_ARG_TYPE_STRING, "key fpr" },
238   };
239
240
241 /* Every option has an associated expert level, than can be used to
242    hide advanced and expert options from beginners.  If you add to
243    this list, don't forget to update GC_LEVEL below.  YOU MUST NOT
244    CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE
245    EXTERNAL INTERFACE.  */
246 typedef enum
247   {
248     /* The basic options should always be displayed.  */
249     GC_LEVEL_BASIC,
250
251     /* The advanced options may be hidden from beginners.  */
252     GC_LEVEL_ADVANCED,
253
254     /* The expert options should only be displayed to experts.  */
255     GC_LEVEL_EXPERT,
256
257     /* The invisible options should normally never be displayed.  */
258     GC_LEVEL_INVISIBLE,
259
260     /* The internal options are never exported, they mark options that
261        are recorded for internal use only.  */
262     GC_LEVEL_INTERNAL,
263
264     /* ADD NEW ENTRIES HERE.  */
265
266     /* The number of the above entries.  */
267     GC_LEVEL_NR
268   } gc_expert_level_t;
269
270 /* A description for each expert level.  */
271 static struct
272 {
273   const char *name;
274 } gc_level[] =
275   {
276     { "basic" },
277     { "advanced" },
278     { "expert" },
279     { "invisible" },
280     { "internal" }
281   };
282
283
284 /* Option flags.  YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING
285    FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE.  */
286 #define GC_OPT_FLAG_NONE        0UL
287 /* Some entries in the option list are not options, but mark the
288    beginning of a new group of options.  These entries have the GROUP
289    flag set.  */
290 #define GC_OPT_FLAG_GROUP       (1UL << 0)
291 /* The ARG_OPT flag for an option indicates that the argument is
292    optional.  This is never set for GC_ARG_TYPE_NONE options.  */
293 #define GC_OPT_FLAG_ARG_OPT     (1UL << 1)
294 /* The LIST flag for an option indicates that the option can occur
295    several times.  A comma separated list of arguments is used as the
296    argument value.  */
297 #define GC_OPT_FLAG_LIST        (1UL << 2)
298 /* The RUNTIME flag for an option indicates that the option can be
299    changed at runtime.  */
300 #define GC_OPT_FLAG_RUNTIME     (1UL << 3)
301
302 /* The following flags are incorporated from the backend.  */
303 /* The DEFAULT flag for an option indicates that the option has a
304    default value.  */
305 #define GC_OPT_FLAG_DEFAULT     (1UL << 4)
306 /* The DEF_DESC flag for an option indicates that the option has a
307    default, which is described by the value of the default field.  */
308 #define GC_OPT_FLAG_DEF_DESC    (1UL << 5)
309 /* The NO_ARG_DESC flag for an option indicates that the argument has
310    a default, which is described by the value of the ARGDEF field.  */
311 #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
312
313 /* A human-readable description for each flag.  */
314 static struct
315 {
316   const char *name;
317 } gc_flag[] =
318   {
319     { "group" },
320     { "optional arg" },
321     { "list" },
322     { "runtime" }
323   };
324
325
326 /* To each option, or group marker, the information in the GC_OPTION
327    struct is provided.  If you change this, don't forget to update the
328    option list of each component.  */
329 struct gc_option
330 {
331   /* If this is NULL, then this is a terminator in an array of unknown
332      length.  Otherwise, if this entry is a group marker (see FLAGS),
333      then this is the name of the group described by this entry.
334      Otherwise it is the name of the option described by this
335      entry.  The name must not contain a colon.  */
336   const char *name;
337
338   /* The option flags.  If the GROUP flag is set, then this entry is a
339      group marker, not an option, and only the fields LEVEL,
340      DESC_DOMAIN and DESC are valid.  In all other cases, this entry
341      describes a new option and all fields are valid.  */
342   unsigned long flags;
343
344   /* The expert level.  This field is valid for options and groups.  A
345      group has the expert level of the lowest-level option in the
346      group.  */
347   gc_expert_level_t level;
348
349   /* A gettext domain in which the following description can be found.
350      If this is NULL, then DESC is not translated.  Valid for groups
351      and options.  */
352   const char *desc_domain;
353
354   /* A gettext description for this group or option.  If it starts
355      with a '|', then the string up to the next '|' describes the
356      argument, and the description follows the second '|'.  */
357   const char *desc;
358
359   /* The following fields are only valid for options.  */
360
361   /* The type of the option argument.  */
362   gc_arg_type_t arg_type;
363
364   /* The backend that implements this option.  */
365   gc_backend_t backend;
366
367   /* The following fields are set to NULL at startup (because all
368      option's are declared as static variables).  They are at the end
369      of the list so that they can be omitted from the option
370      declarations.  */
371
372   /* This is true if the option is supported by this version of the
373      backend.  */
374   int active;
375
376   /* The default value for this option.  This is NULL if the option is
377      not present in the backend, the empty string if no default is
378      available, and otherwise a quoted string.  */
379   char *default_value;
380
381   /* The default argument is only valid if the "optional arg" flag is
382      set, and specifies the default argument (value) that is used if
383      the argument is omitted.  */
384   char *default_arg;
385
386   /* The current value of this option.  */
387   char *value;
388
389   /* The new flags for this option.  The only defined flag is actually
390      GC_OPT_FLAG_DEFAULT, and it means that the option should be
391      deleted.  In this case, NEW_VALUE is NULL.  */
392   unsigned long new_flags;
393
394   /* The new value of this option.  */
395   char *new_value;
396 };
397 typedef struct gc_option gc_option_t;
398
399 /* Use this macro to terminate an option list.  */
400 #define GC_OPTION_NULL { NULL }
401
402 \f
403 /* The options of the GC_COMPONENT_GPG_AGENT component.  */
404 static gc_option_t gc_options_gpg_agent[] =
405  {
406    GC_OPTION_NULL
407  };
408
409
410 /* The options of the GC_COMPONENT_SCDAEMON component.  */
411 static gc_option_t gc_options_scdaemon[] =
412  {
413    GC_OPTION_NULL
414  };
415
416
417 /* The options of the GC_COMPONENT_GPGSM component.  */
418 static gc_option_t gc_options_gpgsm[] =
419  {
420    GC_OPTION_NULL
421  };
422
423
424 /* The options of the GC_COMPONENT_DIRMNGR component.  */
425 static gc_option_t gc_options_dirmngr[] =
426  {
427    /* The configuration file to which we write the changes.  */
428    { "gpgconf-dirmngr.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
429      NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
430
431    { "Monitor",
432      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
433      NULL, "Options controlling the diagnostic output" },
434    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
435      "dirmngr", "verbose",
436      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
437    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
438      "dirmngr", "be somewhat more quiet",
439      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
440    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
441      NULL, NULL,
442      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
443
444    { "Format",
445      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
446      NULL, "Options controlling the format of the output" },
447    { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
448      "dirmngr", "sh-style command output",
449      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
450    { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
451      "dirmngr", "csh-style command output",
452      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
453    
454    { "Configuration",
455      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
456      NULL, "Options controlling the configuration" },
457    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
458      "dirmngr", "|FILE|read options from FILE",
459      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
460
461    { "Debug",
462      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
463      "dirmngr", "Options useful for debugging" },
464    { "debug", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
465      "dirmngr", "|FLAGS|set the debugging FLAGS",
466      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
467    { "debug-all", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
468      "dirmngr", "set all debugging flags",
469      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
470    { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
471      "dirmngr", "do not detach from the console",
472      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
473    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
474      "dirmngr", "|FILE|write logs to FILE",
475      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
476    { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
477      NULL, NULL,
478      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
479    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
480      NULL, NULL,
481      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
482
483    { "Enforcement",
484      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
485      NULL, "Options controlling the interactivity and enforcement" },
486    { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
487      "dirmngr", "run without asking a user",
488      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
489    { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
490      "dirmngr", "force loading of outdated CRLs",
491      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
492
493    { "LDAP",
494      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
495      NULL, "Configuration of LDAP servers to use" },
496    { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
497      "dirmngr", "add new servers discovered in CRL distribution points"
498      " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
499    { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
500      "dirmngr", "|N|set LDAP timeout to N seconds",
501      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
502    /* The following entry must not be removed, as it is required for
503       the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST.  */
504    { "ldapserverlist-file",
505      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
506      "dirmngr", "|FILE|read LDAP server list from FILE",
507      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
508    /* This entry must come after at least one entry for
509       GC_BACKEND_DIRMNGR in this component, so that the entry for
510       "ldapserverlist-file will be initialized before this one.  */
511    { "LDAP Server", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
512      NULL, "LDAP server list",
513      GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST },
514
515    { "CRL",
516      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
517      NULL, "Configuration of the CRL" },
518    { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
519      "dirmngr", "|N|do not return more than N items in one query",
520      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
521
522    GC_OPTION_NULL
523  };
524
525 \f
526 /* Component system.  Each component is a set of options that can be
527    configured at the same time.  If you change this, don't forget to
528    update GC_COMPONENT below.  */
529 typedef enum
530   {
531     /* The GPG Agent.  */
532     GC_COMPONENT_GPG_AGENT,
533
534     /* The Smardcard Daemon.  */
535     GC_COMPONENT_SCDAEMON,
536
537     /* GPG for S/MIME.  */
538     GC_COMPONENT_GPGSM,
539
540     /* The LDAP Directory Manager for CRLs.  */
541     GC_COMPONENT_DIRMNGR,
542
543     /* The number of components.  */
544     GC_COMPONENT_NR
545   } gc_component_t;
546
547
548 /* The information associated with each component.  */
549 static struct
550 {
551   /* The name of this component.  Must not contain a colon (':')
552      character.  */
553   const char *name;
554
555   /* The gettext domain for the description DESC.  If this is NULL,
556      then the description is not translated.  */
557   const char *desc_domain;
558
559   /* The description for this domain.  */
560   const char *desc;
561
562   /* The list of options for this component, terminated by
563      GC_OPTION_NULL.  */
564   gc_option_t *options;
565 } gc_component[] =
566   {
567     { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent },
568     { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon },
569     { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm },
570     { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr }
571   };
572
573 \f
574 /* Robust version of dgettext.  */
575 static const char *
576 my_dgettext (const char *domain, const char *msgid)
577 {
578   if (domain)
579     {
580       char *text = dgettext (domain, msgid);
581       return text ? text : msgid;
582     }
583   else
584     return msgid;
585 }
586
587
588 /* Percent-Escape special characters.  The string is valid until the
589    next invocation of the function.  */
590 static char *
591 percent_escape (const char *src)
592 {
593   static char *esc_str;
594   static int esc_str_len;
595   int new_len = 3 * strlen (src) + 1;
596   char *dst;
597
598   if (esc_str_len < new_len)
599     {
600       char *new_esc_str = realloc (esc_str, new_len);
601       if (!new_esc_str)
602         gc_error (1, errno, "can not escape string");
603       esc_str = new_esc_str;
604       esc_str_len = new_len;
605     }
606
607   dst = esc_str;
608   while (*src)
609     {
610       if (*src == '%')
611         {
612           *(dst++) = '%';
613           *(dst++) = '2';
614           *(dst++) = '5';
615         }         
616       else if (*src == ':')
617         {
618           /* The colon is used as field separator.  */
619           *(dst++) = '%';
620           *(dst++) = '3';
621           *(dst++) = 'a';
622         }
623       else if (*src == ',')
624         {
625           /* The comma is used as list separator.  */
626           *(dst++) = '%';
627           *(dst++) = '2';
628           *(dst++) = 'c';
629         }
630       else
631         *(dst++) = *(src);
632       src++;
633     }
634   *dst = '\0';
635   return esc_str;
636 }
637
638
639 /* Convert two hexadecimal digits from STR to the value they
640    represent.  Returns -1 if one of the characters is not a
641    hexadecimal digit.  */
642 static int
643 hextobyte (const char *str)
644 {
645   int val = 0;
646   int i;
647
648 #define NROFHEXDIGITS 2
649   for (i = 0; i < NROFHEXDIGITS; i++)
650     {
651       if (*str >= '0' && *str <= '9')
652         val += *str - '0';
653       else if (*str >= 'A' && *str <= 'F')
654         val += 10 + *str - 'A';
655       else if (*str >= 'a' && *str <= 'f')
656         val += 10 + *str - 'a';
657       else
658         return -1;
659       if (i < NROFHEXDIGITS - 1)
660         val *= 16;
661       str++;
662     }
663   return val;
664 }
665
666
667
668 /* Percent-Deescape special characters.  The string is valid until the
669    next invocation of the function.  */
670 static char *
671 percent_deescape (const char *src)
672 {
673   static char *str;
674   static int str_len;
675   int new_len = 3 * strlen (src) + 1;
676   char *dst;
677
678   if (str_len < new_len)
679     {
680       char *new_str = realloc (str, new_len);
681       if (!new_str)
682         gc_error (1, errno, "can not deescape string");
683       str = new_str;
684       str_len = new_len;
685     }
686
687   dst = str;
688   while (*src)
689     {
690       if (*src == '%')
691         {
692           int val = hextobyte (src + 1);
693
694           if (val < 0)
695             gc_error (1, 0, "malformed end of string %s", src);
696
697           *(dst++) = (char) val;
698           src += 3;
699         }         
700       else
701         *(dst++) = *(src++);
702     }
703   *dst = '\0';
704   return str;
705 }
706
707 \f
708 /* List all components that are available.  */
709 void
710 gc_component_list_components (FILE *out)
711 {
712   gc_component_t idx;
713
714   for (idx = 0; idx < GC_COMPONENT_NR; idx++)
715     {
716       const char *desc = gc_component[idx].desc;
717       desc = my_dgettext (gc_component[idx].desc_domain, desc);
718       fprintf (out, "%s:%s\n", gc_component[idx].name, percent_escape (desc));
719     }
720 }
721
722 \f
723 /* Find the component with the name NAME.  Returns -1 if not
724    found.  */
725 int
726 gc_component_find (const char *name)
727 {
728   gc_component_t idx;
729
730   for (idx = 0; idx < GC_COMPONENT_NR; idx++)
731     {
732       if (!strcmp (name, gc_component[idx].name))
733         return idx;
734     }
735   return -1;
736 }
737
738 \f
739 /* List all options of the component COMPONENT.  */
740 void
741 gc_component_list_options (int component, FILE *out)
742 {  
743   const gc_option_t *option = gc_component[component].options;
744
745   while (option->name)
746     {
747       const char *desc = NULL;
748       char *arg_name = NULL;
749
750       /* Do not output unknown or internal options.  */
751       if (!(option->flags & GC_OPT_FLAG_GROUP)
752           && (!option->active || option->level == GC_LEVEL_INTERNAL))
753         {
754           option++;
755           continue;
756         }
757
758       if (option->desc)
759         {
760           desc = my_dgettext (option->desc_domain, option->desc);
761
762           if (*desc == '|')
763             {
764               const char *arg_tail = strchr (&desc[1], '|');
765
766               if (arg_tail)
767                 {
768                   int arg_len = arg_tail - &desc[1];
769                   arg_name = xmalloc (arg_len + 1);
770                   memcpy (arg_name, &desc[1], arg_len);
771                   arg_name[arg_len] = '\0';
772                   desc = arg_tail + 1;
773                 }
774             }
775         }
776
777       /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR
778          ORDER IS PART OF THE EXTERNAL INTERFACE.  YOU MUST NOT REMOVE
779          ANY FIELDS.  */
780
781       /* The name field.  */
782       fprintf (out, "%s", option->name);
783
784       /* The flags field.  */
785       fprintf (out, ":%lu", option->flags);
786       if (opt.verbose)
787         {
788           putc (' ', out);
789           
790           if (!option->flags)
791             fprintf (out, "none");
792           else
793             {
794               unsigned long flags = option->flags;
795               unsigned long flag = 0;
796               unsigned long first = 1;
797
798               while (flags)
799                 {
800                   if (flags & 1)
801                     {
802                       if (first)
803                         first = 0;
804                       else
805                         putc (',', out);
806                       fprintf (out, "%s", gc_flag[flag].name);
807                     }
808                   flags >>= 1;
809                   flag++;
810                 }
811             }
812         }
813
814       /* The level field.  */
815       fprintf (out, ":%u", option->level);
816       if (opt.verbose)
817         fprintf (out, " %s", gc_level[option->level].name);
818
819       /* The description field.  */
820       fprintf (out, ":%s", desc ? percent_escape (desc) : "");
821
822       /* The type field.  */
823       fprintf (out, ":%u", option->arg_type);
824       if (opt.verbose)
825         fprintf (out, " %s", gc_arg_type[option->arg_type].name);
826
827       /* The alternate type field.  */
828       fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback);
829       if (opt.verbose)
830         fprintf (out, " %s",
831                  gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
832
833       /* The argument name field.  */
834       fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : "");
835       if (arg_name)
836         xfree (arg_name);
837
838       /* The default value field.  */
839       fprintf (out, ":%s", option->default_value ? option->default_value : "");
840
841       /* The default argument field.  */
842       fprintf (out, ":%s", option->default_arg ? option->default_arg : "");
843
844       /* The value field.  */
845       if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
846           && (option->flags & GC_OPT_FLAG_LIST)
847           && option->value)
848         /* The special format "1,1,1,1,...,1" is converted to a number
849            here.  */
850         fprintf (out, ":%u", (strlen (option->value) + 1) / 2);
851       else
852         fprintf (out, ":%s", option->value ? option->value : "");
853
854       /* ADD NEW FIELDS HERE.  */
855
856       putc ('\n', out);
857       option++;
858     }
859 }
860
861
862 /* Find the option NAME in component COMPONENT, for the backend
863    BACKEND.  If BACKEND is GC_BACKEND_ANY, any backend will match.  */
864 static gc_option_t *
865 find_option (gc_component_t component, const char *name,
866              gc_backend_t backend)
867 {
868   gc_option_t *option = gc_component[component].options;
869   while (option->name)
870     {
871       if (!(option->flags & GC_OPT_FLAG_GROUP)
872           && !strcmp (option->name, name)
873           && (backend == GC_BACKEND_ANY || option->backend == backend))
874         break;
875       option++;
876     }
877   return option->name ? option : NULL;
878 }
879
880 \f
881 /* Determine the configuration pathname for the component COMPONENT
882    and backend BACKEND.  */
883 static char *
884 get_config_pathname (gc_component_t component, gc_backend_t backend)
885 {
886   char *pathname = NULL;
887   gc_option_t *option = find_option
888     (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
889   assert (option);
890   assert (option->arg_type == GC_ARG_TYPE_PATHNAME);
891   assert (!(option->flags & GC_OPT_FLAG_LIST));
892
893   if (!option->active || !option->default_value)
894     gc_error (1, 0, "Option %s, needed by backend %s, was not initialized",
895               gc_backend[backend].option_config_filename,
896               gc_backend[backend].name);
897
898   if (option->value && *option->value)
899     pathname = percent_deescape (&option->value[1]);
900   else if (option->default_value && *option->default_value)
901     pathname = percent_deescape (&option->default_value[1]);
902   else
903     pathname = "";
904
905   if (pathname[0] != '/')
906     gc_error (1, 0, "Option %s, needed by backend %s, is not absolute",
907               gc_backend[backend].option_config_filename,
908               gc_backend[backend].name);
909
910   return pathname;
911 }
912
913 \f
914 /* Retrieve the options for the component COMPONENT from backend
915    BACKEND, which we already know is a program-type backend.  */
916 static void
917 retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
918 {
919   char *cmd_line;
920   char *line = NULL;
921   size_t line_len = 0;
922   ssize_t length;
923   FILE *config;
924   char *config_pathname;
925
926   cmd_line = xasprintf ("%s --gpgconf-list", gc_backend[backend].program);
927
928   config = popen (cmd_line, "r");
929   if (!config)
930     gc_error (1, errno, "could not gather active options from %s", cmd_line);
931
932   while ((length = getline (&line, &line_len, config)) > 0)
933     {
934       gc_option_t *option;
935       char *linep;
936       unsigned long flags = 0;
937       char *default_value = NULL;
938       
939       /* Strip newline and carriage return, if present.  */
940       while (length > 0
941              && (line[length - 1] == '\n' || line[length - 1] == '\r'))
942         line[--length] = '\0';
943
944       linep = strchr (line, ':');
945       if (linep)
946         *(linep++) = '\0';
947       
948       /* Extract additional flags.  Default to none.  */
949       if (linep)
950         {
951           char *end;
952           char *tail;
953
954           end = strchr (linep, ':');
955           if (end)
956             *(end++) = '\0';
957
958           errno = 0;
959           flags = strtoul (linep, &tail, 0);
960           if (errno)
961             gc_error (1, errno, "malformed flags in option %s from %s", line, cmd_line);
962           if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
963             gc_error (1, 0, "garbage after flags in option %s from %s", line, cmd_line);
964
965           linep = end;
966         }
967
968       /* Extract default value, if present.  Default to empty if
969          not.  */
970       if (linep)
971         {
972           char *end;
973
974           end = strchr (linep, ':');
975           if (end)
976             *(end++) = '\0';
977
978           if (flags & GC_OPT_FLAG_DEFAULT)
979             default_value = linep;
980
981           linep = end;
982         }
983
984       /* Look up the option in the component and install the
985          configuration data.  */
986       option = find_option (component, line, backend);
987       if (option)
988         {
989           if (option->active)
990             gc_error (1, errno, "option %s returned twice from %s",
991                       line, cmd_line);
992           option->active = 1;
993
994           option->flags |= flags;
995           if (default_value && *default_value)
996             option->default_value = xstrdup (default_value);
997         }
998     }
999   if (ferror (config))
1000     gc_error (1, errno, "error reading from %s", cmd_line);
1001   if (fclose (config) && ferror (config))
1002     gc_error (1, errno, "error closing %s", cmd_line);
1003   xfree (cmd_line);
1004
1005   /* At this point, we can parse the configuration file.  */
1006   config_pathname = get_config_pathname (component, backend);
1007
1008   config = fopen (config_pathname, "r");
1009   if (!config)
1010     gc_error (0, errno, "warning: can not open config file %s",
1011               config_pathname);
1012   else
1013     {
1014       while ((length = getline (&line, &line_len, config)) > 0)
1015         {
1016           char *name;
1017           char *value;
1018           gc_option_t *option;
1019           
1020           name = line;
1021           while (*name == ' ' || *name == '\t')
1022             name++;
1023           if (!*name || *name == '#' || *name == '\r' || *name == '\n')
1024             continue;
1025
1026           value = name;
1027           while (*value && *value != ' ' && *value != '\t'
1028                  && *value != '#' && *value != '\r' && *value != '\n')
1029             value++;
1030           if (*value == ' ' || *value == '\t')
1031             {
1032               char *end;
1033
1034               *(value++) = '\0';
1035               while (*value == ' ' || *value == '\t')
1036                 value++;
1037
1038               end = value;
1039               while (*end && *end != '#' && *end != '\r' && *end != '\n')
1040                 end++;
1041               while (end > value && (end[-1] == ' ' || end[-1] == '\t'))
1042                 end--;
1043               *end = '\0';
1044             }
1045           else
1046             *value = '\0';
1047
1048           /* Look up the option in the component and install the
1049              configuration data.  */
1050           option = find_option (component, line, backend);
1051           if (option)
1052             {
1053               char *opt_value;
1054
1055               if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
1056                 {
1057                   if (*value)
1058                     gc_error (0, 0,
1059                               "warning: ignoring argument %s for option %s",
1060                               value, name);
1061                   opt_value = xstrdup ("1");
1062                 }
1063               else if (gc_arg_type[option->arg_type].fallback
1064                        == GC_ARG_TYPE_STRING)
1065                 opt_value = xasprintf ("\"%s", percent_escape (value));
1066               else
1067                 {
1068                   /* FIXME: Verify that the number is sane.  */
1069                   opt_value = xstrdup (value);
1070                 }
1071
1072               /* Now enter the option into the table.  */
1073               if (!(option->flags & GC_OPT_FLAG_LIST))
1074                 {
1075                   if (option->value)
1076                     free (option->value);
1077                   option->value = opt_value;
1078                 }
1079               else
1080                 {
1081                   if (!option->value)
1082                     option->value = opt_value;
1083                   else
1084                     {
1085                       char *opt_val = opt_value;
1086
1087                       option->value = xasprintf ("%s,%s", option->value,
1088                                                  opt_val);
1089                       xfree (opt_value);
1090                     }
1091                 }
1092             }
1093         }
1094
1095       if (ferror (config))
1096         gc_error (1, errno, "error reading from %s", config_pathname);
1097       if (fclose (config) && ferror (config))
1098         gc_error (1, errno, "error closing %s", config_pathname);
1099     }
1100
1101   if (line)
1102     free (line);
1103 }
1104
1105
1106 /* Retrieve the options for the component COMPONENT from backend
1107    BACKEND, which we already know is of type file list.  */ 
1108 static void
1109 retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
1110 {
1111   gc_option_t *list_option;
1112   char *list_pathname;
1113   FILE *list_file;
1114   char *line = NULL;
1115   size_t line_len = 0;
1116   ssize_t length;
1117   char *list = NULL;
1118
1119   list_option = find_option (component,
1120                              gc_backend[backend].option_name, GC_BACKEND_ANY);
1121   assert (list_option);
1122   assert (!list_option->active);
1123
1124   list_pathname = get_config_pathname (component, backend);
1125   list_file = fopen (list_pathname, "r");
1126   if (!list_file)
1127     gc_error (0, errno, "warning: can not open list file %s", list_pathname);
1128   else
1129     {
1130
1131       while ((length = getline (&line, &line_len, list_file)) > 0)
1132         {
1133           char *start;
1134           char *end;
1135           char *new_list;
1136
1137           start = line;
1138           while (*start == ' ' || *start == '\t')
1139             start++;
1140           if (!*start || *start == '#' || *start == '\r' || *start == '\n')
1141             continue;
1142
1143           end = start;
1144           while (*end && *end != '#' && *end != '\r' && *end != '\n')
1145             end++;
1146           /* Walk back to skip trailing white spaces.  Looks evil, but
1147              works because of the conditions on START and END imposed
1148              at this point (END is at least START + 1, and START is
1149              not a whitespace character).  */
1150           while (*(end - 1) == ' ' || *(end - 1) == '\t')
1151             end--;
1152           *end = '\0';
1153           /* FIXME: Oh, no!  This is so lame!  Use realloc and really
1154              append.  */
1155           if (list)
1156             {
1157               new_list = xasprintf ("%s,%s", list, percent_escape (start));
1158               xfree (list);
1159               list = new_list;
1160             }
1161           else
1162             list = xasprintf ("\"%s", percent_escape (start));
1163         }
1164       if (ferror (list_file))
1165         gc_error (1, errno, "can not read list file %s", list_pathname);
1166     }
1167
1168   list_option->active = 1;
1169   list_option->value = list;
1170
1171   if (line)
1172     free (line);
1173 }
1174
1175
1176 /* Retrieve the currently active options and their defaults from all
1177    involved backends for this component.  */
1178 void
1179 gc_component_retrieve_options (int component)
1180 {
1181   int backend_seen[GC_BACKEND_NR];
1182   gc_backend_t backend;
1183   gc_option_t *option = gc_component[component].options;
1184
1185   for (backend = 0; backend < GC_BACKEND_NR; backend++)
1186     backend_seen[backend] = 0;
1187
1188   while (option->name)
1189     {
1190       if (!(option->flags & GC_OPT_FLAG_GROUP))
1191         {
1192           backend = option->backend;
1193
1194           if (backend_seen[backend])
1195             {
1196               option++;
1197               continue;
1198             }
1199           backend_seen[backend] = 1;
1200
1201           assert (backend != GC_BACKEND_ANY);
1202
1203           if (gc_backend[backend].program)
1204             retrieve_options_from_program (component, backend);
1205           else
1206             retrieve_options_from_file (component, backend);
1207         }
1208       option++;
1209     }
1210 }
1211
1212 \f
1213 /* Perform a simple validity check based on the type.  Return in
1214    NEW_VALUE_NR the value of the number in NEW_VALUE if OPTION is of
1215    type GC_ARG_TYPE_NONE.  */
1216 static void
1217 option_check_validity (gc_option_t *option, unsigned long flags,
1218                        char *new_value, unsigned long *new_value_nr)
1219 {
1220   char *arg;
1221
1222   if (option->new_flags || option->new_value)
1223     gc_error (1, 0, "option %s already changed", option->name);
1224
1225   if (flags & GC_OPT_FLAG_DEFAULT)
1226     {
1227       if (*new_value)
1228         gc_error (1, 0, "argument %s provided for deleted option %s",
1229                   new_value, option->name);
1230
1231       return;
1232     }
1233
1234   /* GC_ARG_TYPE_NONE options have special list treatment.  */
1235   if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
1236     {
1237       char *tail;
1238
1239       errno = 0;
1240       *new_value_nr = strtoul (new_value, &tail, 0);
1241
1242       if (errno)
1243         gc_error (1, errno, "invalid argument for option %s",
1244                   option->name);
1245       if (*tail)
1246         gc_error (1, 0, "garbage after argument for option %s",
1247                       option->name);
1248
1249       if (!(option->flags & GC_OPT_FLAG_LIST))
1250         {
1251           if (*new_value_nr != 1)
1252             gc_error (1, 0, "argument for non-list option %s of type 0 "
1253                       "(none) must be 1", option->name);
1254         }
1255       else
1256         {
1257           if (*new_value_nr == 0)
1258             gc_error (1, 0, "argument for option %s of type 0 (none) "
1259                       "must be positive", option->name);
1260         }
1261
1262       return;
1263     }
1264
1265   arg = new_value;
1266   do
1267     {
1268       if (*arg == '\0' || *arg == ',')
1269         {
1270           if (!(option->flags & GC_OPT_FLAG_ARG_OPT))
1271             gc_error (1, 0, "argument required for option %s", option->name);
1272
1273           if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST))
1274             gc_error (1, 0, "list found for non-list option %s", option->name);
1275         }
1276       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
1277         {
1278           if (*arg != '"')
1279             gc_error (1, 0, "string argument for option %s must begin "
1280                       "with a quote (\") character", option->name);
1281         }
1282       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
1283         {
1284           errno = 0;
1285           (void) strtol (arg, &arg, 0);
1286
1287           if (errno)
1288             gc_error (1, errno, "invalid argument for option %s",
1289                       option->name);
1290
1291           if (*arg != '\0' && *arg != ',')
1292             gc_error (1, 0, "garbage after argument for option %s",
1293                       option->name);
1294         }
1295       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
1296         {
1297           errno = 0;
1298           (void) strtoul (arg, &arg, 0);
1299
1300           if (errno)
1301             gc_error (1, errno, "invalid argument for option %s",
1302                       option->name);
1303
1304           if (*arg != '\0' && *arg != ',')
1305             gc_error (1, 0, "garbage after argument for option %s",
1306                       option->name);
1307         }
1308       arg = strchr (arg, ',');
1309       if (arg)
1310         arg++;
1311     }
1312   while (arg && *arg);
1313 }
1314
1315
1316 /* Create and verify the new configuration file for the specified
1317    backend and component.  Returns 0 on success and -1 on error.  */
1318 static int
1319 change_options_file (gc_component_t component, gc_backend_t backend,
1320                      char **src_filenamep, char **dest_filenamep,
1321                      char **orig_filenamep)
1322 {
1323   /* FIXME.  */
1324   assert (!"Not implemented.");
1325   return -1;
1326 }
1327
1328
1329 /* Create and verify the new configuration file for the specified
1330    backend and component.  Returns 0 on success and -1 on error.  */
1331 static int
1332 change_options_program (gc_component_t component, gc_backend_t backend,
1333                         char **src_filenamep, char **dest_filenamep,
1334                         char **orig_filenamep)
1335 {
1336   static const char marker[] = "###+++--- GPGConf ---+++###";
1337   /* True if we are within the marker in the config file.  */
1338   int in_marker = 0;
1339   gc_option_t *option;
1340   char *line = NULL;
1341   size_t line_len;
1342   ssize_t length;
1343   int res;
1344   int fd;
1345   FILE *src_file = NULL;
1346   FILE *dest_file = NULL;
1347   char *src_filename;
1348   char *dest_filename;
1349   char *orig_filename;
1350
1351   /* FIXME.  Throughout the function, do better error reporting.  */
1352   dest_filename = xstrdup (get_config_pathname (component, backend));
1353   src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ());
1354   orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ());
1355
1356   res = link (dest_filename, orig_filename);
1357   if (res < 0 && errno != ENOENT)
1358     return -1;
1359   if (res < 0)
1360     {
1361       xfree (orig_filename);
1362       orig_filename = NULL;
1363     }
1364
1365   /* We now initialize the return strings, so the caller can do the
1366      cleanup for us.  */
1367   *src_filenamep = src_filename;
1368   *dest_filenamep = dest_filename;
1369   *orig_filenamep = orig_filename;
1370
1371   /* Use open() so that we can use O_EXCL.  */
1372   fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
1373   if (fd < 0)
1374     return -1;
1375   src_file = fdopen (fd, "w");
1376   res = errno;
1377   if (!src_file)
1378     {
1379       errno = res;
1380       return -1;
1381     }
1382
1383   /* Only if ORIG_FILENAME is not NULL did the configuration file
1384      exist already.  In this case, we will copy its content into the
1385      new configuration file, changing it to our liking in the
1386      process.  */
1387   if (orig_filename)
1388     {
1389       dest_file = fopen (dest_filename, "r");
1390       if (!dest_file)
1391         goto change_one_err;
1392
1393       while ((length = getline (&line, &line_len, dest_file)) > 0)
1394         {
1395           int disable = 0;
1396           char *start;
1397           char *end;
1398
1399           if (!strncmp (marker, line, sizeof (marker) - 1))
1400             {
1401               if (!in_marker)
1402                 in_marker = 1;
1403               else
1404                 break;
1405             }
1406
1407           start = line;
1408           while (*start == ' ' || *start == '\t')
1409             start++;
1410           if (*start && *start != '\r' && *start != '\n' && *start != '#')
1411             {
1412               char saved_end;
1413
1414               end = start;
1415               while (*end && *end != ' ' && *end != '\t'
1416                      && *end != '\r' && *end != '\n' && *end != '#')
1417                 end++;
1418               saved_end = *end;
1419               *end = '\0';
1420
1421               option = find_option (component, start, backend);
1422               *end = saved_end;
1423               if (option && ((option->new_flags & GC_OPT_FLAG_DEFAULT)
1424                              || option->new_value))
1425                 disable = 1;
1426             }
1427           if (disable)
1428             {
1429               if (!in_marker)
1430                 {
1431                   fprintf (src_file,
1432                            "# GPGConf disabled this option here at %s\n",
1433                            asctimestamp (gnupg_get_time ()));
1434                   if (ferror (src_file))
1435                     goto change_one_err;
1436                   fprintf (src_file, "# %s", line);
1437                   if (ferror (src_file))
1438                     goto change_one_err;
1439                 }
1440             }
1441           else
1442             {
1443               fprintf (src_file, "%s", line);
1444               if (ferror (src_file))
1445                 goto change_one_err;
1446             }
1447         }
1448       if (ferror (dest_file))
1449         goto change_one_err;
1450     }
1451
1452   if (!in_marker)
1453     {
1454       /* There was no marker.  This is the first time we edit the
1455          file.  We add our own marker at the end of the file and
1456          proceed.  Note that we first write a newline, this guards us
1457          against files which lack the newline at the end of the last
1458          line, while it doesn't hurt us in all other cases.  */
1459       fprintf (src_file, "\n%s\n", marker);
1460       if (ferror (src_file))
1461         goto change_one_err;
1462     }
1463   /* At this point, we have copied everything up to the end marker
1464      into the new file, except for the options we are going to change.
1465      Now, dump the changed options (except for those we are going to
1466      revert to their default), and write the end marker, possibly
1467      followed by the rest of the original file.  */
1468   option = gc_component[component].options;
1469   while (option->name)
1470     {
1471       if (!(option->flags & GC_OPT_FLAG_GROUP)
1472           && option->backend == backend
1473           && option->new_value)
1474         {
1475           char *arg = option->new_value;
1476
1477           do
1478             {
1479               if (*arg == '\0' || *arg == ',')
1480                 {
1481                   fprintf (src_file, "%s\n", option->name);
1482                   if (ferror (src_file))
1483                     goto change_one_err;
1484                 }
1485               else if (gc_arg_type[option->arg_type].fallback
1486                        == GC_ARG_TYPE_NONE)
1487                 {
1488                   assert (*arg == '1');
1489                   fprintf (src_file, "%s\n", option->name);
1490                   if (ferror (src_file))
1491                     goto change_one_err;
1492
1493                   arg++;
1494                 }
1495               else if (gc_arg_type[option->arg_type].fallback
1496                        == GC_ARG_TYPE_STRING)
1497                 {
1498                   char *end;
1499                   
1500                   assert (*arg == '"');
1501                   arg++;
1502                   
1503                   end = strchr (arg, ',');
1504                   if (end)
1505                     *end = '\0';
1506
1507                   fprintf (src_file, "%s %s\n", option->name,
1508                            percent_deescape (arg));
1509                   if (ferror (src_file))
1510                     goto change_one_err;
1511
1512                   if (end)
1513                     *end = ',';
1514                   arg = end;
1515                 }
1516               else
1517                 {
1518                   char *end;
1519
1520                   end = strchr (arg, ',');
1521                   if (end)
1522                     *end = '\0';
1523
1524                   fprintf (src_file, "%s %s\n", option->name, arg);
1525                   if (ferror (src_file))
1526                     goto change_one_err;
1527
1528                   if (end)
1529                     *end = ',';
1530                   arg = end;
1531                 }
1532
1533               assert (arg == NULL || *arg == '\0' || *arg == ',');
1534               if (arg && *arg == ',')
1535                 arg++;
1536             }
1537           while (arg && *arg);
1538         }
1539       option++;
1540     }
1541
1542   fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
1543   if (ferror (src_file))
1544     goto change_one_err;
1545
1546   if (!in_marker)
1547     {
1548       fprintf (src_file, "# GPGConf edited this configuration file.\n");
1549       if (ferror (src_file))
1550         goto change_one_err;
1551       fprintf (src_file, "# It will disable options before this marked "
1552                "block, but it will\n");
1553       if (ferror (src_file))
1554         goto change_one_err;
1555       fprintf (src_file, "# never change anything below these lines.\n");
1556       if (ferror (src_file))
1557         goto change_one_err;
1558     }
1559   if (dest_file)
1560     {
1561       while ((length = getline (&line, &line_len, dest_file)) > 0)
1562         {
1563           fprintf (src_file, "%s", line);
1564           if (ferror (src_file))
1565             goto change_one_err;
1566         }
1567       if (ferror (dest_file))
1568         goto change_one_err;
1569     }
1570   if (line)
1571     free (line);
1572   res = fclose (src_file);
1573   if (res)
1574     {
1575       res = errno;
1576       close (fd);
1577       if (dest_file)
1578         fclose (dest_file);
1579       errno = res;
1580       return -1;
1581     }
1582   close (fd);
1583   if (dest_file)
1584     {
1585       res = fclose (dest_file);
1586       if (res)
1587         return -1;
1588     }
1589   return 0;
1590
1591  change_one_err:
1592   if (line)
1593     free (line);
1594   res = errno;
1595   if (src_file)
1596     {
1597       fclose (src_file);
1598       close (fd);
1599     }
1600   if (dest_file)
1601     fclose (dest_file);
1602   errno = res;
1603   return -1;
1604 }
1605
1606
1607 /* Read the modifications from IN and apply them.  */
1608 void
1609 gc_component_change_options (int component, FILE *in)
1610 {
1611   int err = 0;
1612   char *src_pathname[GC_BACKEND_NR];
1613   char *dest_pathname[GC_BACKEND_NR];
1614   char *orig_pathname[GC_BACKEND_NR];
1615   gc_backend_t backend;
1616   gc_option_t *option;
1617   char *line = NULL;
1618   size_t line_len = 0;
1619   ssize_t length;
1620
1621   for (backend = 0; backend < GC_BACKEND_NR; backend++)
1622     {
1623       src_pathname[backend] = NULL;
1624       dest_pathname[backend] = NULL;
1625       orig_pathname[backend] = NULL;
1626     }
1627
1628   while ((length = getline (&line, &line_len, in)) > 0)
1629     {
1630       char *linep;
1631       unsigned long flags = 0;
1632       char *new_value = "";
1633       unsigned long new_value_nr;
1634
1635       /* Strip newline and carriage return, if present.  */
1636       while (length > 0
1637              && (line[length - 1] == '\n' || line[length - 1] == '\r'))
1638         line[--length] = '\0';
1639
1640       linep = strchr (line, ':');
1641       if (linep)
1642         *(linep++) = '\0';
1643
1644       /* Extract additional flags.  Default to none.  */
1645       if (linep)
1646         {
1647           char *end;
1648           char *tail;
1649
1650           end = strchr (linep, ':');
1651           if (end)
1652             *(end++) = '\0';
1653
1654           errno = 0;
1655           flags = strtoul (linep, &tail, 0);
1656           if (errno)
1657             gc_error (1, errno, "malformed flags in option %s", line);
1658           if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
1659             gc_error (1, 0, "garbage after flags in option %s", line);
1660
1661           linep = end;
1662         }
1663
1664       /* Extract default value, if present.  Default to empty if
1665          not.  */
1666       if (linep)
1667         {
1668           char *end;
1669
1670           end = strchr (linep, ':');
1671           if (end)
1672             *(end++) = '\0';
1673
1674           new_value = linep;
1675
1676           linep = end;
1677         }
1678
1679       option = find_option (component, line, GC_BACKEND_ANY);
1680       if (!option)
1681         gc_error (1, 0, "unknown option %s", line);
1682
1683       option_check_validity (option, flags, new_value, &new_value_nr);
1684
1685       option->new_flags = flags;
1686       if (!(flags & GC_OPT_FLAG_DEFAULT))
1687         {
1688           if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
1689               && (option->flags & GC_OPT_FLAG_LIST))
1690             {
1691               char *str;
1692
1693               /* We convert the number to a list of 1's for
1694                  convenient list handling.  */
1695               assert (new_value_nr > 0);
1696               option->new_value = xmalloc ((2 * (new_value_nr - 1) + 1) + 1);
1697               str = option->new_value;
1698               *(str++) = '1';
1699               while (--new_value_nr > 0)
1700                 {
1701                   *(str++) = ',';
1702                   *(str++) = '1';
1703                 }
1704               *(str++) = '\0';
1705             }
1706           else
1707             option->new_value = xstrdup (new_value);
1708         }
1709     }
1710
1711   /* Now that we have collected and locally verified the changes,
1712      write them out to new configuration files, verify them
1713      externally, and then commit them.  */
1714   option = gc_component[component].options;
1715   while (option->name)
1716     {
1717       /* Go on if we have already seen this backend, or if there is
1718          nothing to do.  */
1719       if (src_pathname[option->backend] || !(option->new_flags || option->new_value))
1720         {
1721           option++;
1722           continue;
1723         }
1724
1725       if (gc_backend[option->backend].program)
1726         err = change_options_program (component, option->backend,
1727                                       &src_pathname[component],
1728                                       &dest_pathname[component],
1729                                       &orig_pathname[component]);
1730       else
1731         err = change_options_file (component, option->backend,
1732                                    &src_pathname[component],
1733                                    &dest_pathname[component],
1734                                    &orig_pathname[component]);
1735         
1736       if (err)
1737         break;
1738           
1739       option++;
1740     }
1741
1742   if (!err)
1743     {
1744       int i;
1745
1746       for (i = 0; i < GC_COMPONENT_NR; i++)
1747         {
1748           if (src_pathname[i])
1749             {
1750               /* FIXME: Make a verification here.  */
1751
1752               assert (dest_pathname[i]);
1753
1754               if (orig_pathname[i])
1755                 err = rename (src_pathname[i], dest_pathname[i]);
1756               else
1757                 {
1758                   /* This is a bit safer than rename() because we
1759                      expect DEST_PATHNAME not to be there.  If it
1760                      happens to be there, this will fail.  */
1761                   err = link (src_pathname[i], dest_pathname[i]);
1762                   if (!err)
1763                     unlink (src_pathname[i]);
1764                 }
1765               if (err)
1766                 break;
1767               src_pathname[i] = NULL;
1768             }
1769         }
1770     }
1771
1772   if (err)
1773     {
1774       int i;
1775       int saved_errno = errno;
1776
1777       /* An error occured.  */
1778       for (i = 0; i < GC_COMPONENT_NR; i++)
1779         {
1780           if (src_pathname[i])
1781             {
1782               /* The change was not yet committed.  */
1783               unlink (src_pathname[i]);
1784               if (orig_pathname[i])
1785                 unlink (orig_pathname[i]);
1786             }
1787           else
1788             {
1789               /* The changes were already committed.  FIXME: This is a
1790                  tad dangerous, as we don't know if we don't overwrite
1791                  a version of the file that is even newer than the one
1792                  we just installed.  */
1793               if (orig_pathname[i])
1794                 rename (orig_pathname[i], dest_pathname[i]);
1795               else
1796                 unlink (dest_pathname[i]);
1797             }
1798         }
1799       gc_error (1, saved_errno, "could not commit changes");
1800     }
1801   if (line)
1802     free (line);
1803 }