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