LCOV - code coverage report
Current view: top level - tools - gpgconf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 48 172 27.9 %
Date: 2016-09-12 13:01:59 Functions: 3 4 75.0 %

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

Generated by: LCOV version 1.11