2004-02-25 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.  */
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 value of this option.  */
390   char *new_value;
391 };
392 typedef struct gc_option gc_option_t;
393
394 /* Use this macro to terminate an option list.  */
395 #define GC_OPTION_NULL { NULL }
396
397 \f
398 /* The options of the GC_COMPONENT_GPG_AGENT component.  */
399 static gc_option_t gc_options_gpg_agent[] =
400  {
401    GC_OPTION_NULL
402  };
403
404
405 /* The options of the GC_COMPONENT_SCDAEMON component.  */
406 static gc_option_t gc_options_scdaemon[] =
407  {
408    GC_OPTION_NULL
409  };
410
411
412 /* The options of the GC_COMPONENT_GPGSM component.  */
413 static gc_option_t gc_options_gpgsm[] =
414  {
415    GC_OPTION_NULL
416  };
417
418
419 /* The options of the GC_COMPONENT_DIRMNGR component.  */
420 static gc_option_t gc_options_dirmngr[] =
421  {
422    /* The configuration file to which we write the changes.  */
423    { "gpgconf-dirmngr.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
424      NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
425
426    { "Monitor",
427      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
428      NULL, "Options controlling the diagnostic output" },
429    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
430      "dirmngr", "verbose",
431      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
432    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
433      "dirmngr", "be somewhat more quiet",
434      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
435    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
436      NULL, NULL,
437      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
438
439    { "Format",
440      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
441      NULL, "Options controlling the format of the output" },
442    { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
443      "dirmngr", "sh-style command output",
444      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
445    { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
446      "dirmngr", "csh-style command output",
447      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
448    
449    { "Configuration",
450      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
451      NULL, "Options controlling the configuration" },
452    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
453      "dirmngr", "|FILE|read options from FILE",
454      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
455
456    { "Debug",
457      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
458      "dirmngr", "Options useful for debugging" },
459    { "debug", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
460      "dirmngr", "|FLAGS|set the debugging FLAGS",
461      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
462    { "debug-all", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
463      "dirmngr", "set all debugging flags",
464      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
465    { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
466      "dirmngr", "do not detach from the console",
467      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
468    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
469      "dirmngr", "|FILE|write logs to FILE",
470      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
471    { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
472      NULL, NULL,
473      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
474    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
475      NULL, NULL,
476      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
477
478    { "Enforcement",
479      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
480      NULL, "Options controlling the interactivity and enforcement" },
481    { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
482      "dirmngr", "run without asking a user",
483      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
484    { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
485      "dirmngr", "force loading of outdated CRLs",
486      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
487
488    { "LDAP",
489      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
490      NULL, "Configuration of LDAP servers to use" },
491    { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
492      "dirmngr", "add new servers discovered in CRL distribution points"
493      " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
494    { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
495      "dirmngr", "|N|set LDAP timeout to N seconds",
496      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
497    /* The following entry must not be removed, as it is required for
498       the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST.  */
499    { "ldapserverlist-file",
500      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
501      "dirmngr", "|FILE|read LDAP server list from FILE",
502      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
503    /* This entry must come after at least one entry for
504       GC_BACKEND_DIRMNGR in this component, so that the entry for
505       "ldapserverlist-file will be initialized before this one.  */
506    { "LDAP Server", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
507      NULL, "LDAP server list",
508      GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST },
509
510    { "CRL",
511      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
512      NULL, "Configuration of the CRL" },
513    { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
514      "dirmngr", "|N|do not return more than N items in one query",
515      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
516
517    GC_OPTION_NULL
518  };
519
520 \f
521 /* Component system.  Each component is a set of options that can be
522    configured at the same time.  If you change this, don't forget to
523    update GC_COMPONENT below.  */
524 typedef enum
525   {
526     /* The GPG Agent.  */
527     GC_COMPONENT_GPG_AGENT,
528
529     /* The Smardcard Daemon.  */
530     GC_COMPONENT_SCDAEMON,
531
532     /* GPG for S/MIME.  */
533     GC_COMPONENT_GPGSM,
534
535     /* The LDAP Directory Manager for CRLs.  */
536     GC_COMPONENT_DIRMNGR,
537
538     /* The number of components.  */
539     GC_COMPONENT_NR
540   } gc_component_t;
541
542
543 /* The information associated with each component.  */
544 static struct
545 {
546   /* The name of this component.  Must not contain a colon (':')
547      character.  */
548   const char *name;
549
550   /* The gettext domain for the description DESC.  If this is NULL,
551      then the description is not translated.  */
552   const char *desc_domain;
553
554   /* The description for this domain.  */
555   const char *desc;
556
557   /* The list of options for this component, terminated by
558      GC_OPTION_NULL.  */
559   gc_option_t *options;
560 } gc_component[] =
561   {
562     { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent },
563     { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon },
564     { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm },
565     { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr }
566   };
567
568 \f
569 /* Robust version of dgettext.  */
570 static const char *
571 my_dgettext (const char *domain, const char *msgid)
572 {
573   if (domain)
574     {
575       char *text = dgettext (domain, msgid);
576       return text ? text : msgid;
577     }
578   else
579     return msgid;
580 }
581
582
583 /* Percent-Escape special characters.  The string is valid until the
584    next invocation of the function.  */
585 static char *
586 percent_escape (const char *src)
587 {
588   static char *esc_str;
589   static int esc_str_len;
590   int new_len = 3 * strlen (src) + 1;
591   char *dst;
592
593   if (esc_str_len < new_len)
594     {
595       char *new_esc_str = realloc (esc_str, new_len);
596       if (!new_esc_str)
597         gc_error (1, errno, "can not escape string");
598       esc_str = new_esc_str;
599       esc_str_len = new_len;
600     }
601
602   dst = esc_str;
603   while (*src)
604     {
605       if (*src == '%')
606         {
607           *(dst++) = '%';
608           *(dst++) = '2';
609           *(dst++) = '5';
610         }         
611       else if (*src == ':')
612         {
613           /* The colon is used as field separator.  */
614           *(dst++) = '%';
615           *(dst++) = '3';
616           *(dst++) = 'a';
617         }
618       else if (*src == ',')
619         {
620           /* The comma is used as list separator.  */
621           *(dst++) = '%';
622           *(dst++) = '2';
623           *(dst++) = 'c';
624         }
625       else
626         *(dst++) = *(src);
627       src++;
628     }
629   *dst = '\0';
630   return esc_str;
631 }
632
633
634 /* Convert two hexadecimal digits from STR to the value they
635    represent.  Returns -1 if one of the characters is not a
636    hexadecimal digit.  */
637 static int
638 hextobyte (const char *str)
639 {
640   int val = 0;
641   int i;
642
643 #define NROFHEXDIGITS 2
644   for (i = 0; i < NROFHEXDIGITS; i++)
645     {
646       if (*str >= '0' && *str <= '9')
647         val += *str - '0';
648       else if (*str >= 'A' && *str <= 'F')
649         val += 10 + *str - 'A';
650       else if (*str >= 'a' && *str <= 'f')
651         val += 10 + *str - 'a';
652       else
653         return -1;
654       if (i < NROFHEXDIGITS - 1)
655         val *= 16;
656       str++;
657     }
658   return val;
659 }
660
661
662
663 /* Percent-Deescape special characters.  The string is valid until the
664    next invocation of the function.  */
665 static char *
666 percent_deescape (const char *src)
667 {
668   static char *str;
669   static int str_len;
670   int new_len = 3 * strlen (src) + 1;
671   char *dst;
672
673   if (str_len < new_len)
674     {
675       char *new_str = realloc (str, new_len);
676       if (!new_str)
677         gc_error (1, errno, "can not deescape string");
678       str = new_str;
679       str_len = new_len;
680     }
681
682   dst = str;
683   while (*src)
684     {
685       if (*src == '%')
686         {
687           int val = hextobyte (src + 1);
688
689           if (val < 0)
690             gc_error (1, 0, "malformed end of string %s", src);
691
692           *(dst++) = (char) val;
693           src += 3;
694         }         
695       else
696         *(dst++) = *(src++);
697     }
698   *dst = '\0';
699   return str;
700 }
701
702 \f
703 /* List all components that are available.  */
704 void
705 gc_component_list_components (FILE *out)
706 {
707   gc_component_t idx;
708
709   for (idx = 0; idx < GC_COMPONENT_NR; idx++)
710     {
711       const char *desc = gc_component[idx].desc;
712       desc = my_dgettext (gc_component[idx].desc_domain, desc);
713       fprintf (out, "%s:%s\n", gc_component[idx].name, percent_escape (desc));
714     }
715 }
716
717 \f
718 /* Find the component with the name NAME.  Returns -1 if not
719    found.  */
720 int
721 gc_component_find (const char *name)
722 {
723   gc_component_t idx;
724
725   for (idx = 0; idx < GC_COMPONENT_NR; idx++)
726     {
727       if (!strcmp (name, gc_component[idx].name))
728         return idx;
729     }
730   return -1;
731 }
732
733 \f
734 /* List all options of the component COMPONENT.  */
735 void
736 gc_component_list_options (int component, FILE *out)
737 {  
738   const gc_option_t *option = gc_component[component].options;
739
740   while (option->name)
741     {
742       const char *desc = NULL;
743       char *arg_name = NULL;
744
745       /* Do not output unknown or internal options.  */
746       if (!(option->flags & GC_OPT_FLAG_GROUP)
747           && (!option->active || option->level == GC_LEVEL_INTERNAL))
748         {
749           option++;
750           continue;
751         }
752
753       if (option->desc)
754         {
755           desc = my_dgettext (option->desc_domain, option->desc);
756
757           if (*desc == '|')
758             {
759               const char *arg_tail = strchr (&desc[1], '|');
760
761               if (arg_tail)
762                 {
763                   int arg_len = arg_tail - &desc[1];
764                   arg_name = xmalloc (arg_len + 1);
765                   memcpy (arg_name, &desc[1], arg_len);
766                   arg_name[arg_len] = '\0';
767                   desc = arg_tail + 1;
768                 }
769             }
770         }
771
772       /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR
773          ORDER IS PART OF THE EXTERNAL INTERFACE.  YOU MUST NOT REMOVE
774          ANY FIELDS.  */
775
776       /* The name field.  */
777       fprintf (out, "%s", option->name);
778
779       /* The flags field.  */
780       fprintf (out, ":%lu", option->flags);
781       if (opt.verbose)
782         {
783           putc (' ', out);
784           
785           if (!option->flags)
786             fprintf (out, "none");
787           else
788             {
789               unsigned long flags = option->flags;
790               unsigned long flag = 0;
791               unsigned long first = 1;
792
793               while (flags)
794                 {
795                   if (flags & 1)
796                     {
797                       if (first)
798                         first = 0;
799                       else
800                         putc (',', out);
801                       fprintf (out, "%s", gc_flag[flag].name);
802                     }
803                   flags >>= 1;
804                   flag++;
805                 }
806             }
807         }
808
809       /* The level field.  */
810       fprintf (out, ":%u", option->level);
811       if (opt.verbose)
812         fprintf (out, " %s", gc_level[option->level].name);
813
814       /* The description field.  */
815       fprintf (out, ":%s", desc ? percent_escape (desc) : "");
816
817       /* The type field.  */
818       fprintf (out, ":%u", option->arg_type);
819       if (opt.verbose)
820         fprintf (out, " %s", gc_arg_type[option->arg_type].name);
821
822       /* The alternate type field.  */
823       fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback);
824       if (opt.verbose)
825         fprintf (out, " %s",
826                  gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
827
828       /* The argument name field.  */
829       fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : "");
830       if (arg_name)
831         xfree (arg_name);
832
833       /* The default value field.  */
834       fprintf (out, ":%s", option->default_value ? option->default_value : "");
835
836       /* The default argument field.  */
837       fprintf (out, ":%s", option->default_arg ? option->default_arg : "");
838
839       /* The value field.  */
840       if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
841           && (option->flags & GC_OPT_FLAG_LIST)
842           && option->value)
843         /* The special format "1,1,1,1,...,1" is converted to a number
844            here.  */
845         fprintf (out, ":%u", (strlen (option->value) + 1) / 2);
846       else
847         fprintf (out, ":%s", option->value ? option->value : "");
848
849       /* ADD NEW FIELDS HERE.  */
850
851       putc ('\n', out);
852       option++;
853     }
854 }
855
856
857 /* Find the option NAME in component COMPONENT, for the backend
858    BACKEND.  If BACKEND is GC_BACKEND_ANY, any backend will match.  */
859 static gc_option_t *
860 find_option (gc_component_t component, const char *name,
861              gc_backend_t backend)
862 {
863   gc_option_t *option = gc_component[component].options;
864   while (option->name)
865     {
866       if (!(option->flags & GC_OPT_FLAG_GROUP)
867           && !strcmp (option->name, name)
868           && (backend == GC_BACKEND_ANY || option->backend == backend))
869         break;
870       option++;
871     }
872   return option->name ? option : NULL;
873 }
874
875 \f
876 /* Determine the configuration pathname for the component COMPONENT
877    and backend BACKEND.  */
878 static char *
879 get_config_pathname (gc_component_t component, gc_backend_t backend)
880 {
881   char *pathname = NULL;
882   gc_option_t *option = find_option
883     (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
884   assert (option);
885   assert (option->arg_type == GC_ARG_TYPE_PATHNAME);
886   assert (!(option->flags & GC_OPT_FLAG_LIST));
887
888   if (!option->active || !option->default_value)
889     gc_error (1, 0, "Option %s, needed by backend %s, was not initialized",
890               gc_backend[backend].option_config_filename,
891               gc_backend[backend].name);
892
893   if (option->value && *option->value)
894     pathname = percent_deescape (&option->value[1]);
895   else if (option->default_value && *option->default_value)
896     pathname = percent_deescape (&option->default_value[1]);
897   else
898     pathname = "";
899
900   if (pathname[0] != '/')
901     gc_error (1, 0, "Option %s, needed by backend %s, is not absolute",
902               gc_backend[backend].option_config_filename,
903               gc_backend[backend].name);
904
905   return pathname;
906 }
907
908 \f
909 /* Retrieve the options for the component COMPONENT from backend
910    BACKEND, which we already know is a program-type backend.  */
911 static void
912 retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
913 {
914   char *cmd_line;
915   char *line = NULL;
916   size_t line_len = 0;
917   ssize_t length;
918   FILE *config;
919   char *config_pathname;
920
921   cmd_line = xasprintf ("%s --gpgconf-list", gc_backend[backend].program);
922
923   config = popen (cmd_line, "r");
924   if (!config)
925     gc_error (1, errno, "could not gather active options from %s", cmd_line);
926
927   while ((length = getline (&line, &line_len, config)) > 0)
928     {
929       gc_option_t *option;
930       char *linep;
931       unsigned long flags = 0;
932       char *default_value = NULL;
933       
934       /* Strip newline and carriage return, if present.  */
935       while (length > 0
936              && (line[length - 1] == '\n' || line[length - 1] == '\r'))
937         line[--length] = '\0';
938
939       linep = strchr (line, ':');
940       if (linep)
941         *(linep++) = '\0';
942       
943       /* Extract additional flags.  Default to none.  */
944       if (linep)
945         {
946           char *end;
947           char *tail;
948
949           end = strchr (linep, ':');
950           if (end)
951             *(end++) = '\0';
952
953           errno = 0;
954           flags = strtoul (linep, &tail, 0);
955           if (errno)
956             gc_error (1, errno, "malformed flags in option %s from %s", line, cmd_line);
957           if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
958             gc_error (1, 0, "garbage after flags in option %s from %s", line, cmd_line);
959
960           linep = end;
961         }
962
963       /* Extract default value, if present.  Default to empty if
964          not.  */
965       if (linep)
966         {
967           char *end;
968
969           end = strchr (linep, ':');
970           if (end)
971             *(end++) = '\0';
972
973           if (flags & GC_OPT_FLAG_DEFAULT)
974             default_value = linep;
975
976           linep = end;
977         }
978
979       /* Look up the option in the component and install the
980          configuration data.  */
981       option = find_option (component, line, backend);
982       if (option)
983         {
984           if (option->active)
985             gc_error (1, errno, "option %s returned twice from %s",
986                       line, cmd_line);
987           option->active = 1;
988
989           option->flags |= flags;
990           if (default_value && *default_value)
991             option->default_value = xstrdup (default_value);
992         }
993     }
994   if (ferror (config))
995     gc_error (1, errno, "error reading from %s", cmd_line);
996   if (fclose (config) && ferror (config))
997     gc_error (1, errno, "error closing %s", cmd_line);
998   xfree (cmd_line);
999
1000   /* At this point, we can parse the configuration file.  */
1001   config_pathname = get_config_pathname (component, backend);
1002
1003   config = fopen (config_pathname, "r");
1004   if (!config)
1005     gc_error (0, errno, "warning: can not open config file %s",
1006               config_pathname);
1007   else
1008     {
1009       while ((length = getline (&line, &line_len, config)) > 0)
1010         {
1011           char *name;
1012           char *value;
1013           gc_option_t *option;
1014           
1015           name = line;
1016           while (*name == ' ' || *name == '\t')
1017             name++;
1018           if (!*name || *name == '#' || *name == '\r' || *name == '\n')
1019             continue;
1020
1021           value = name;
1022           while (*value && *value != ' ' && *value != '\t'
1023                  && *value != '#' && *value != '\r' && *value != '\n')
1024             value++;
1025           if (*value == ' ' || *value == '\t')
1026             {
1027               char *end;
1028
1029               *(value++) = '\0';
1030               while (*value == ' ' || *value == '\t')
1031                 value++;
1032
1033               end = value;
1034               while (*end && *end != '#' && *end != '\r' && *end != '\n')
1035                 end++;
1036               while (end > value && (end[-1] == ' ' || end[-1] == '\t'))
1037                 end--;
1038               *end = '\0';
1039             }
1040           else
1041             *value = '\0';
1042
1043           /* Look up the option in the component and install the
1044              configuration data.  */
1045           option = find_option (component, line, backend);
1046           if (option)
1047             {
1048               char *opt_value;
1049
1050               if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
1051                 {
1052                   if (*value)
1053                     gc_error (0, 0,
1054                               "warning: ignoring argument %s for option %s",
1055                               value, name);
1056                   opt_value = xstrdup ("1");
1057                 }
1058               else if (gc_arg_type[option->arg_type].fallback
1059                        == GC_ARG_TYPE_STRING)
1060                 opt_value = xasprintf ("\"%s", percent_escape (value));
1061               else
1062                 {
1063                   /* FIXME: Verify that the number is sane.  */
1064                   opt_value = xstrdup (value);
1065                 }
1066
1067               /* Now enter the option into the table.  */
1068               if (!(option->flags & GC_OPT_FLAG_LIST))
1069                 {
1070                   if (option->value)
1071                     free (option->value);
1072                   option->value = opt_value;
1073                 }
1074               else
1075                 {
1076                   if (!option->value)
1077                     option->value = opt_value;
1078                   else
1079                     {
1080                       char *opt_val = opt_value;
1081
1082                       if (gc_arg_type[option->arg_type].fallback
1083                           == GC_ARG_TYPE_STRING)
1084                         opt_val++;
1085
1086                       /* FIXME.  For type none arguments, this is
1087                          wrong.  */
1088                       option->value = xasprintf ("%s,%s", option->value,
1089                                                  opt_val);
1090                       xfree (opt_value);
1091                     }
1092                 }
1093             }
1094         }
1095
1096       if (ferror (config))
1097         gc_error (1, errno, "error reading from %s", config_pathname);
1098       if (fclose (config) && ferror (config))
1099         gc_error (1, errno, "error closing %s", config_pathname);
1100     }
1101
1102   if (line)
1103     free (line);
1104 }
1105
1106
1107 /* Retrieve the options for the component COMPONENT from backend
1108    BACKEND, which we already know is of type file list.  */ 
1109 static void
1110 retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
1111 {
1112   gc_option_t *list_option;
1113   char *list_pathname;
1114   FILE *list_file;
1115   char *line = NULL;
1116   size_t line_len = 0;
1117   ssize_t length;
1118   char *list = NULL;
1119
1120   list_option = find_option (component,
1121                              gc_backend[backend].option_name, GC_BACKEND_ANY);
1122   assert (list_option);
1123   assert (!list_option->active);
1124
1125   list_pathname = get_config_pathname (component, backend);
1126   list_file = fopen (list_pathname, "r");
1127   if (!list_file)
1128     gc_error (0, errno, "warning: can not open list file %s", list_pathname);
1129   else
1130     {
1131
1132       while ((length = getline (&line, &line_len, list_file)) > 0)
1133         {
1134           char *start;
1135           char *end;
1136           char *new_list;
1137
1138           start = line;
1139           while (*start == ' ' || *start == '\t')
1140             start++;
1141           if (!*start || *start == '#' || *start == '\r' || *start == '\n')
1142             continue;
1143
1144           end = start;
1145           while (*end && *end != '#' && *end != '\r' && *end != '\n')
1146             end++;
1147           /* Walk back to skip trailing white spaces.  Looks evil, but
1148              works because of the conditions on START and END imposed
1149              at this point (END is at least START + 1, and START is
1150              not a whitespace character).  */
1151           while (*(end - 1) == ' ' || *(end - 1) == '\t')
1152             end--;
1153           *end = '\0';
1154           /* FIXME: Oh, no!  This is so lame!  Use realloc and really
1155              append.  */
1156           if (list)
1157             {
1158               new_list = xasprintf ("%s,%s", list, percent_escape (start));
1159               xfree (list);
1160               list = new_list;
1161             }
1162           else
1163             list = xasprintf ("\"%s", percent_escape (start));
1164         }
1165       if (ferror (list_file))
1166         gc_error (1, errno, "can not read list file %s", list_pathname);
1167     }
1168
1169   list_option->active = 1;
1170   list_option->value = list;
1171
1172   if (line)
1173     free (line);
1174 }
1175
1176
1177 /* Retrieve the currently active options and their defaults from all
1178    involved backends for this component.  */
1179 void
1180 gc_component_retrieve_options (int component)
1181 {
1182   int backend_seen[GC_BACKEND_NR];
1183   gc_backend_t backend;
1184   gc_option_t *option = gc_component[component].options;
1185
1186   for (backend = 0; backend < GC_BACKEND_NR; backend++)
1187     backend_seen[backend] = 0;
1188
1189   while (option->name)
1190     {
1191       if (!(option->flags & GC_OPT_FLAG_GROUP))
1192         {
1193           backend = option->backend;
1194
1195           if (backend_seen[backend])
1196             {
1197               option++;
1198               continue;
1199             }
1200           backend_seen[backend] = 1;
1201
1202           assert (backend != GC_BACKEND_ANY);
1203
1204           if (gc_backend[backend].program)
1205             retrieve_options_from_program (component, backend);
1206           else
1207             retrieve_options_from_file (component, backend);
1208         }
1209       option++;
1210     }
1211 }
1212
1213 \f
1214 /* Perform a simple validity check based on the type.  */
1215 static void
1216 option_check_validity (gc_option_t *option, const char *new_value)
1217 {
1218   if (option->new_value)
1219     gc_error (1, 0, "option %s already changed", option->name);
1220
1221   if (!*new_value)
1222     return;
1223
1224   /* FIXME.  Verify that lists are lists, numbers are numbers, strings
1225      are strings, etc.  */
1226 }
1227
1228
1229 /* Create and verify the new configuration file for the specified
1230    backend and component.  Returns 0 on success and -1 on error.  */
1231 static int
1232 change_options_file (gc_component_t component, gc_backend_t backend,
1233                      char **src_filenamep, char **dest_filenamep,
1234                      char **orig_filenamep)
1235 {
1236   /* FIXME.  */
1237   assert (!"Not implemented.");
1238   return -1;
1239 }
1240
1241
1242 /* Create and verify the new configuration file for the specified
1243    backend and component.  Returns 0 on success and -1 on error.  */
1244 static int
1245 change_options_program (gc_component_t component, gc_backend_t backend,
1246                         char **src_filenamep, char **dest_filenamep,
1247                         char **orig_filenamep)
1248 {
1249   static const char marker[] = "###+++--- GPGConf ---+++###";
1250   /* True if we are within the marker in the config file.  */
1251   int in_marker = 0;
1252   gc_option_t *option;
1253   char *line = NULL;
1254   size_t line_len;
1255   ssize_t length;
1256   int res;
1257   int fd;
1258   FILE *src_file = NULL;
1259   FILE *dest_file = NULL;
1260   char *src_filename;
1261   char *dest_filename;
1262   char *orig_filename;
1263
1264   /* FIXME.  Throughout the function, do better error reporting.  */
1265   dest_filename = xstrdup (get_config_pathname (component, backend));
1266   src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ());
1267   orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ());
1268
1269   res = link (dest_filename, orig_filename);
1270   if (res < 0 && errno != ENOENT)
1271     return -1;
1272   if (res < 0)
1273     {
1274       xfree (orig_filename);
1275       orig_filename = NULL;
1276     }
1277   /* We now initialize the return strings, so the caller can do the
1278      cleanup for us.  */
1279   *src_filenamep = src_filename;
1280   *dest_filenamep = dest_filename;
1281   *orig_filenamep = orig_filename;
1282
1283   /* Use open() so that we can use O_EXCL.  */
1284   fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
1285   if (fd < 0)
1286     return -1;
1287   src_file = fdopen (fd, "w");
1288   res = errno;
1289   if (!src_file)
1290     {
1291       errno = res;
1292       return -1;
1293     }
1294
1295   /* Only if ORIG_FILENAME is not NULL did the configuration file
1296      exist already.  In this case, we will copy its content into the
1297      new configuration file, changing it to our liking in the
1298      process.  */
1299   if (orig_filename)
1300     {
1301       dest_file = fopen (dest_filename, "r");
1302       if (!dest_file)
1303         goto change_one_err;
1304
1305       while ((length = getline (&line, &line_len, dest_file)) > 0)
1306         {
1307           int disable = 0;
1308           char *start;
1309           char *end;
1310
1311           if (!strncmp (marker, line, sizeof (marker) - 1))
1312             {
1313               if (!in_marker)
1314                 in_marker = 1;
1315               else
1316                 break;
1317             }
1318
1319           start = line;
1320           while (*start == ' ' || *start == '\t')
1321             start++;
1322           if (*start && *start != '\r' && *start != '\n' && *start != '#')
1323             {
1324               char saved_end;
1325
1326               end = start;
1327               while (*end && *end != ' ' && *end != '\t'
1328                      && *end != '\r' && *end != '\n' && *end != '#')
1329                 end++;
1330               saved_end = *end;
1331               *end = '\0';
1332
1333               option = find_option (component, start, backend);
1334               *end = saved_end;
1335               if (option && option->new_value)
1336                 disable = 1;
1337             }
1338           if (disable)
1339             {
1340               if (!in_marker)
1341                 {
1342                   fprintf (src_file,
1343                            "# GPGConf disabled this option here at %s\n",
1344                            asctimestamp (gnupg_get_time ()));
1345                   if (ferror (src_file))
1346                     goto change_one_err;
1347                   fprintf (src_file, "# %s", line);
1348                   if (ferror (src_file))
1349                     goto change_one_err;
1350                 }
1351             }
1352           else
1353             {
1354               fprintf (src_file, "%s", line);
1355               if (ferror (src_file))
1356                 goto change_one_err;
1357             }
1358         }
1359       if (ferror (dest_file))
1360         goto change_one_err;
1361     }
1362
1363   if (!in_marker)
1364     {
1365       /* There was no marker.  This is the first time we edit the
1366          file.  We add our own marker at the end of the file and
1367          proceed.  Note that we first write a newline, this guards us
1368          against files which lack the newline at the end of the last
1369          line, while it doesn't hurt us in all other cases.  */
1370       fprintf (src_file, "\n%s\n", marker);
1371       if (ferror (src_file))
1372         goto change_one_err;
1373     }
1374   /* At this point, we have copied everything up to the end marker
1375      into the new file, except for the options we are going to change.
1376      Now, dump the changed options (except for those we are going to
1377      revert to their default), and write the end marker, possibly
1378      followed by the rest of the original file.  */
1379   option = gc_component[component].options;
1380   while (option->name)
1381     {
1382       /* FIXME: Add support for lists.  */
1383       if (!(option->flags & GC_OPT_FLAG_GROUP)
1384           && option->backend == backend
1385           && option->new_value
1386           && *option->new_value)
1387         {
1388           if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
1389             fprintf (src_file, "%s %s\n", option->name,
1390                      percent_deescape (&option->new_value[1]));
1391           else if (option->arg_type == GC_ARG_TYPE_NONE)
1392             fprintf (src_file, "%s\n", option->name);
1393           else
1394             fprintf (src_file, "%s %s\n", option->name, option->new_value);
1395           if (ferror (src_file))
1396             goto change_one_err;
1397         }
1398       option++;
1399     }
1400
1401   fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
1402   if (ferror (src_file))
1403     goto change_one_err;
1404
1405   if (!in_marker)
1406     {
1407       fprintf (src_file, "# GPGConf edited this configuration file.\n");
1408       if (ferror (src_file))
1409         goto change_one_err;
1410       fprintf (src_file, "# It will disable options before this marked "
1411                "block, but it will\n");
1412       if (ferror (src_file))
1413         goto change_one_err;
1414       fprintf (src_file, "# never change anything below these lines.\n");
1415       if (ferror (src_file))
1416         goto change_one_err;
1417     }
1418   if (dest_file)
1419     {
1420       while ((length = getline (&line, &line_len, dest_file)) > 0)
1421         {
1422           fprintf (src_file, "%s", line);
1423           if (ferror (src_file))
1424             goto change_one_err;
1425         }
1426       if (ferror (dest_file))
1427         goto change_one_err;
1428     }
1429   if (line)
1430     free (line);
1431   res = fclose (src_file);
1432   if (res)
1433     {
1434       res = errno;
1435       close (fd);
1436       if (dest_file)
1437         fclose (dest_file);
1438       errno = res;
1439       return -1;
1440     }
1441   close (fd);
1442   if (dest_file)
1443     {
1444       res = fclose (dest_file);
1445       if (res)
1446         return -1;
1447     }
1448   return 0;
1449
1450  change_one_err:
1451   if (line)
1452     free (line);
1453   res = errno;
1454   if (src_file)
1455     {
1456       fclose (src_file);
1457       close (fd);
1458     }
1459   if (dest_file)
1460     fclose (dest_file);
1461   errno = res;
1462   return -1;
1463 }
1464
1465 /* Read the modifications from IN and apply them.  */
1466 void
1467 gc_component_change_options (int component, FILE *in)
1468 {
1469   int err = 0;
1470   char *src_pathname[GC_BACKEND_NR];
1471   char *dest_pathname[GC_BACKEND_NR];
1472   char *orig_pathname[GC_BACKEND_NR];
1473   gc_backend_t backend;
1474   gc_option_t *option;
1475   char *line = NULL;
1476   size_t line_len = 0;
1477   ssize_t length;
1478
1479   for (backend = 0; backend < GC_BACKEND_NR; backend++)
1480     {
1481       src_pathname[backend] = NULL;
1482       dest_pathname[backend] = NULL;
1483       orig_pathname[backend] = NULL;
1484     }
1485
1486   while ((length = getline (&line, &line_len, in)) > 0)
1487     {
1488       char *linep;
1489       unsigned long flags = 0;
1490       char *new_value = NULL;
1491
1492       /* Strip newline and carriage return, if present.  */
1493       while (length > 0
1494              && (line[length - 1] == '\n' || line[length - 1] == '\r'))
1495         line[--length] = '\0';
1496
1497       linep = strchr (line, ':');
1498       if (linep)
1499         *(linep++) = '\0';
1500
1501       /* Extract additional flags.  Default to none.  */
1502       if (linep)
1503         {
1504           char *end;
1505           char *tail;
1506
1507           end = strchr (linep, ':');
1508           if (end)
1509             *(end++) = '\0';
1510
1511           errno = 0;
1512           flags = strtoul (linep, &tail, 0);
1513           if (errno)
1514             gc_error (1, errno, "malformed flags in option %s", line);
1515           if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
1516             gc_error (1, 0, "garbage after flags in option %s", line);
1517
1518           linep = end;
1519         }
1520
1521       /* Extract default value, if present.  Default to empty if
1522          not.  */
1523       if (linep)
1524         {
1525           char *end;
1526
1527           end = strchr (linep, ':');
1528           if (end)
1529             *(end++) = '\0';
1530
1531           if (!(flags & GC_OPT_FLAG_DEFAULT))
1532             new_value = linep;
1533
1534           linep = end;
1535         }
1536
1537       option = find_option (component, line, GC_BACKEND_ANY);
1538       if (!option)
1539         gc_error (1, 0, "unknown option %s", line);
1540
1541       /* FIXME: This is not correct, as it ignores the optional arg
1542          case.  */
1543       if (flags & GC_OPT_FLAG_DEFAULT)
1544         new_value = "";
1545
1546       option_check_validity (option, new_value);
1547       option->new_value = xstrdup (new_value);
1548     }
1549
1550   /* Now that we have collected and locally verified the changes,
1551      write them out to new configuration files, verify them
1552      externally, and then commit them.  */
1553   option = gc_component[component].options;
1554   while (option->name)
1555     {
1556       /* Go on if we have already seen this backend, or if there is
1557          nothing to do.  */
1558       if (src_pathname[option->backend] || !option->new_value)
1559         {
1560           option++;
1561           continue;
1562         }
1563
1564       if (gc_backend[option->backend].program)
1565         err = change_options_program (component, option->backend,
1566                                       &src_pathname[component],
1567                                       &dest_pathname[component],
1568                                       &orig_pathname[component]);
1569       else
1570         err = change_options_file (component, option->backend,
1571                                    &src_pathname[component],
1572                                    &dest_pathname[component],
1573                                    &orig_pathname[component]);
1574         
1575       if (err)
1576         break;
1577           
1578       option++;
1579     }
1580   if (!err)
1581     {
1582       int i;
1583
1584       for (i = 0; i < GC_COMPONENT_NR; i++)
1585         {
1586           if (src_pathname[i])
1587             {
1588               /* FIXME: Make a verification here.  */
1589
1590               assert (dest_pathname[i]);
1591
1592               if (orig_pathname[i])
1593                 err = rename (src_pathname[i], dest_pathname[i]);
1594               else
1595                 {
1596                   /* This is a bit safer than rename() because we
1597                      expect DEST_PATHNAME not to be there.  If it
1598                      happens to be there, this will fail.  */
1599                   err = link (src_pathname[i], dest_pathname[i]);
1600                   if (!err)
1601                     unlink (src_pathname[i]);
1602                 }
1603               if (err)
1604                 break;
1605               src_pathname[i] = NULL;
1606             }
1607         }
1608     }
1609
1610   if (err)
1611     {
1612       int i;
1613       int saved_errno = errno;
1614
1615       /* An error occured.  */
1616       for (i = 0; i < GC_COMPONENT_NR; i++)
1617         {
1618           if (src_pathname[i])
1619             {
1620               /* The change was not yet committed.  */
1621               unlink (src_pathname[i]);
1622               if (orig_pathname[i])
1623                 unlink (orig_pathname[i]);
1624             }
1625           else
1626             {
1627               /* The changes were already committed.  FIXME: This is a
1628                  tad dangerous, as we don't know if we don't overwrite
1629                  a version of the file that is even newer than the one
1630                  we just installed.  */
1631               if (orig_pathname[i])
1632                 rename (orig_pathname[i], dest_pathname[i]);
1633               else
1634                 unlink (dest_pathname[i]);
1635             }
1636         }
1637       gc_error (1, saved_errno, "could not commit changes");
1638     }
1639   if (line)
1640     free (line);
1641 }