Imported Upstream version 2.2.6
[platform/upstream/gpg2.git] / tools / gpgconf-comp.c
index f608f7a..b10b146 100644 (file)
@@ -48,6 +48,7 @@
 #include "../common/i18n.h"
 #include "../common/exechelp.h"
 #include "../common/sysutils.h"
+#include "../common/status.h"
 
 #include "../common/gc-opt-flags.h"
 #include "gpgconf.h"
@@ -99,7 +100,7 @@ gc_error (int status, int errnum, const char *fmt, ...)
     {
       log_printf (NULL);
       log_printf ("fatal error (exit status %i)\n", status);
-      exit (status);
+      gpgconf_failure (gpg_error_from_errno (errnum));
     }
 }
 
@@ -149,7 +150,7 @@ typedef enum
 
 /* To be able to implement generic algorithms for the various
    backends, we collect all information about them in this struct.  */
-static struct
+static const struct
 {
   /* The name of the backend.  */
   const char *name;
@@ -256,7 +257,7 @@ typedef enum
 
 /* For every argument, we record some information about it in the
    following struct.  */
-static struct
+static const struct
 {
   /* For every argument type exists a basic argument type that can be
      used as a fallback for input and validation purposes.  */
@@ -328,7 +329,7 @@ typedef enum
   } gc_expert_level_t;
 
 /* A description for each expert level.  */
-static struct
+static const struct
 {
   const char *name;
 } gc_level[] =
@@ -361,7 +362,7 @@ static struct
 
 
 /* A human-readable description for each flag.  */
-static struct
+static const struct
 {
   const char *name;
 } gc_flag[] =
@@ -500,6 +501,10 @@ static gc_option_t gc_options_gpg_agent[] =
    { "enable-ssh-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", "enable ssh support",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
+   { "ssh-fingerprint-digest",
+     GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
+     "gnupg", "|ALGO|use ALGO to show ssh fingerprints",
+     GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT },
    { "enable-putty-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", "enable putty support",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
@@ -546,6 +551,9 @@ static gc_option_t gc_options_gpg_agent[] =
      GC_LEVEL_ADVANCED,
      "gnupg", "allow passphrase to be prompted through Emacs",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
+   { "grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
+     "gnupg", NULL,
+     GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
    { "no-allow-external-cache", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_BASIC, "gnupg", "disallow the use of an external password cache",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
@@ -555,9 +563,6 @@ static gc_option_t gc_options_gpg_agent[] =
    { "no-allow-loopback-pinentry", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_EXPERT, "gnupg", "disallow caller to override the pinentry",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
-   { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
-     "gnupg", "do not grab keyboard and mouse",
-     GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
 
    { "Passphrase policy",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
@@ -710,7 +715,7 @@ static gc_option_t gc_options_gpg[] =
    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
-   { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+   { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      NULL, NULL,
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
    { "default-new-key-algo", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
@@ -751,8 +756,25 @@ static gc_option_t gc_options_gpg[] =
    { "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address"),
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
-   { "auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+   { "auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
+   { "no-auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+     NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
+   { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
+     "gnupg", N_("disable all access to the dirmngr"),
+     GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
+   { "max-cert-depth",
+     GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+     NULL, NULL,
+     GC_ARG_TYPE_UINT32, GC_BACKEND_GPG },
+   { "completes-needed",
+     GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+     NULL, NULL,
+     GC_ARG_TYPE_UINT32, GC_BACKEND_GPG },
+   { "marginals-needed",
+     GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+     NULL, NULL,
+     GC_ARG_TYPE_UINT32, GC_BACKEND_GPG },
 
 
    GC_OPTION_NULL
@@ -812,6 +834,9 @@ static gc_option_t gc_options_gpgsm[] =
      (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
+   { "compliance", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
+     NULL, NULL,
+     GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
@@ -1070,7 +1095,7 @@ typedef enum
 
 
 /* The information associated with each component.  */
-static struct
+static const struct
 {
   /* The name of this component.  Must not contain a colon (':')
      character.  */
@@ -1286,7 +1311,7 @@ gc_component_launch (int component)
     {
       es_fputs (_("Component not suitable for launching"), es_stderr);
       es_putc ('\n', es_stderr);
-      exit (1);
+      gpgconf_failure (0);
     }
 
   pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
@@ -2051,7 +2076,9 @@ get_config_filename (gc_component_t component, gc_backend_t backend)
 #elif defined(HAVE_DOSISH_SYSTEM)
   if (!(filename[0]
         && filename[1] == ':'
-        && (filename[2] == '/' || filename[2] == '\\')))
+        && (filename[2] == '/' || filename[2] == '\\')) /* x:\ or x:/ */
+      && !((filename[0] == '\\' && filename[1] == '\\')
+           || (filename[0] == '/' && filename[1] == '/'))) /* \\server */
 #else
   if (filename[0] != '/')
 #endif
@@ -2064,9 +2091,12 @@ get_config_filename (gc_component_t component, gc_backend_t backend)
 
 \f
 /* Retrieve the options for the component COMPONENT from backend
-   BACKEND, which we already know is a program-type backend.  */
+ * BACKEND, which we already know is a program-type backend.  With
+ * ONLY_INSTALLED set components which are not installed are silently
+ * ignored. */
 static void
-retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
+retrieve_options_from_program (gc_component_t component, gc_backend_t backend,
+                               int only_installed)
 {
   gpg_error_t err;
   const char *pgmname;
@@ -2086,6 +2116,11 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
   argv[0] = "--gpgconf-list";
   argv[1] = NULL;
 
+  if (only_installed && access (pgmname, X_OK))
+    {
+      return;  /* The component is not installed.  */
+    }
+
   err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0,
                              NULL, &outfp, NULL, &pid);
   if (err)
@@ -2357,7 +2392,7 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
 
 /* Retrieve the currently active options and their defaults from all
    involved backends for this component.  Using -1 for component will
-   retrieve all options from all components. */
+   retrieve all options from all installed components. */
 void
 gc_component_retrieve_options (int component)
 {
@@ -2399,7 +2434,8 @@ gc_component_retrieve_options (int component)
               assert (backend != GC_BACKEND_ANY);
 
               if (gc_backend[backend].program)
-                retrieve_options_from_program (component, backend);
+                retrieve_options_from_program (component, backend,
+                                               process_all);
               else
                 retrieve_options_from_file (component, backend);
             }
@@ -3724,6 +3760,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
             {
               gc_error (0, 0, "missing rule at '%s', line %d", fname, lineno);
               result = -1;
+              gpgconf_write_status (STATUS_WARNING,
+                                    "gpgconf.conf %d file '%s' line %d "
+                                    "missing rule",
+                                    GPG_ERR_SYNTAX, fname, lineno);
               continue;
             }
           *p++ = 0;
@@ -3753,6 +3793,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
         {
           gc_error (0, 0, "missing component at '%s', line %d",
                     fname, lineno);
+          gpgconf_write_status (STATUS_WARNING,
+                                "gpgconf.conf %d file '%s' line %d "
+                                " missing component",
+                                GPG_ERR_NO_NAME, fname, lineno);
           result = -1;
           continue;
         }
@@ -3764,6 +3808,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
         {
           gc_error (0, 0, "unknown component at '%s', line %d",
                     fname, lineno);
+          gpgconf_write_status (STATUS_WARNING,
+                                "gpgconf.conf %d file '%s' line %d "
+                                "unknown component",
+                                GPG_ERR_UNKNOWN_NAME, fname, lineno);
           result = -1;
         }
 
@@ -3776,6 +3824,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
         {
           gc_error (0, 0, "missing option at '%s', line %d",
                     fname, lineno);
+          gpgconf_write_status (STATUS_WARNING,
+                                "gpgconf.conf %d file '%s' line %d "
+                                "missing option",
+                                GPG_ERR_INV_NAME, fname, lineno);
           result = -1;
           continue;
         }
@@ -3788,6 +3840,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
             {
               gc_error (0, 0, "unknown option at '%s', line %d",
                         fname, lineno);
+              gpgconf_write_status (STATUS_WARNING,
+                                    "gpgconf.conf %d file '%s' line %d "
+                                    "unknown option",
+                                    GPG_ERR_UNKNOWN_OPTION, fname, lineno);
               result = -1;
             }
         }
@@ -3804,6 +3860,10 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
             {
               gc_error (0, 0, "syntax error in rule at '%s', line %d",
                         fname, lineno);
+              gpgconf_write_status (STATUS_WARNING,
+                                    "gpgconf.conf %d file '%s' line %d "
+                                    "syntax error in rule",
+                                    GPG_ERR_SYNTAX, fname, lineno);
               result = -1;
               continue;
             }