gpgconf: Add command --launch.
[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     { oNoVerbose, "no-verbose",  0, "@"},
91     {0}
92   };
93
94
95 /* Print usage information and and provide strings for help. */
96 static const char *
97 my_strusage( int level )
98 {
99   const char *p;
100
101   switch (level)
102     {
103     case 11: p = "@GPGCONF@ (@GNUPG@)";
104       break;
105     case 13: p = VERSION; break;
106     case 17: p = PRINTABLE_OS_NAME; break;
107     case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
108
109     case 1:
110     case 40: p = _("Usage: @GPGCONF@ [options] (-h for help)");
111       break;
112     case 41:
113       p = _("Syntax: @GPGCONF@ [options]\n"
114             "Manage configuration options for tools of the @GNUPG@ system\n");
115       break;
116
117     default: p = NULL; break;
118     }
119   return p;
120 }
121
122
123 /* Return the fp for the output.  This is usually stdout unless
124    --output has been used.  In the latter case this function opens
125    that file.  */
126 static estream_t
127 get_outfp (estream_t *fp)
128 {
129   if (!*fp)
130     {
131       if (opt.outfile)
132         {
133           *fp = es_fopen (opt.outfile, "w");
134           if (!*fp)
135             gc_error (1, errno, "can not open '%s'", opt.outfile);
136         }
137       else
138         *fp = es_stdout;
139     }
140   return *fp;
141 }
142
143
144 /* gpgconf main. */
145 int
146 main (int argc, char **argv)
147 {
148   ARGPARSE_ARGS pargs;
149   const char *fname;
150   int no_more_options = 0;
151   enum cmd_and_opt_values cmd = 0;
152   estream_t outfp = NULL;
153
154   gnupg_reopen_std ("gpgconf");
155   set_strusage (my_strusage);
156   log_set_prefix ("gpgconf", 1);
157
158   /* Make sure that our subsystems are ready.  */
159   i18n_init();
160   init_common_subsystems (&argc, &argv);
161
162   /* Parse the command line. */
163   pargs.argc  = &argc;
164   pargs.argv  = &argv;
165   pargs.flags =  1;  /* Do not remove the args.  */
166   while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
167     {
168       switch (pargs.r_opt)
169         {
170         case oOutput:    opt.outfile = pargs.r.ret_str; break;
171         case oQuiet:     opt.quiet = 1; break;
172         case oDryRun:    opt.dry_run = 1; break;
173         case oRuntime:
174           opt.runtime = 1;
175           break;
176         case oVerbose:   opt.verbose++; break;
177         case oNoVerbose: opt.verbose = 0; break;
178
179         case aListDirs:
180         case aListComponents:
181         case aCheckPrograms:
182         case aListOptions:
183         case aChangeOptions:
184         case aCheckOptions:
185         case aApplyDefaults:
186         case aListConfig:
187         case aCheckConfig:
188         case aReload:
189         case aLaunch:
190         case aKill:
191           cmd = pargs.r_opt;
192           break;
193
194         default: pargs.err = 2; break;
195         }
196     }
197
198   if (log_get_errorcount (0))
199     exit (2);
200
201   /* Print a warning if an argument looks like an option.  */
202   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
203     {
204       int i;
205
206       for (i=0; i < argc; i++)
207         if (argv[i][0] == '-' && argv[i][1] == '-')
208           log_info (_("NOTE: '%s' is not considered an option\n"), argv[i]);
209     }
210
211   fname = argc ? *argv : NULL;
212
213   switch (cmd)
214     {
215     case aListComponents:
216     default:
217       /* List all components. */
218       gc_component_list_components (get_outfp (&outfp));
219       break;
220
221     case aCheckPrograms:
222       /* Check all programs. */
223       gc_check_programs (get_outfp (&outfp));
224       break;
225
226     case aListOptions:
227     case aChangeOptions:
228     case aCheckOptions:
229       if (!fname)
230         {
231           es_fputs (_("usage: gpgconf [options] "), es_stderr);
232           es_putc ('\n', es_stderr);
233           es_fputs (_("Need one component argument"), es_stderr);
234           es_putc ('\n', es_stderr);
235           exit (2);
236         }
237       else
238         {
239           int idx = gc_component_find (fname);
240           if (idx < 0)
241             {
242               es_fputs (_("Component not found"), es_stderr);
243               es_putc ('\n', es_stderr);
244               exit (1);
245             }
246           if (cmd == aCheckOptions)
247             gc_component_check_options (idx, get_outfp (&outfp), NULL);
248           else
249             {
250               gc_component_retrieve_options (idx);
251               if (gc_process_gpgconf_conf (NULL, 1, 0, NULL))
252                 exit (1);
253               if (cmd == aListOptions)
254                 gc_component_list_options (idx, get_outfp (&outfp));
255               else if (cmd == aChangeOptions)
256                 gc_component_change_options (idx, es_stdin, get_outfp (&outfp));
257             }
258         }
259       break;
260
261     case aLaunch:
262     case aKill:
263       if (!fname)
264         {
265           es_fputs (_("usage: gpgconf [options] "), es_stderr);
266           es_putc ('\n', es_stderr);
267           es_fputs (_("Need one component argument"), es_stderr);
268           es_putc ('\n', es_stderr);
269           exit (2);
270         }
271       else
272         {
273           /* Launch/Kill a given component.  */
274           int idx;
275
276           idx = gc_component_find (fname);
277           if (idx < 0)
278             {
279               es_fputs (_("Component not found"), es_stderr);
280               es_putc ('\n', es_stderr);
281               exit (1);
282             }
283           else if (cmd == aLaunch)
284             gc_component_launch (idx);
285           else
286             gc_component_kill (idx);
287         }
288       break;
289
290     case aReload:
291       if (!fname)
292         {
293           /* Reload all.  */
294           gc_component_reload (-1);
295         }
296       else
297         {
298           /* Reload given component.  */
299           int idx;
300
301           idx = gc_component_find (fname);
302           if (idx < 0)
303             {
304               es_fputs (_("Component not found"), es_stderr);
305               es_putc ('\n', es_stderr);
306               exit (1);
307             }
308           else
309             {
310               gc_component_reload (idx);
311             }
312         }
313       break;
314
315     case aListConfig:
316       if (gc_process_gpgconf_conf (fname, 0, 0, get_outfp (&outfp)))
317         exit (1);
318       break;
319
320     case aCheckConfig:
321       if (gc_process_gpgconf_conf (fname, 0, 0, NULL))
322         exit (1);
323       break;
324
325     case aApplyDefaults:
326       if (fname)
327         {
328           es_fputs (_("usage: gpgconf [options] "), es_stderr);
329           es_putc ('\n', es_stderr);
330           es_fputs (_("No argument allowed"), es_stderr);
331           es_putc ('\n', es_stderr);
332           exit (2);
333         }
334       gc_component_retrieve_options (-1);
335       if (gc_process_gpgconf_conf (NULL, 1, 1, NULL))
336         exit (1);
337       break;
338
339     case aListDirs:
340       /* Show the system configuration directories for gpgconf.  */
341       get_outfp (&outfp);
342       es_fprintf (outfp, "sysconfdir:%s\n",
343                   gc_percent_escape (gnupg_sysconfdir ()));
344       es_fprintf (outfp, "bindir:%s\n",
345                   gc_percent_escape (gnupg_bindir ()));
346       es_fprintf (outfp, "libexecdir:%s\n",
347                   gc_percent_escape (gnupg_libexecdir ()));
348       es_fprintf (outfp, "libdir:%s\n",
349                   gc_percent_escape (gnupg_libdir ()));
350       es_fprintf (outfp, "datadir:%s\n",
351                   gc_percent_escape (gnupg_datadir ()));
352       es_fprintf (outfp, "localedir:%s\n",
353                   gc_percent_escape (gnupg_localedir ()));
354
355       if (dirmngr_user_socket_name ())
356         {
357           es_fprintf (outfp, "dirmngr-socket:%s\n",
358                       gc_percent_escape (dirmngr_user_socket_name ()));
359           es_fprintf (outfp, "dirmngr-sys-socket:%s\n",
360                       gc_percent_escape (dirmngr_sys_socket_name ()));
361         }
362       else
363         {
364           es_fprintf (outfp, "dirmngr-socket:%s\n",
365                       gc_percent_escape (dirmngr_sys_socket_name ()));
366         }
367
368       {
369         char *infostr = getenv (GPG_AGENT_INFO_NAME);
370
371         if (!infostr || !*infostr)
372           infostr = make_filename (default_homedir (),
373                                    GPG_AGENT_SOCK_NAME, NULL);
374         else
375           {
376             char *tmp;
377
378             infostr = xstrdup (infostr);
379             tmp = strchr (infostr, PATHSEP_C);
380             if (!tmp || tmp == infostr)
381               {
382                 xfree (infostr);
383                 infostr = NULL;
384               }
385             else
386               *tmp = 0;
387           }
388         es_fprintf (outfp, "agent-socket:%s\n",
389                     infostr? gc_percent_escape (infostr) : "");
390         xfree (infostr);
391       }
392       {
393         /* We need to use make_filename to expand a possible "~/".  */
394         char *tmp = make_filename (default_homedir (), NULL);
395         es_fprintf (outfp, "homedir:%s\n", gc_percent_escape (tmp));
396         xfree (tmp);
397       }
398       break;
399     }
400
401   if (outfp != es_stdout)
402     if (es_fclose (outfp))
403       gc_error (1, errno, "error closing '%s'", opt.outfile);
404
405   return 0;
406 }