gpgconf: Add access to --list-dirs for non-default engine.
[gpgme.git] / tests / gpg / t-gpgconf.c
1 /* t-gpgconf.c - Regression test.
2    Copyright (C) 2001, 2004, 2007 g10 Code GmbH
3
4    This file is part of GPGME.
5
6    GPGME is free software; you can redistribute it and/or modify it
7    under the terms of the GNU Lesser General Public License as
8    published by the Free Software Foundation; either version 2.1 of
9    the License, or (at your option) any later version.
10
11    GPGME 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    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <unistd.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <locale.h>
29 #include <string.h>
30
31 #ifdef HAVE_W32_SYSTEM
32 #include <windows.h>
33 #endif
34
35 #include <gpgme.h>
36
37 #include "t-support.h"
38 \f
39 static char *
40 spaces (char *str, int extra)
41 {
42   static char buf[80];
43   int len = str ? strlen (str) : 0;
44   int n;
45
46 #define TABSTOP 30
47   n = TABSTOP - len - extra;
48
49   memset (buf, ' ', sizeof (buf));
50   if (n < 1 || n > (sizeof (buf) - 1))
51     {
52       buf[0] = '\n';
53       n = TABSTOP + 1;
54     }
55
56   buf[n] = '\0';
57   return buf;
58 }
59
60
61 void
62 dump_arg (int type, gpgme_conf_arg_t arg)
63 {
64   if (!arg)
65     {
66       printf ("(none)");
67       return;
68     }
69
70   while (arg)
71     {
72       switch (type)
73         {
74         case GPGME_CONF_STRING:
75         case GPGME_CONF_PATHNAME:
76         case GPGME_CONF_LDAP_SERVER:
77         case GPGME_CONF_KEY_FPR:
78         case GPGME_CONF_PUB_KEY:
79         case GPGME_CONF_SEC_KEY:
80         case GPGME_CONF_ALIAS_LIST:
81           printf ("`%s'", arg->value.string);
82           break;
83
84         case GPGME_CONF_UINT32:
85           printf ("%u", arg->value.uint32);
86           break;
87
88         case GPGME_CONF_INT32:
89           printf ("%i", arg->value.int32);
90           break;
91
92         case GPGME_CONF_NONE:
93           printf ("%i (times)", arg->value.count);
94           break;
95
96         default:
97           printf ("(unknown type)");
98         }
99
100       arg = arg->next;
101       if (arg)
102         printf (" ");
103     }
104 }
105
106
107 void
108 dump_opt (gpgme_conf_opt_t opt)
109 {
110   char level;
111   char runtime = (opt->flags & GPGME_CONF_RUNTIME) ? 'r' : ' ';
112
113   switch (opt->level)
114     {
115     case GPGME_CONF_BASIC:
116       level = 'b';
117       break;
118     case GPGME_CONF_ADVANCED:
119       level = 'a';
120       break;
121     case GPGME_CONF_EXPERT:
122       level = 'e';
123       break;
124     case GPGME_CONF_INVISIBLE:
125       level = 'i';
126       break;
127     case GPGME_CONF_INTERNAL:
128       level = '#';
129       break;
130     default:
131       level = '?';
132     }
133
134   if (opt->flags & GPGME_CONF_GROUP)
135     {
136       printf ("\n");
137       printf ("%c%c [%s]%s%s\n", level, runtime, opt->name, spaces (opt->name, 5),
138               opt->description
139               ? opt->description : "");
140     }
141   else
142     {
143       if (opt->argname)
144         {
145           const char *more = (opt->flags & GPGME_CONF_LIST) ? "..." : "";
146
147           if (opt->flags & GPGME_CONF_OPTIONAL)
148             {
149               printf ("%c%c --%s [%s%s] %s", level, runtime, opt->name, opt->argname, more,
150                       spaces (opt->name, 9 + strlen (opt->argname) + strlen (more)));
151             }
152           else
153             {
154               printf ("%c%c --%s %s%s %s", level, runtime, opt->name, opt->argname, more,
155                       spaces (opt->name, 7 + strlen (opt->argname) + strlen (more)));
156             }
157         }
158       else
159         printf ("%c%c --%s%s", level, runtime, opt->name, spaces (opt->name, 5));
160
161       if (opt->description)
162         printf ("%s", opt->description);
163       printf ("\n");
164
165       if (opt->flags & GPGME_CONF_DEFAULT)
166         {
167           printf ("%s%s = ", spaces (NULL, 0), opt->argname ? opt->argname : "(default)");
168           dump_arg (opt->type, opt->default_value);
169           printf ("\n");
170         }
171       else if (opt->flags & GPGME_CONF_DEFAULT_DESC)
172         printf ("%s%s = %s\n", spaces (NULL, 0), opt->argname ? opt->argname : "(default)",
173                 opt->default_description);
174
175       if (opt->no_arg_value)
176         {
177           printf ("%sNo Arg Def = ", spaces (NULL, 0));
178           dump_arg (opt->type, opt->no_arg_value);
179           printf ("\n");
180         }
181       if (opt->value)
182         {
183           printf ("%sCurrent = ", spaces (NULL, 0));
184           dump_arg (opt->type, opt->value);
185           printf ("\n");
186         }
187     }
188
189 #if 0
190   arg = comp->options;
191   while (opt)
192     {
193       dump_opt (opt);
194       opt = opt->next;
195     }
196 #endif
197 }
198
199
200 void
201 dump_comp (gpgme_conf_comp_t comp)
202 {
203   gpgme_conf_opt_t opt;
204
205   printf ("COMPONENT\n");
206   printf ("=========\n");
207   printf ("  Name: %s\n", comp->name);
208   if (comp->description)
209     printf ("  Desc: %s\n", comp->description);
210   if (comp->program_name)
211     printf ("  Path: %s\n", comp->program_name);
212   printf ("\n");
213
214   opt = comp->options;
215   while (opt)
216     {
217       dump_opt (opt);
218       opt = opt->next;
219     }
220 }
221
222
223 int
224 lookup (gpgme_conf_comp_t conf,
225         const char *component,
226         const char *option,
227         gpgme_conf_comp_t *comp,
228         gpgme_conf_opt_t *opt)
229 {
230   *comp = conf;
231   while (*comp && strcmp ((*comp)->name, component))
232     *comp = (*comp)->next;
233
234   if (*comp)
235     {
236       *opt = (*comp)->options;
237       while (*opt && strcmp ((*opt)->name, option))
238         *opt = (*opt)->next;
239
240       /* Allow for the option not to be there.  */
241       if (*opt)
242         return 1;       /* Found.  */
243     }
244
245   return 0;             /* Not found.  */
246 }
247
248 #include <assert.h>
249
250
251 int
252 main (void)
253 {
254   gpgme_ctx_t ctx;
255   gpgme_error_t err;
256   gpgme_conf_comp_t conf;
257   gpgme_conf_comp_t comp;
258   int first;
259   int i, N = 10;
260
261   init_gpgme (GPGME_PROTOCOL_GPGCONF);
262
263   err = gpgme_new (&ctx);
264   fail_if_err (err);
265
266   /* Let's check getting the agent-socket directory for different homedirs.  */
267   char *result1 = NULL;
268   err = gpgme_ctx_set_engine_info (ctx, GPGME_PROTOCOL_GPGCONF, NULL, "/tmp/foo");
269   fail_if_err (err);
270   err = gpgme_op_conf_dir (ctx, "agent-socket", &result1);
271   fail_if_err (err);
272
273   char *result2 = NULL;
274   err = gpgme_ctx_set_engine_info (ctx, GPGME_PROTOCOL_GPGCONF, NULL, NULL);
275   fail_if_err (err);
276   err = gpgme_op_conf_dir (ctx, "agent-socket", &result2);
277   fail_if_err (err);
278
279   /* They have to be different.  */
280   test (strcmp(result1, result2));
281
282
283   err = gpgme_op_conf_load (ctx, &conf);
284   fail_if_err (err);
285
286   comp = conf;
287   first = 1;
288   while (comp)
289     {
290       if (!first)
291         printf ("\n");
292       else
293         first = 0;
294       dump_comp (comp);
295       comp = comp->next;
296     }
297
298   /* Now change something.  */
299   fprintf (stderr, " dirmngr.verbose ");
300   for (i = 0; i < N; i++) {
301     unsigned int count = i % 4 + 1; /* counts must not be zero */
302     gpgme_conf_arg_t arg;
303     gpgme_conf_opt_t opt;
304
305     err = gpgme_conf_arg_new (&arg, GPGME_CONF_NONE, &count);
306     fail_if_err (err);
307
308     if (lookup (conf, "dirmngr", "verbose", &comp, &opt))
309       {
310         /* Found.  */
311         err = gpgme_conf_opt_change (opt, 0, arg);
312         fail_if_err (err);
313
314         err = gpgme_op_conf_save (ctx, comp);
315         fail_if_err (err);
316       }
317     else
318       {
319         fprintf (stderr, "Skipping test, option dirmngr.verbose not found.\n");
320         break;
321       }
322
323     /* Reload config and verify that the value was updated.  */
324     gpgme_conf_release (conf);
325     err = gpgme_op_conf_load (ctx, &conf);
326     fail_if_err (err);
327     if (lookup (conf, "dirmngr", "verbose", &comp, &opt))
328       {
329         /* Found.  */
330         test (opt->alt_type == GPGME_CONF_NONE);
331         test (opt->value);
332         test ((unsigned long) opt->value->value.count == count);
333       }
334
335     fprintf (stderr, ".");
336     fflush (stderr);
337   }
338
339   /* Now change something else.  */
340   fprintf (stderr, " gpg.keyserver ");
341   for (i = 0; i < N; i++) {
342     const char *values[2] = { "hkp://foo.bar", "hkps://bar.foo" };
343     gpgme_conf_arg_t arg;
344     gpgme_conf_opt_t opt;
345
346     err = gpgme_conf_arg_new (&arg, GPGME_CONF_STRING, values[i%2]);
347     fail_if_err (err);
348
349     if (lookup (conf, "gpg", "keyserver", &comp, &opt))
350       {
351         /* Found.  */
352         test (opt->alt_type == GPGME_CONF_STRING);
353         err = gpgme_conf_opt_change (opt, 0, arg);
354         fail_if_err (err);
355
356         err = gpgme_op_conf_save (ctx, comp);
357         fail_if_err (err);
358       }
359     else
360       {
361         fprintf (stderr, "Skipping test, option gpg.keyserver not found.\n");
362         break;
363       }
364
365     /* Reload config and verify that the value was updated.  */
366     gpgme_conf_release (conf);
367     err = gpgme_op_conf_load (ctx, &conf);
368     fail_if_err (err);
369     if (lookup (conf, "gpg", "keyserver", &comp, &opt))
370       {
371         /* Found.  */
372         test (opt->alt_type == GPGME_CONF_STRING);
373         test (opt->value);
374         test (opt->value->value.string);
375         test (strcmp (opt->value->value.string, values[i%2]) == 0);
376       }
377
378     fprintf (stderr, ".");
379     fflush (stderr);
380   }
381   fprintf (stderr, "\n");
382
383   gpgme_conf_release (conf);
384   gpgme_release (ctx);
385   return 0;
386 }