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