Change stack size for Wince.
[gnupg.git] / tools / gpgconf.c
1 /* gpgconf.c - Configuration utility for GnuPG
2  * Copyright (C) 2003, 2007, 2009 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
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "gpgconf.h"
27 #include "i18n.h"
28 #include "sysutils.h"
29
30 /* Constants to identify the commands and options. */
31 enum cmd_and_opt_values
32   {
33     aNull = 0,
34     oDryRun     = 'n',
35     oOutput     = 'o',
36     oQuiet      = 'q',
37     oVerbose    = 'v',
38     oRuntime    = 'r',
39     oComponent  = 'c',
40     oNoVerbose  = 500,
41     oHomedir,
42
43     aListComponents,
44     aCheckPrograms,
45     aListOptions,
46     aChangeOptions,
47     aCheckOptions,
48     aApplyDefaults,
49     aListConfig,
50     aCheckConfig,
51     aListDirs,
52     aReload
53   };
54
55
56 /* The list of commands and options. */
57 static ARGPARSE_OPTS opts[] =
58   {
59     { 300, NULL, 0, N_("@Commands:\n ") },
60     
61     { aListComponents, "list-components", 256, N_("list all components") },
62     { aCheckPrograms, "check-programs", 256, N_("check all programs") },
63     { aListOptions, "list-options", 256, N_("|COMPONENT|list options") },
64     { aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") },
65     { aCheckOptions, "check-options", 256, N_("|COMPONENT|check options") },
66     { aApplyDefaults, "apply-defaults", 256,
67       N_("apply global default values") },
68     { aListDirs, "list-dirs", 256,
69       N_("get the configuration directories for gpgconf") },
70     { aListConfig,   "list-config", 256,
71       N_("list global configuration file") },
72     { aCheckConfig,   "check-config", 256,
73       N_("check global configuration file") },
74     { aReload,        "reload", 256, N_("reload all or a given component")},
75
76     { 301, NULL, 0, N_("@\nOptions:\n ") },
77     
78     { oOutput, "output",    2, N_("use as output file") },
79     { oVerbose, "verbose",  0, N_("verbose") },
80     { oQuiet, "quiet",      0, N_("quiet") },
81     { oDryRun, "dry-run",   0, N_("do not make any changes") },
82     { oRuntime, "runtime",  0, N_("activate changes at runtime, if possible") },
83     /* hidden options */
84     { oNoVerbose, "no-verbose",  0, "@"},
85     {0}
86   };
87
88
89 /* Print usage information and and provide strings for help. */
90 static const char *
91 my_strusage( int level )
92 {
93   const char *p;
94
95   switch (level)
96     {
97     case 11: p = "gpgconf (GnuPG)";
98       break;
99     case 13: p = VERSION; break;
100     case 17: p = PRINTABLE_OS_NAME; break;
101     case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
102
103     case 1:
104     case 40: p = _("Usage: gpgconf [options] (-h for help)");
105       break;
106     case 41:
107       p = _("Syntax: gpgconf [options]\n"
108             "Manage configuration options for tools of the GnuPG system\n");
109       break;
110
111     default: p = NULL; break;
112     }
113   return p;
114 }
115
116
117 /* Return the fp for the output.  This is usually stdout unless
118    --output has been used.  In the latter case this function opens
119    that file.  */
120 static estream_t
121 get_outfp (estream_t *fp)
122 {
123   if (!*fp)
124     {
125       if (opt.outfile)
126         {
127           *fp = es_fopen (opt.outfile, "w");
128           if (!*fp)
129             gc_error (1, errno, "can not open `%s'", opt.outfile);
130         }
131       else
132         *fp = es_stdout;
133     }
134   return *fp;
135 }
136
137
138 /* gpgconf main. */
139 int
140 main (int argc, char **argv)
141 {
142   ARGPARSE_ARGS pargs;
143   const char *fname;
144   int no_more_options = 0;
145   enum cmd_and_opt_values cmd = 0;
146   estream_t outfp = NULL;
147
148   gnupg_reopen_std ("gpgconf");
149   set_strusage (my_strusage);
150   log_set_prefix ("gpgconf", 1);
151
152   /* Make sure that our subsystems are ready.  */
153   i18n_init();
154   init_common_subsystems (&argc, &argv);
155
156   /* Parse the command line. */
157   pargs.argc  = &argc;
158   pargs.argv  = &argv;
159   pargs.flags =  1;  /* Do not remove the args.  */
160   while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
161     {
162       switch (pargs.r_opt)
163         {
164         case oOutput:    opt.outfile = pargs.r.ret_str; break;
165         case oQuiet:     opt.quiet = 1; break;
166         case oDryRun:    opt.dry_run = 1; break;
167         case oRuntime:
168           opt.runtime = 1;
169           break;
170         case oVerbose:   opt.verbose++; break;
171         case oNoVerbose: opt.verbose = 0; break;
172
173         case aListDirs:
174         case aListComponents:
175         case aCheckPrograms:
176         case aListOptions:
177         case aChangeOptions:
178         case aCheckOptions:
179         case aApplyDefaults:
180         case aListConfig:
181         case aCheckConfig:
182         case aReload:
183           cmd = pargs.r_opt;
184           break;
185
186         default: pargs.err = 2; break;
187         }
188     }
189
190   if (log_get_errorcount (0))
191     exit (2);
192   
193   fname = argc ? *argv : NULL;
194   
195   switch (cmd)
196     {
197     case aListComponents:
198     default:
199       /* List all components. */
200       gc_component_list_components (get_outfp (&outfp));
201       break;
202
203     case aCheckPrograms:
204       /* Check all programs. */
205       gc_check_programs (get_outfp (&outfp));
206       break;
207
208     case aListOptions:
209     case aChangeOptions:
210     case aCheckOptions:
211       if (!fname)
212         {
213           es_fputs (_("usage: gpgconf [options] "), es_stderr);
214           es_putc ('\n', es_stderr);
215           es_fputs (_("Need one component argument"), es_stderr);
216           es_putc ('\n', es_stderr);
217           exit (2);
218         }
219       else
220         {
221           int idx = gc_component_find (fname);
222           if (idx < 0)
223             {
224               es_fputs (_("Component not found"), es_stderr);
225               es_putc ('\n', es_stderr);
226               exit (1);
227             }
228           if (cmd == aCheckOptions)
229             gc_component_check_options (idx, get_outfp (&outfp), NULL);
230           else
231             {
232               gc_component_retrieve_options (idx);
233               if (gc_process_gpgconf_conf (NULL, 1, 0, NULL))
234                 exit (1);
235               if (cmd == aListOptions)
236                 gc_component_list_options (idx, get_outfp (&outfp));
237               else if (cmd == aChangeOptions)
238                 gc_component_change_options (idx, es_stdin, get_outfp (&outfp));
239             }
240         }
241       break;
242
243     case aReload:
244       if (!fname)
245         {
246           /* Reload all.  */
247           gc_component_reload (-1);
248         }
249       else
250         {
251           /* Reload given component.  */
252           int idx;
253
254           idx = gc_component_find (fname);
255           if (idx < 0)
256             {
257               es_fputs (_("Component not found"), es_stderr);
258               es_putc ('\n', es_stderr);
259               exit (1);
260             }
261           else
262             {
263               gc_component_reload (idx);
264             }
265         }
266       break;
267
268     case aListConfig:
269       if (gc_process_gpgconf_conf (fname, 0, 0, get_outfp (&outfp)))
270         exit (1);
271       break;
272
273     case aCheckConfig:
274       if (gc_process_gpgconf_conf (fname, 0, 0, NULL))
275         exit (1);
276       break;
277
278     case aApplyDefaults:
279       if (fname)
280         {
281           es_fputs (_("usage: gpgconf [options] "), es_stderr);
282           es_putc ('\n', es_stderr);
283           es_fputs (_("No argument allowed"), es_stderr);
284           es_putc ('\n', es_stderr);
285           exit (2);
286         }
287       gc_component_retrieve_options (-1);
288       if (gc_process_gpgconf_conf (NULL, 1, 1, NULL))
289         exit (1);
290       break;
291       
292     case aListDirs:
293       /* Show the system configuration directories for gpgconf.  */
294       get_outfp (&outfp);
295       es_fprintf (outfp, "sysconfdir:%s\n",
296                   gc_percent_escape (gnupg_sysconfdir ()));
297       es_fprintf (outfp, "bindir:%s\n",
298                   gc_percent_escape (gnupg_bindir ()));
299       es_fprintf (outfp, "libexecdir:%s\n",
300                   gc_percent_escape (gnupg_libexecdir ()));
301       es_fprintf (outfp, "libdir:%s\n",
302                   gc_percent_escape (gnupg_libdir ()));
303       es_fprintf (outfp, "datadir:%s\n",
304                   gc_percent_escape (gnupg_datadir ()));
305       es_fprintf (outfp, "localedir:%s\n",
306                   gc_percent_escape (gnupg_localedir ()));
307       es_fprintf (outfp, "dirmngr-socket:%s\n",
308                   gc_percent_escape (dirmngr_socket_name ()));
309       {
310         char *infostr = getenv ("GPG_AGENT_INFO");
311
312         if (!infostr || !*infostr)
313           infostr = make_filename (default_homedir (), "S.gpg-agent", NULL);
314         else
315           {
316             char *tmp;
317
318             infostr = xstrdup (infostr);
319             tmp = strchr (infostr, PATHSEP_C);
320             if (!tmp || tmp == infostr)
321               {
322                 xfree (infostr);
323                 infostr = NULL;
324               }
325             else
326               *tmp = 0;
327           }
328         es_fprintf (outfp, "agent-socket:%s\n",
329                     infostr? gc_percent_escape (infostr) : "");
330         xfree (infostr);
331       }
332       {
333         /* We need to use make_filename to expand a possible "~/".  */
334         char *tmp = make_filename (default_homedir (), NULL);
335         es_fprintf (outfp, "homedir:%s\n", gc_percent_escape (tmp));
336         xfree (tmp);
337       }
338       break;
339     }
340
341   if (outfp != es_stdout)
342     if (es_fclose (outfp))
343       gc_error (1, errno, "error closing `%s'", opt.outfile);
344
345   return 0; 
346 }
347