63cc654585ce72d388165d9b59c0621d2805838a
[gnupg.git] / tools / gpgconf.c
1 /* gpgconf.c - Configuration utility for GnuPG
2  * Copyright (C) 2003, 2007, 2009, 2011 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 #include "../common/init.h"
30
31
32 /* Constants to identify the commands and options. */
33 enum cmd_and_opt_values
34   {
35     aNull = 0,
36     oDryRun     = 'n',
37     oOutput     = 'o',
38     oQuiet      = 'q',
39     oVerbose    = 'v',
40     oRuntime    = 'r',
41     oComponent  = 'c',
42     oNoVerbose  = 500,
43     oHomedir,
44
45     aListComponents,
46     aCheckPrograms,
47     aListOptions,
48     aChangeOptions,
49     aCheckOptions,
50     aApplyDefaults,
51     aListConfig,
52     aCheckConfig,
53     aListDirs,
54     aLaunch,
55     aKill,
56     aReload
57   };
58
59
60 /* The list of commands and options. */
61 static ARGPARSE_OPTS opts[] =
62   {
63     { 300, NULL, 0, N_("@Commands:\n ") },
64
65     { aListComponents, "list-components", 256, N_("list all components") },
66     { aCheckPrograms, "check-programs", 256, N_("check all programs") },
67     { aListOptions, "list-options", 256, N_("|COMPONENT|list options") },
68     { aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") },
69     { aCheckOptions, "check-options", 256, N_("|COMPONENT|check options") },
70     { aApplyDefaults, "apply-defaults", 256,
71       N_("apply global default values") },
72     { aListDirs, "list-dirs", 256,
73       N_("get the configuration directories for @GPGCONF@") },
74     { aListConfig,   "list-config", 256,
75       N_("list global configuration file") },
76     { aCheckConfig,   "check-config", 256,
77       N_("check global configuration file") },
78     { aReload,        "reload", 256, N_("reload all or a given component")},
79     { aLaunch,        "launch", 256, N_("launch a given component")},
80     { aKill,          "kill", 256,   N_("kill a given component")},
81
82     { 301, NULL, 0, N_("@\nOptions:\n ") },
83
84     { oOutput, "output",    2, N_("use as output file") },
85     { oVerbose, "verbose",  0, N_("verbose") },
86     { oQuiet, "quiet",      0, N_("quiet") },
87     { oDryRun, "dry-run",   0, N_("do not make any changes") },
88     { oRuntime, "runtime",  0, N_("activate changes at runtime, if possible") },
89     /* hidden options */
90     { oHomedir, "homedir", 2, "@" },
91     { oNoVerbose, "no-verbose",  0, "@"},
92     {0}
93   };
94
95
96 /* Print usage information and and provide strings for help. */
97 static const char *
98 my_strusage( int level )
99 {
100   const char *p;
101
102   switch (level)
103     {
104     case 11: p = "@GPGCONF@ (@GNUPG@)";
105       break;
106     case 13: p = VERSION; break;
107     case 17: p = PRINTABLE_OS_NAME; break;
108     case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
109
110     case 1:
111     case 40: p = _("Usage: @GPGCONF@ [options] (-h for help)");
112       break;
113     case 41:
114       p = _("Syntax: @GPGCONF@ [options]\n"
115             "Manage configuration options for tools of the @GNUPG@ system\n");
116       break;
117
118     default: p = NULL; break;
119     }
120   return p;
121 }
122
123
124 /* Return the fp for the output.  This is usually stdout unless
125    --output has been used.  In the latter case this function opens
126    that file.  */
127 static estream_t
128 get_outfp (estream_t *fp)
129 {
130   if (!*fp)
131     {
132       if (opt.outfile)
133         {
134           *fp = es_fopen (opt.outfile, "w");
135           if (!*fp)
136             gc_error (1, errno, "can not open '%s'", opt.outfile);
137         }
138       else
139         *fp = es_stdout;
140     }
141   return *fp;
142 }
143
144
145 /* gpgconf main. */
146 int
147 main (int argc, char **argv)
148 {
149   ARGPARSE_ARGS pargs;
150   const char *fname;
151   int no_more_options = 0;
152   enum cmd_and_opt_values cmd = 0;
153   estream_t outfp = NULL;
154
155   early_system_init ();
156   gnupg_reopen_std (GPGCONF_NAME);
157   set_strusage (my_strusage);
158   log_set_prefix (GPGCONF_NAME, 1);
159
160   /* Make sure that our subsystems are ready.  */
161   i18n_init();
162   init_common_subsystems (&argc, &argv);
163
164   /* Parse the command line. */
165   pargs.argc  = &argc;
166   pargs.argv  = &argv;
167   pargs.flags =  1;  /* Do not remove the args.  */
168   while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
169     {
170       switch (pargs.r_opt)
171         {
172         case oOutput:    opt.outfile = pargs.r.ret_str; break;
173         case oQuiet:     opt.quiet = 1; break;
174         case oDryRun:    opt.dry_run = 1; break;
175         case oRuntime:
176           opt.runtime = 1;
177           break;
178         case oVerbose:   opt.verbose++; break;
179         case oNoVerbose: opt.verbose = 0; break;
180         case oHomedir:   gnupg_set_homedir (pargs.r.ret_str); break;
181
182         case aListDirs:
183         case aListComponents:
184         case aCheckPrograms:
185         case aListOptions:
186         case aChangeOptions:
187         case aCheckOptions:
188         case aApplyDefaults:
189         case aListConfig:
190         case aCheckConfig:
191         case aReload:
192         case aLaunch:
193         case aKill:
194           cmd = pargs.r_opt;
195           break;
196
197         default: pargs.err = 2; break;
198         }
199     }
200
201   if (log_get_errorcount (0))
202     exit (2);
203
204   /* Print a warning if an argument looks like an option.  */
205   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
206     {
207       int i;
208
209       for (i=0; i < argc; i++)
210         if (argv[i][0] == '-' && argv[i][1] == '-')
211           log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
212     }
213
214   fname = argc ? *argv : NULL;
215
216   switch (cmd)
217     {
218     case aListComponents:
219     default:
220       /* List all components. */
221       gc_component_list_components (get_outfp (&outfp));
222       break;
223
224     case aCheckPrograms:
225       /* Check all programs. */
226       gc_check_programs (get_outfp (&outfp));
227       break;
228
229     case aListOptions:
230     case aChangeOptions:
231     case aCheckOptions:
232       if (!fname)
233         {
234           es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME);
235           es_putc ('\n', es_stderr);
236           es_fputs (_("Need one component argument"), es_stderr);
237           es_putc ('\n', es_stderr);
238           exit (2);
239         }
240       else
241         {
242           int idx = gc_component_find (fname);
243           if (idx < 0)
244             {
245               es_fputs (_("Component not found"), es_stderr);
246               es_putc ('\n', es_stderr);
247               exit (1);
248             }
249           if (cmd == aCheckOptions)
250             gc_component_check_options (idx, get_outfp (&outfp), NULL);
251           else
252             {
253               gc_component_retrieve_options (idx);
254               if (gc_process_gpgconf_conf (NULL, 1, 0, NULL))
255                 exit (1);
256               if (cmd == aListOptions)
257                 gc_component_list_options (idx, get_outfp (&outfp));
258               else if (cmd == aChangeOptions)
259                 gc_component_change_options (idx, es_stdin, get_outfp (&outfp));
260             }
261         }
262       break;
263
264     case aLaunch:
265     case aKill:
266       if (!fname)
267         {
268           es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME);
269           es_putc ('\n', es_stderr);
270           es_fputs (_("Need one component argument"), es_stderr);
271           es_putc ('\n', es_stderr);
272           exit (2);
273         }
274       else
275         {
276           /* Launch/Kill a given component.  */
277           int idx;
278
279           idx = gc_component_find (fname);
280           if (idx < 0)
281             {
282               es_fputs (_("Component not found"), es_stderr);
283               es_putc ('\n', es_stderr);
284               exit (1);
285             }
286           else if (cmd == aLaunch)
287             {
288               if (gc_component_launch (idx))
289                 exit (1);
290             }
291           else
292             {
293               /* We don't error out if the kill failed because this
294                  command should do nothing if the component is not
295                  running.  */
296               gc_component_kill (idx);
297             }
298         }
299       break;
300
301     case aReload:
302       if (!fname)
303         {
304           /* Reload all.  */
305           gc_component_reload (-1);
306         }
307       else
308         {
309           /* Reload given component.  */
310           int idx;
311
312           idx = gc_component_find (fname);
313           if (idx < 0)
314             {
315               es_fputs (_("Component not found"), es_stderr);
316               es_putc ('\n', es_stderr);
317               exit (1);
318             }
319           else
320             {
321               gc_component_reload (idx);
322             }
323         }
324       break;
325
326     case aListConfig:
327       if (gc_process_gpgconf_conf (fname, 0, 0, get_outfp (&outfp)))
328         exit (1);
329       break;
330
331     case aCheckConfig:
332       if (gc_process_gpgconf_conf (fname, 0, 0, NULL))
333         exit (1);
334       break;
335
336     case aApplyDefaults:
337       if (fname)
338         {
339           es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME);
340           es_putc ('\n', es_stderr);
341           es_fputs (_("No argument allowed"), es_stderr);
342           es_putc ('\n', es_stderr);
343           exit (2);
344         }
345       gc_component_retrieve_options (-1);
346       if (gc_process_gpgconf_conf (NULL, 1, 1, NULL))
347         exit (1);
348       break;
349
350     case aListDirs:
351       /* Show the system configuration directories for gpgconf.  */
352       get_outfp (&outfp);
353       es_fprintf (outfp, "sysconfdir:%s\n",
354                   gc_percent_escape (gnupg_sysconfdir ()));
355       es_fprintf (outfp, "bindir:%s\n",
356                   gc_percent_escape (gnupg_bindir ()));
357       es_fprintf (outfp, "libexecdir:%s\n",
358                   gc_percent_escape (gnupg_libexecdir ()));
359       es_fprintf (outfp, "libdir:%s\n",
360                   gc_percent_escape (gnupg_libdir ()));
361       es_fprintf (outfp, "datadir:%s\n",
362                   gc_percent_escape (gnupg_datadir ()));
363       es_fprintf (outfp, "localedir:%s\n",
364                   gc_percent_escape (gnupg_localedir ()));
365
366       if (dirmngr_user_socket_name ())
367         {
368           es_fprintf (outfp, "dirmngr-socket:%s\n",
369                       gc_percent_escape (dirmngr_user_socket_name ()));
370           es_fprintf (outfp, "dirmngr-sys-socket:%s\n",
371                       gc_percent_escape (dirmngr_sys_socket_name ()));
372         }
373       else
374         {
375           es_fprintf (outfp, "dirmngr-socket:%s\n",
376                       gc_percent_escape (dirmngr_sys_socket_name ()));
377         }
378
379       {
380         char *tmp = make_filename (gnupg_socketdir (),
381                                    GPG_AGENT_SOCK_NAME, NULL);
382         es_fprintf (outfp, "agent-socket:%s\n", gc_percent_escape (tmp));
383         xfree (tmp);
384       }
385       {
386         /* We need to use make_filename to expand a possible "~/".  */
387         char *tmp = make_filename (default_homedir (), NULL);
388         es_fprintf (outfp, "homedir:%s\n", gc_percent_escape (tmp));
389         xfree (tmp);
390       }
391       break;
392     }
393
394   if (outfp != es_stdout)
395     if (es_fclose (outfp))
396       gc_error (1, errno, "error closing '%s'", opt.outfile);
397
398   return 0;
399 }