Fix copyright line.
[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
180     /* Complex argument types.  */
181
182     /* A complete pathname.  */
183     GC_ARG_TYPE_PATHNAME = 4,
184
185     /* An LDAP server in the format
186        HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN.  */
187     GC_ARG_TYPE_LDAP_SERVER = 5,
188
189     /* A 40 character fingerprint.  */
190     GC_ARG_TYPE_KEY_FPR = 6,
191
192     /* ADD NEW ENTRIES HERE.  */
193
194     /* The number of the above entries.  */
195     GC_ARG_TYPE_NR
196   } gc_arg_type_t;
197
198
199 /* For every argument, we record some information about it in the
200    following struct.  */
201 static struct
202 {
203   /* For every argument type exists a basic argument type that can be
204      used as a fallback for input and validation purposes.  */
205   gc_arg_type_t fallback;
206
207   /* Human-readable name of the type.  */
208   const char *name;
209 } gc_arg_type[GC_ARG_TYPE_NR] =
210   {
211     /* The basic argument types have their own types as fallback.  */
212     { GC_ARG_TYPE_NONE, "none" },
213     { GC_ARG_TYPE_STRING, "string" },
214     { GC_ARG_TYPE_INT32, "int32" },
215     { GC_ARG_TYPE_UINT32, "uint32" },
216
217     /* The complex argument types have a basic type as fallback.  */
218     { GC_ARG_TYPE_STRING, "pathname" },
219     { GC_ARG_TYPE_STRING, "ldap server" },
220     { GC_ARG_TYPE_STRING, "key fpr" },
221   };
222
223
224 /* Every option has an associated expert level, than can be used to
225    hide advanced and expert options from beginners.  If you add to
226    this list, don't forget to update GC_LEVEL below.  YOU MUST NOT
227    CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE
228    EXTERNAL INTERFACE.  */
229 typedef enum
230   {
231     /* The basic options should always be displayed.  */
232     GC_LEVEL_BASIC,
233
234     /* The advanced options may be hidden from beginners.  */
235     GC_LEVEL_ADVANCED,
236
237     /* The expert options should only be displayed to experts.  */
238     GC_LEVEL_EXPERT,
239
240     /* The invisible options should normally never be displayed.  */
241     GC_LEVEL_INVISIBLE,
242
243     /* The internal options are never exported, they mark options that
244        are recorded for internal use only.  */
245     GC_LEVEL_INTERNAL,
246
247     /* ADD NEW ENTRIES HERE.  */
248
249     /* The number of the above entries.  */
250     GC_LEVEL_NR
251   } gc_expert_level_t;
252
253 /* A description for each expert level.  */
254 static struct
255 {
256   const char *name;
257 } gc_level[] =
258   {
259     { "basic" },
260     { "advanced" },
261     { "expert" },
262     { "invisible" },
263     { "internal" }
264   };
265
266
267 /* Option flags.  YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING
268    FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE.  */
269 #define GC_OPT_FLAG_NONE        0
270 /* Some entries in the option list are not options, but mark the
271    beginning of a new group of options.  These entries have the GROUP
272    flag set.  */
273 #define GC_OPT_FLAG_GROUP       (1 << 0)
274 /* The ARG_OPT flag for an option indicates that the argument is
275    optional.  */
276 #define GC_OPT_FLAG_ARG_OPT     (1 << 1)
277 /* The LIST flag for an option indicates that the option can occur
278    several times.  A comma separated list of arguments is used as the
279    argument value.  */
280 #define GC_OPT_FLAG_LIST        (1 << 2)
281 /* The RUNTIME flag for an option indicates that the option can be
282    changed at runtime.  */
283 #define GC_OPT_FLAG_RUNTIME     (1 << 3)
284
285 /* A human-readable description for each flag.  */
286 static struct
287 {
288   const char *name;
289 } gc_flag[] =
290   {
291     { "group" },
292     { "optional arg" },
293     { "list" },
294     { "runtime" }
295   };
296
297
298 /* To each option, or group marker, the information in the GC_OPTION
299    struct is provided.  If you change this, don't forget to update the
300    option list of each component.  */
301 struct gc_option
302 {
303   /* If this is NULL, then this is a terminator in an array of unknown
304      length.  Otherwise, if this entry is a group marker (see FLAGS),
305      then this is the name of the group described by this entry.
306      Otherwise it is the name of the option described by this
307      entry.  The name must not contain a colon.  */
308   const char *name;
309
310   /* The option flags.  If the GROUP flag is set, then this entry is a
311      group marker, not an option, and only the fields LEVEL,
312      DESC_DOMAIN and DESC are valid.  In all other cases, this entry
313      describes a new option and all fields are valid.  */
314   unsigned int flags;
315
316   /* The expert level.  This field is valid for options and groups.  A
317      group has the expert level of the lowest-level option in the
318      group.  */
319   gc_expert_level_t level;
320
321   /* A gettext domain in which the following description can be found.
322      If this is NULL, then DESC is not translated.  Valid for groups
323      and options.  */
324   const char *desc_domain;
325
326   /* A gettext description for this group or option.  If it starts
327      with a '|', then the string up to the next '|' describes the
328      argument, and the description follows the second '|'.  */
329   const char *desc;
330
331   /* The following fields are only valid for options.  */
332
333   /* The type of the option argument.  */
334   gc_arg_type_t arg_type;
335
336   /* The backend that implements this option.  */
337   gc_backend_t backend;
338
339   /* The following fields are set to NULL at startup (because all
340      option's are declared as static variables).  They are at the end
341      of the list so that they can be omitted from the option
342      declarations.  */
343
344   /* This is true if the option is supported by this version of the
345      backend.  */
346   int active;
347
348   /* The default value for this option.  This is NULL if the option is
349      not present in the backend, the empty string if no default is
350      available, and otherwise a quoted string.  */
351   char *default_value;
352
353   /* The current value of this option.  */
354   char *value;
355
356   /* The new value of this option.  */
357   char *new_value;
358 };
359 typedef struct gc_option gc_option_t;
360
361 /* Use this macro to terminate an option list.  */
362 #define GC_OPTION_NULL { NULL }
363
364 \f
365 /* The options of the GC_COMPONENT_GPG_AGENT component.  */
366 static gc_option_t gc_options_gpg_agent[] =
367  {
368    GC_OPTION_NULL
369  };
370
371
372 /* The options of the GC_COMPONENT_DIRMNGR component.  */
373 static gc_option_t gc_options_dirmngr[] =
374  {
375    /* The configuration file to which we write the changes.  */
376    { "gpgconf-dirmngr.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
377      NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
378
379    { "Monitor",
380      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
381      NULL, "Options controlling the diagnostic output" },
382    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
383      "dirmngr", "verbose",
384      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
385    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
386      "dirmngr", "be somewhat more quiet",
387      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
388    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
389      NULL, NULL,
390      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
391
392    { "Format",
393      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
394      NULL, "Options controlling the format of the output" },
395    { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
396      "dirmngr", "sh-style command output",
397      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
398    { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
399      "dirmngr", "csh-style command output",
400      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
401    
402    { "Configuration",
403      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
404      NULL, "Options controlling the configuration" },
405    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
406      "dirmngr", "|FILE|read options from FILE",
407      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
408
409    { "Debug",
410      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
411      "dirmngr", "Options useful for debugging" },
412    { "debug", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
413      "dirmngr", "|FLAGS|set the debugging FLAGS",
414      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
415    { "debug-all", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
416      "dirmngr", "set all debugging flags",
417      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
418    { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
419      "dirmngr", "do not detach from the console",
420      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
421    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
422      "dirmngr", "|FILE|write logs to FILE",
423      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
424    { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
425      NULL, NULL,
426      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
427    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
428      NULL, NULL,
429      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
430
431    { "Enforcement",
432      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
433      NULL, "Options controlling the interactivity and enforcement" },
434    { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
435      "dirmngr", "run without asking a user",
436      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
437    { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
438      "dirmngr", "force loading of outdated CRLs",
439      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
440
441    { "LDAP",
442      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
443      NULL, "Configuration of LDAP servers to use" },
444    { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
445      "dirmngr", "add new servers discovered in CRL distribution points"
446      " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
447    { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
448      "dirmngr", "|N|set LDAP timeout to N seconds",
449      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
450    /* The following entry must not be removed, as it is required for
451       the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST.  */
452    { "ldapserverlist-file",
453      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
454      "dirmngr", "|FILE|read LDAP server list from FILE",
455      GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
456    /* This entry must come after at least one entry for
457       GC_BACKEND_DIRMNGR in this component, so that the entry for
458       "ldapserverlist-file will be initialized before this one.  */
459    { "LDAP Server", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
460      NULL, "LDAP server list",
461      GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST },
462
463    { "CRL",
464      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
465      NULL, "Configuration of the CRL" },
466    { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
467      "dirmngr", "|N|do not return more than N items in one query",
468      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
469
470    GC_OPTION_NULL
471  };
472
473 \f
474 /* Component system.  Each component is a set of options that can be
475    configured at the same time.  If you change this, don't forget to
476    update GC_COMPONENT below.  */
477 typedef enum
478   {
479     /* The GPG Agent.  */
480     GC_COMPONENT_GPG_AGENT,
481
482     /* The LDAP Directory Manager for CRLs.  */
483     GC_COMPONENT_DIRMNGR,
484
485     /* The number of components.  */
486     GC_COMPONENT_NR
487   } gc_component_t;
488
489
490 /* The information associated with each component.  */
491 static struct
492 {
493   /* The name of this component.  Must not contain a colon (':')
494      character.  */
495   const char *name;
496
497   /* The gettext domain for the description DESC.  If this is NULL,
498      then the description is not translated.  */
499   const char *desc_domain;
500
501   /* The description for this domain.  */
502   const char *desc;
503
504   /* The list of options for this component, terminated by
505      GC_OPTION_NULL.  */
506   gc_option_t *options;
507 } gc_component[] =
508   {
509     { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent },
510     { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr }
511   };
512
513 \f
514 /* Robust version of dgettext.  */
515 static const char *
516 my_dgettext (const char *domain, const char *msgid)
517 {
518   if (domain)
519     {
520       char *text = dgettext (domain, msgid);
521       return text ? text : msgid;
522     }
523   else
524     return msgid;
525 }
526
527
528 /* Percent-Escape special characters.  The string is valid until the
529    next invocation of the function.  */
530 static char *
531 percent_escape (const char *src)
532 {
533   static char *esc_str;
534   static int esc_str_len;
535   int new_len = 3 * strlen (src) + 1;
536   char *dst;
537
538   if (esc_str_len < new_len)
539     {
540       char *new_esc_str = realloc (esc_str, new_len);
541       if (!new_esc_str)
542         gc_error (1, errno, "can not escape string");
543       esc_str = new_esc_str;
544       esc_str_len = new_len;
545     }
546
547   dst = esc_str;
548   while (*src)
549     {
550       if (*src == '%')
551         {
552           *(dst++) = '%';
553           *(dst++) = '2';
554           *(dst++) = '5';
555         }         
556       else if (*src == ':')
557         {
558           /* The colon is used as field separator.  */
559           *(dst++) = '%';
560           *(dst++) = '3';
561           *(dst++) = 'a';
562         }
563       else if (*src == ',')
564         {
565           /* The comma is used as list separator.  */
566           *(dst++) = '%';
567           *(dst++) = '2';
568           *(dst++) = 'c';
569         }
570       else
571         *(dst++) = *(src);
572       src++;
573     }
574   *dst = '\0';
575   return esc_str;
576 }
577
578
579 \f
580 /* List all components that are available.  */
581 void
582 gc_component_list_components (FILE *out)
583 {
584   gc_component_t idx;
585
586   for (idx = 0; idx < GC_COMPONENT_NR; idx++)
587     {
588       const char *desc = gc_component[idx].desc;
589       desc = my_dgettext (gc_component[idx].desc_domain, desc);
590       fprintf (out, "%s:%s\n", gc_component[idx].name, percent_escape (desc));
591     }
592 }
593
594 \f
595 /* Find the component with the name NAME.  Returns -1 if not
596    found.  */
597 int
598 gc_component_find (const char *name)
599 {
600   gc_component_t idx;
601
602   for (idx = 0; idx < GC_COMPONENT_NR; idx++)
603     {
604       if (!strcmp (name, gc_component[idx].name))
605         return idx;
606     }
607   return -1;
608 }
609
610 \f
611 /* List all options of the component COMPONENT.  */
612 void
613 gc_component_list_options (int component, FILE *out)
614 {  
615   const gc_option_t *option = gc_component[component].options;
616
617   while (option->name)
618     {
619       const char *desc = NULL;
620       char *arg_name = NULL;
621
622       /* Do not output unknown or internal options.  */
623       if (!option->active || option->level == GC_LEVEL_INTERNAL)
624         {
625           option++;
626           continue;
627         }
628
629       if (option->desc)
630         {
631           desc = my_dgettext (option->desc_domain, option->desc);
632
633           if (*desc == '|')
634             {
635               const char *arg_tail = strchr (&desc[1], '|');
636
637               if (arg_tail)
638                 {
639                   int arg_len = arg_tail - &desc[1];
640                   arg_name = xmalloc (arg_len + 1);
641                   memcpy (arg_name, &desc[1], arg_len);
642                   arg_name[arg_len] = '\0';
643                   desc = arg_tail + 1;
644                 }
645             }
646         }
647
648       /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR
649          ORDER IS PART OF THE EXTERNAL INTERFACE.  YOU MUST NOT REMOVE
650          ANY FIELDS.  */
651
652       /* The name field.  */
653       fprintf (out, "%s", option->name);
654
655       /* The flags field.  */
656       fprintf (out, ":%u", option->flags);
657       if (opt.verbose)
658         {
659           putc (' ', out);
660           
661           if (!option->flags)
662             fprintf (out, "none");
663           else
664             {
665               unsigned int flags = option->flags;
666               unsigned int flag = 0;
667               unsigned int first = 1;
668
669               while (flags)
670                 {
671                   if (flags & 1)
672                     {
673                       if (first)
674                         first = 0;
675                       else
676                         putc (',', out);
677                       fprintf (out, "%s", gc_flag[flag].name);
678                     }
679                   flags >>= 1;
680                   flag++;
681                 }
682             }
683         }
684
685       /* The level field.  */
686       fprintf (out, ":%u", option->level);
687       if (opt.verbose)
688         fprintf (out, " %s", gc_level[option->level].name);
689
690       /* The description field.  */
691       fprintf (out, ":%s", desc ? percent_escape (desc) : "");
692
693       /* The type field.  */
694       fprintf (out, ":%u", option->arg_type);
695       if (opt.verbose)
696         fprintf (out, " %s", gc_arg_type[option->arg_type].name);
697
698       /* The alternate type field.  */
699       fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback);
700       if (opt.verbose)
701         fprintf (out, " %s",
702                  gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
703
704       /* The argument name field.  */
705       fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : "");
706       if (arg_name)
707         xfree (arg_name);
708
709       /* The default value field.  */
710       fprintf (out, ":%s", option->default_value ? option->default_value : "");
711
712       /* The value field.  */
713       fprintf (out, ":%s", option->value ? option->value : "");
714
715       /* ADD NEW FIELDS HERE.  */
716
717       putc ('\n', out);
718       option++;
719     }
720 }
721
722
723 /* Find the option NAME in component COMPONENT, for the backend
724    BACKEND.  If BACKEND is GC_BACKEND_ANY, any backend will match.  */
725 static gc_option_t *
726 find_option (gc_component_t component, const char *name,
727              gc_backend_t backend)
728 {
729   gc_option_t *option = gc_component[component].options;
730   while (option->name)
731     {
732       if (!(option->flags & GC_OPT_FLAG_GROUP)
733           && !strcmp (option->name, name)
734           && (backend == GC_BACKEND_ANY || option->backend == backend))
735         break;
736       option++;
737     }
738   return option->name ? option : NULL;
739 }
740
741 \f
742 /* Determine the configuration pathname for the component COMPONENT
743    and backend BACKEND.  */
744 static char *
745 get_config_pathname (gc_component_t component, gc_backend_t backend)
746 {
747   char *pathname = NULL;
748   gc_option_t *option = find_option
749     (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
750   assert (option);
751   assert (option->arg_type == GC_ARG_TYPE_PATHNAME);
752   assert (!(option->flags & GC_OPT_FLAG_LIST));
753
754   if (!option->active || !option->default_value)
755     gc_error (1, 0, "Option %s, needed by backend %s, was not initialized",
756               gc_backend[backend].option_config_filename,
757               gc_backend[backend].name);
758
759   if (option->value && *option->value)
760     pathname = option->value;
761   else
762     pathname = option->default_value;
763
764   if (pathname[1] != '/')
765     gc_error (1, 0, "Option %s, needed by backend %s, is not absolute",
766               gc_backend[backend].option_config_filename,
767               gc_backend[backend].name);
768
769   return &pathname[1];
770 }
771
772 \f
773 /* Retrieve the options for the component COMPONENT from backend
774    BACKEND, which we already know is a program-type backend.  */
775 static void
776 retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
777 {
778   char *cmd_line;
779   char *line = NULL;
780   size_t line_len = 0;
781   ssize_t length;
782   FILE *config;
783   char *config_pathname;
784
785   cmd_line = xasprintf ("%s --gpgconf-list", gc_backend[backend].program);
786
787   config = popen (cmd_line, "r");
788   if (!config)
789     gc_error (1, errno, "could not gather active options from %s", cmd_line);
790
791   while ((length = getline (&line, &line_len, config)) > 0)
792     {
793       gc_option_t *option;
794       char *value;
795
796       /* Strip newline and carriage return, if present.  */
797       while (length > 0
798              && (line[length - 1] == '\n' || line[length - 1] == '\r'))
799         line[--length] = '\0';
800
801       /* Extract default value, if present.  Default to empty if
802          not.  */
803       value = strchr (line, ':');
804       if (!value)
805         value = "";
806       else
807         {
808           char *end;
809
810           *(value++) = '\0';
811           end = strchr (value, ':');
812           if (end)
813             *end = '\0';
814         }
815
816       /* Look up the option in the component and install the
817          configuration data.  */
818       option = find_option (component, line, backend);
819       if (option)
820         {
821           if (option->active)
822             gc_error (1, errno, "option %s returned twice from %s",
823                       line, cmd_line);
824           option->active = 1;
825           if (*value)
826             option->default_value = xstrdup (value);
827         }
828     }
829   if (ferror (config))
830     gc_error (1, errno, "error reading from %s", cmd_line);
831   if (fclose (config) && ferror (config))
832     gc_error (1, errno, "error closing %s", cmd_line);
833   xfree (cmd_line);
834
835   /* At this point, we can parse the configuration file.  */
836   config_pathname = get_config_pathname (component, backend);
837
838   config = fopen (config_pathname, "r");
839   if (!config)
840     gc_error (0, errno, "warning: can not open config file %s",
841               config_pathname);
842   else
843     {
844       while ((length = getline (&line, &line_len, config)) > 0)
845         {
846           char *name;
847           char *value;
848           gc_option_t *option;
849           
850           name = line;
851           while (*name == ' ' || *name == '\t')
852             name++;
853           if (!*name || *name == '#' || *name == '\r' || *name == '\n')
854             continue;
855
856           value = name;
857           while (*value && *value != ' ' && *value != '\t'
858                  && *value != '#' && *value != '\r' && *value != '\n')
859             value++;
860           if (*value == ' ' || *value == '\t')
861             {
862               char *end;
863
864               *(value++) = '\0';
865               while (*value == ' ' || *value == '\t')
866                 value++;
867
868               end = value;
869               while (*end && *end != '#' && *end != '\r' && *end != '\n')
870                 end++;
871               while (end > value && (end[-1] == ' ' || end[-1] == '\t'))
872                 end--;
873               *end = '\0';
874             }
875           else
876             *value = '\0';
877
878           /* Look up the option in the component and install the
879              configuration data.  */
880           option = find_option (component, line, backend);
881           if (option)
882             {
883               char *opt_value;
884
885               if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
886                 {
887                   if (*value)
888                     gc_error (0, 0,
889                               "warning: ignoring argument %s for option %s",
890                               value, name);
891                   opt_value = xstrdup ("Y");
892                 }
893               else if (gc_arg_type[option->arg_type].fallback
894                        == GC_ARG_TYPE_STRING)
895                 opt_value = xasprintf ("\"%s", percent_escape (value));
896               else
897                 {
898                   /* FIXME: Verify that the number is sane.  */
899                   opt_value = xstrdup (value);
900                 }
901
902               /* Now enter the option into the table.  */
903               if (!(option->flags & GC_OPT_FLAG_LIST))
904                 {
905                   if (option->value)
906                     free (option->value);
907                   option->value = opt_value;
908                 }
909               else
910                 {
911                   if (!option->value)
912                     option->value = opt_value;
913                   else
914                     {
915                       char *opt_val = opt_value;
916
917                       if (gc_arg_type[option->arg_type].fallback
918                           == GC_ARG_TYPE_STRING)
919                         opt_val++;
920
921                       option->value = xasprintf ("%s,%s", option->value,
922                                                  opt_val);
923                       xfree (opt_value);
924                     }
925                 }
926             }
927         }
928
929       if (ferror (config))
930         gc_error (1, errno, "error reading from %s", config_pathname);
931       if (fclose (config) && ferror (config))
932         gc_error (1, errno, "error closing %s", config_pathname);
933     }
934
935   if (line)
936     free (line);
937 }
938
939
940 /* Retrieve the options for the component COMPONENT from backend
941    BACKEND, which we already know is of type file list.  */ 
942 static void
943 retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
944 {
945   gc_option_t *list_option;
946   char *list_pathname;
947   FILE *list_file;
948   char *line = NULL;
949   size_t line_len = 0;
950   ssize_t length;
951   char *list = NULL;
952
953   list_option = find_option (component,
954                              gc_backend[backend].option_name, GC_BACKEND_ANY);
955   assert (list_option);
956   assert (!list_option->active);
957
958   list_pathname = get_config_pathname (component, backend);
959   list_file = fopen (list_pathname, "r");
960   if (!list_file)
961     gc_error (0, errno, "warning: can not open list file %s", list_pathname);
962   else
963     {
964
965       while ((length = getline (&line, &line_len, list_file)) > 0)
966         {
967           char *start;
968           char *end;
969           char *new_list;
970
971           start = line;
972           while (*start == ' ' || *start == '\t')
973             start++;
974           if (!*start || *start == '#' || *start == '\r' || *start == '\n')
975             continue;
976
977           end = start;
978           while (*end && *end != '#' && *end != '\r' && *end != '\n')
979             end++;
980           /* Walk back to skip trailing white spaces.  Looks evil, but
981              works because of the conditions on START and END imposed
982              at this point (END is at least START + 1, and START is
983              not a whitespace character).  */
984           while (*(end - 1) == ' ' || *(end - 1) == '\t')
985             end--;
986           *end = '\0';
987           /* FIXME: Oh, no!  This is so lame!  Use realloc and really
988              append.  */
989           if (list)
990             {
991               new_list = xasprintf ("%s,%s", list, percent_escape (start));
992               xfree (list);
993               list = new_list;
994             }
995           else
996             list = xasprintf ("\"%s", percent_escape (start));
997         }
998       if (ferror (list_file))
999         gc_error (1, errno, "can not read list file %s", list_pathname);
1000     }
1001
1002   list_option->active = 1;
1003   list_option->value = list;
1004
1005   if (line)
1006     free (line);
1007 }
1008
1009
1010 /* Retrieve the currently active options and their defaults from all
1011    involved backends for this component.  */
1012 void
1013 gc_component_retrieve_options (int component)
1014 {
1015   int backend_seen[GC_BACKEND_NR];
1016   gc_backend_t backend;
1017   gc_option_t *option = gc_component[component].options;
1018
1019   for (backend = 0; backend < GC_BACKEND_NR; backend++)
1020     backend_seen[backend] = 0;
1021
1022   while (option->name)
1023     {
1024       if (!(option->flags & GC_OPT_FLAG_GROUP))
1025         {
1026           backend = option->backend;
1027
1028           if (backend_seen[backend])
1029             {
1030               option++;
1031               continue;
1032             }
1033           backend_seen[backend] = 1;
1034
1035           assert (backend != GC_BACKEND_ANY);
1036
1037           if (gc_backend[backend].program)
1038             retrieve_options_from_program (component, backend);
1039           else
1040             retrieve_options_from_file (component, backend);
1041         }
1042       option++;
1043     }
1044 }
1045
1046 \f
1047 /* Perform a simple validity check based on the type.  */
1048 static void
1049 option_check_validity (gc_option_t *option, const char *new_value)
1050 {
1051   if (option->new_value)
1052     gc_error (1, 0, "option %s already changed", option->name);
1053
1054   if (!*new_value)
1055     return;
1056
1057   /* FIXME.  Verify that lists are lists, numbers are numbers, strings
1058      are strings, etc.  */
1059 }
1060
1061
1062 /* Create and verify the new configuration file for the specified
1063    backend and component.  Returns 0 on success and -1 on error.  */
1064 static int
1065 change_options_file (gc_component_t component, gc_backend_t backend,
1066                      char **src_filenamep, char **dest_filenamep,
1067                      char **orig_filenamep)
1068 {
1069   /* FIXME.  */
1070   assert (!"Not implemented.");
1071   return -1;
1072 }
1073
1074
1075 /* Create and verify the new configuration file for the specified
1076    backend and component.  Returns 0 on success and -1 on error.  */
1077 static int
1078 change_options_program (gc_component_t component, gc_backend_t backend,
1079                         char **src_filenamep, char **dest_filenamep,
1080                         char **orig_filenamep)
1081 {
1082   static const char marker[] = "###+++--- GPGConf ---+++###";
1083   /* True if we are within the marker in the config file.  */
1084   int in_marker = 0;
1085   gc_option_t *option;
1086   char *line = NULL;
1087   size_t line_len;
1088   ssize_t length;
1089   int res;
1090   int fd;
1091   FILE *src_file = NULL;
1092   FILE *dest_file = NULL;
1093   char *src_filename;
1094   char *dest_filename;
1095   char *orig_filename;
1096
1097   /* FIXME.  Throughout the function, do better error reporting.  */
1098   dest_filename = xstrdup (get_config_pathname (component, backend));
1099   src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ());
1100   orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ());
1101
1102   res = link (dest_filename, orig_filename);
1103   if (res < 0 && errno != ENOENT)
1104     return -1;
1105   if (res < 0)
1106     {
1107       xfree (orig_filename);
1108       orig_filename = NULL;
1109     }
1110   /* We now initialize the return strings, so the caller can do the
1111      cleanup for us.  */
1112   *src_filenamep = src_filename;
1113   *dest_filenamep = dest_filename;
1114   *orig_filenamep = orig_filename;
1115
1116   /* Use open() so that we can use O_EXCL.  */
1117   fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
1118   if (fd < 0)
1119     return -1;
1120   src_file = fdopen (fd, "w");
1121   res = errno;
1122   if (!src_file)
1123     {
1124       errno = res;
1125       return -1;
1126     }
1127
1128   /* Only if ORIG_FILENAME is not NULL did the configuration file
1129      exist already.  In this case, we will copy its content into the
1130      new configuration file, changing it to our liking in the
1131      process.  */
1132   if (orig_filename)
1133     {
1134       dest_file = fopen (dest_filename, "r");
1135       if (!dest_file)
1136         goto change_one_err;
1137
1138       while ((length = getline (&line, &line_len, dest_file)) > 0)
1139         {
1140           int disable = 0;
1141           char *start;
1142           char *end;
1143
1144           if (!strncmp (marker, line, sizeof (marker) - 1))
1145             {
1146               if (!in_marker)
1147                 in_marker = 1;
1148               else
1149                 break;
1150             }
1151
1152           start = line;
1153           while (*start == ' ' || *start == '\t')
1154             start++;
1155           if (*start && *start != '\r' && *start != '\n' && *start != '#')
1156             {
1157               char saved_end;
1158
1159               end = start;
1160               while (*end && *end != ' ' && *end != '\t'
1161                      && *end != '\r' && *end != '\n' && *end != '#')
1162                 end++;
1163               saved_end = *end;
1164               *end = '\0';
1165
1166               option = find_option (component, start, backend);
1167               *end = saved_end;
1168               if (option && option->new_value)
1169                 disable = 1;
1170             }
1171           if (disable)
1172             {
1173               if (!in_marker)
1174                 {
1175                   fprintf (src_file,
1176                            "# GPGConf disabled this option here at %s\n",
1177                            asctimestamp (gnupg_get_time ()));
1178                   if (ferror (src_file))
1179                     goto change_one_err;
1180                   fprintf (src_file, "# %s", line);
1181                   if (ferror (src_file))
1182                     goto change_one_err;
1183                 }
1184             }
1185           else
1186             {
1187               fprintf (src_file, "%s", line);
1188               if (ferror (src_file))
1189                 goto change_one_err;
1190             }
1191         }
1192       if (ferror (dest_file))
1193         goto change_one_err;
1194     }
1195
1196   if (!in_marker)
1197     {
1198       /* There was no marker.  This is the first time we edit the
1199          file.  We add our own marker at the end of the file and
1200          proceed.  Note that we first write a newline, this guards us
1201          against files which lack the newline at the end of the last
1202          line, while it doesn't hurt us in all other cases.  */
1203       fprintf (src_file, "\n%s\n", marker);
1204       if (ferror (src_file))
1205         goto change_one_err;
1206     }
1207   /* At this point, we have copied everything up to the end marker
1208      into the new file, except for the options we are going to change.
1209      Now, dump the changed options (except for those we are going to
1210      revert to their default), and write the end marker, possibly
1211      followed by the rest of the original file.  */
1212   option = gc_component[component].options;
1213   while (option->name)
1214     {
1215       if (!(option->flags & GC_OPT_FLAG_GROUP)
1216           && option->backend == backend
1217           && option->new_value
1218           && *option->new_value)
1219         {
1220           if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
1221             fprintf (src_file, "%s %s\n", option->name, &option->new_value[1]);
1222           else if (option->arg_type == GC_ARG_TYPE_NONE)
1223             fprintf (src_file, "%s\n", option->name);
1224           else
1225             fprintf (src_file, "%s %s\n", option->name, option->new_value);
1226           if (ferror (src_file))
1227             goto change_one_err;
1228         }
1229       option++;
1230     }
1231   {
1232     fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
1233     if (ferror (src_file))
1234       goto change_one_err;
1235   }
1236   if (!in_marker)
1237     {
1238       fprintf (src_file, "# GPGConf edited this configuration file.\n");
1239       if (ferror (src_file))
1240         goto change_one_err;
1241       fprintf (src_file, "# It will disable options before this marked "
1242                "block, but it will\n");
1243       if (ferror (src_file))
1244         goto change_one_err;
1245       fprintf (src_file, "# never change anything below these lines.\n");
1246       if (ferror (src_file))
1247         goto change_one_err;
1248     }
1249   if (dest_file)
1250     {
1251       while ((length = getline (&line, &line_len, dest_file)) > 0)
1252         {
1253           fprintf (src_file, "%s", line);
1254           if (ferror (src_file))
1255             goto change_one_err;
1256         }
1257       if (ferror (dest_file))
1258         goto change_one_err;
1259     }
1260   if (line)
1261     free (line);
1262   res = fclose (src_file);
1263   if (res)
1264     {
1265       res = errno;
1266       close (fd);
1267       if (dest_file)
1268         fclose (dest_file);
1269       errno = res;
1270       return -1;
1271     }
1272   close (fd);
1273   if (dest_file)
1274     {
1275       res = fclose (dest_file);
1276       if (res)
1277         return -1;
1278     }
1279   return 0;
1280
1281  change_one_err:
1282   if (line)
1283     free (line);
1284   res = errno;
1285   if (src_file)
1286     {
1287       fclose (src_file);
1288       close (fd);
1289     }
1290   if (dest_file)
1291     fclose (dest_file);
1292   errno = res;
1293   return -1;
1294 }
1295
1296 /* Read the modifications from IN and apply them.  */
1297 void
1298 gc_component_change_options (int component, FILE *in)
1299 {
1300   int err = 0;
1301   char *src_pathname[GC_BACKEND_NR];
1302   char *dest_pathname[GC_BACKEND_NR];
1303   char *orig_pathname[GC_BACKEND_NR];
1304   gc_backend_t backend;
1305   gc_option_t *option;
1306   char *line = NULL;
1307   size_t line_len = 0;
1308   ssize_t length;
1309
1310   for (backend = 0; backend < GC_BACKEND_NR; backend++)
1311     {
1312       src_pathname[backend] = NULL;
1313       dest_pathname[backend] = NULL;
1314       orig_pathname[backend] = NULL;
1315     }
1316
1317   while ((length = getline (&line, &line_len, in)) > 0)
1318     {
1319       char *value;
1320
1321       /* Strip newline and carriage return, if present.  */
1322       while (length > 0
1323              && (line[length - 1] == '\n' || line[length - 1] == '\r'))
1324         line[--length] = '\0';
1325
1326       value = strchr (line, ':');
1327       if (!value)
1328         value = "";
1329       else
1330         {
1331           char *end;
1332
1333           *(value++) = '\0';
1334           end = strchr (value, ':');
1335           if (end)
1336             *end = '\0';
1337         }
1338
1339       option = find_option (component, line, GC_BACKEND_ANY);
1340       if (!option)
1341         gc_error (1, 0, "unknown option %s", line);
1342
1343       option_check_validity (option, value);
1344       option->new_value = xstrdup (value);
1345     }
1346
1347   /* Now that we have collected and locally verified the changes,
1348      write them out to new configuration files, verify them
1349      externally, and then commit them.  */
1350   option = gc_component[component].options;
1351   while (option->name)
1352     {
1353       /* Go on if we have already seen this backend, or if there is
1354          nothing to do.  */
1355       if (src_pathname[option->backend] || !option->new_value)
1356         {
1357           option++;
1358           continue;
1359         }
1360
1361       if (gc_backend[option->backend].program)
1362         err = change_options_program (component, option->backend,
1363                                       &src_pathname[component],
1364                                       &dest_pathname[component],
1365                                       &orig_pathname[component]);
1366       else
1367         err = change_options_file (component, option->backend,
1368                                    &src_pathname[component],
1369                                    &dest_pathname[component],
1370                                    &orig_pathname[component]);
1371         
1372       if (err)
1373         break;
1374           
1375       option++;
1376     }
1377   if (!err)
1378     {
1379       int i;
1380
1381       for (i = 0; i < GC_COMPONENT_NR; i++)
1382         {
1383           if (src_pathname[i])
1384             {
1385               /* FIXME: Make a verification here.  */
1386
1387               assert (dest_pathname[i]);
1388
1389               if (orig_pathname[i])
1390                 err = rename (src_pathname[i], dest_pathname[i]);
1391               else
1392                 {
1393                   /* This is a bit safer than rename() because we
1394                      expect DEST_PATHNAME not to be there.  If it
1395                      happens to be there, this will fail.  */
1396                   err = link (src_pathname[i], dest_pathname[i]);
1397                   if (!err)
1398                     unlink (src_pathname[i]);
1399                 }
1400               if (err)
1401                 break;
1402               src_pathname[i] = NULL;
1403             }
1404         }
1405     }
1406
1407   if (err)
1408     {
1409       int i;
1410       int saved_errno = errno;
1411
1412       /* An error occured.  */
1413       for (i = 0; i < GC_COMPONENT_NR; i++)
1414         {
1415           if (src_pathname[i])
1416             {
1417               /* The change was not yet committed.  */
1418               unlink (src_pathname[i]);
1419               if (orig_pathname[i])
1420                 unlink (orig_pathname[i]);
1421             }
1422           else
1423             {
1424               /* The changes were already committed.  FIXME: This is a
1425                  tad dangerous, as we don't know if we don't overwrite
1426                  a version of the file that is even newer than the one
1427                  we just installed.  */
1428               if (orig_pathname[i])
1429                 rename (orig_pathname[i], dest_pathname[i]);
1430               else
1431                 unlink (dest_pathname[i]);
1432             }
1433         }
1434       gc_error (1, saved_errno, "could not commit changes");
1435     }
1436   if (line)
1437     free (line);
1438 }