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