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