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