* call-dirmngr.c (start_dirmngr): Use PATHSEP_C instead of ':'.
[gnupg.git] / sm / call-agent.c
index 053959b..885abf4 100644 (file)
@@ -34,6 +34,7 @@
 #include <gcrypt.h>
 #include <assuan.h>
 #include "i18n.h"
+#include "asshelp.h"
 #include "keydb.h" /* fixme: Move this to import.c */
 #include "../common/membuf.h"
 
@@ -64,16 +65,11 @@ struct learn_parm_s {
 /* Try to connect to the agent via socket or fork it off and work by
    pipes.  Handle the server's initial greeting */
 static int
-start_agent (void)
+start_agent (ctrl_t ctrl)
 {
   int rc = 0;
   char *infostr, *p;
-  ASSUAN_CONTEXT ctx;
-  char *dft_display = NULL;
-  char *dft_ttyname = NULL;
-  char *dft_ttytype = NULL;
-  char *old_lc = NULL;
-  char *dft_lc = NULL;
+  assuan_context_t ctx;
 
   if (agent_ctx)
     return 0; /* fixme: We need a context for each thread or serialize
@@ -85,39 +81,53 @@ start_agent (void)
     {
       const char *pgmname;
       const char *argv[3];
+      char *sockname;
       int no_close_list[3];
       int i;
 
-      if (opt.verbose)
-        log_info (_("no running gpg-agent - starting one\n"));
+      /* First check whether we can connect at the standard
+         socket.  */
+      sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
+      rc = assuan_socket_connect (&ctx, sockname, 0);
+      xfree (sockname);
 
-      if (fflush (NULL))
+      if (rc)
         {
-          gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
-          log_error ("error flushing pending output: %s\n", strerror (errno));
-          return tmperr;
+          /* With no success start a new server.  */
+          if (opt.verbose)
+            log_info (_("no running gpg-agent - starting one\n"));
+          
+          gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0");
+          
+          if (fflush (NULL))
+            {
+              gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
+              log_error ("error flushing pending output: %s\n",
+                         strerror (errno));
+              return tmperr;
+            }
+          
+          if (!opt.agent_program || !*opt.agent_program)
+            opt.agent_program = GNUPG_DEFAULT_AGENT;
+          if ( !(pgmname = strrchr (opt.agent_program, '/')))
+            pgmname = opt.agent_program;
+          else
+            pgmname++;
+
+          argv[0] = pgmname;
+          argv[1] = "--server";
+          argv[2] = NULL;
+
+          i=0;
+          if (log_get_fd () != -1)
+            no_close_list[i++] = log_get_fd ();
+          no_close_list[i++] = fileno (stderr);
+          no_close_list[i] = -1;
+
+          /* Connect to the agent and perform initial handshaking. */
+          rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv,
+                                    no_close_list);
         }
-
-      if (!opt.agent_program || !*opt.agent_program)
-        opt.agent_program = GNUPG_DEFAULT_AGENT;
-      if ( !(pgmname = strrchr (opt.agent_program, '/')))
-        pgmname = opt.agent_program;
-      else
-        pgmname++;
-
-      argv[0] = pgmname;
-      argv[1] = "--server";
-      argv[2] = NULL;
-
-      i=0;
-      if (log_get_fd () != -1)
-        no_close_list[i++] = log_get_fd ();
-      no_close_list[i++] = fileno (stderr);
-      no_close_list[i] = -1;
-
-      /* connect to the agent and perform initial handshaking */
-      rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv,
-                                no_close_list);
     }
   else
     {
@@ -125,16 +135,16 @@ start_agent (void)
       int pid;
 
       infostr = xstrdup (infostr);
-      if ( !(p = strchr (infostr, ':')) || p == infostr)
+      if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
         {
           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
           xfree (infostr);
           force_pipe_server = 1;
-          return start_agent ();
+          return start_agent (ctrl);
         }
       *p++ = 0;
       pid = atoi (p);
-      while (*p && *p != ':')
+      while (*p && *p != PATHSEP_C)
         p++;
       prot = *p? atoi (p+1) : 0;
       if (prot != 1)
@@ -143,7 +153,7 @@ start_agent (void)
                      prot);
           xfree (infostr);
           force_pipe_server = 1;
-          return start_agent ();
+          return start_agent (ctrl);
         }
 
       rc = assuan_socket_connect (&ctx, infostr, pid);
@@ -152,7 +162,7 @@ start_agent (void)
         {
           log_error (_("can't connect to the agent - trying fall back\n"));
           force_pipe_server = 1;
-          return start_agent ();
+          return start_agent (ctrl);
         }
     }
 
@@ -170,118 +180,9 @@ start_agent (void)
   if (rc)
     return map_assuan_err (rc);
 
-  dft_display = getenv ("DISPLAY");
-  if (opt.display || dft_display)
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION display=%s",
-                   opt.display ? opt.display : dft_display) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-  if (!opt.ttyname)
-    {
-      dft_ttyname = getenv ("GPG_TTY");
-      if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
-        dft_ttyname = ttyname (0);
-    }
-  if (opt.ttyname || dft_ttyname)
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION ttyname=%s",
-                   opt.ttyname ? opt.ttyname : dft_ttyname) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-  dft_ttytype = getenv ("TERM");
-  if (opt.ttytype || (dft_ttyname && dft_ttytype))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION ttytype=%s",
-                   opt.ttyname ? opt.ttytype : dft_ttytype) < 0)
-       return OUT_OF_CORE (errno);
-      rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                           NULL);
-      free (optstr);
-      if (rc)
-       return map_assuan_err (rc);
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
-  old_lc = setlocale (LC_CTYPE, NULL);
-  if (old_lc)
-    {
-      old_lc = strdup (old_lc);
-      if (!old_lc)
-        return OUT_OF_CORE (errno);
-    }
-  dft_lc = setlocale (LC_CTYPE, "");
-#endif
-  if (opt.lc_ctype || (dft_ttyname && dft_lc))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION lc-ctype=%s",
-                   opt.lc_ctype ? opt.lc_ctype : dft_lc) < 0)
-       rc = OUT_OF_CORE (errno);
-      else
-       {
-         rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                               NULL);
-         free (optstr);
-         if (rc)
-           rc = map_assuan_err (rc);
-       }
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
-  if (old_lc)
-    {
-      setlocale (LC_CTYPE, old_lc);
-      free (old_lc);
-    }
-#endif
-  if (rc)
-    return rc;
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
-  old_lc = setlocale (LC_MESSAGES, NULL);
-  if (old_lc)
-    {
-      old_lc = strdup (old_lc);
-      if (!old_lc)
-        return OUT_OF_CORE (errno);
-    }
-  dft_lc = setlocale (LC_MESSAGES, "");
-#endif
-  if (opt.lc_messages || (dft_ttyname && dft_lc))
-    {
-      char *optstr;
-      if (asprintf (&optstr, "OPTION lc-messages=%s",
-                   opt.lc_messages ? opt.lc_messages : dft_lc) < 0)
-       rc = OUT_OF_CORE (errno);
-      else
-       {
-         rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
-                               NULL);
-         free (optstr);
-         if (rc)
-           rc = map_assuan_err (rc);
-       }
-    }
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
-  if (old_lc)
-    {
-      setlocale (LC_MESSAGES, old_lc);
-      free (old_lc);
-    }
-#endif
-
-  return rc;
+  return send_pinentry_environment (agent_ctx, GPG_ERR_SOURCE_DEFAULT,
+                                    opt.display, opt.ttyname, opt.ttytype,
+                                    opt.lc_ctype, opt.lc_messages);
 }
 
 
@@ -301,7 +202,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length)
 /* Call the agent to do a sign operation using the key identified by
    the hex string KEYGRIP. */
 int
-gpgsm_agent_pksign (const char *keygrip, const char *desc,
+gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
                     unsigned char *digest, size_t digestlen, int digestalgo,
                     char **r_buf, size_t *r_buflen )
 {
@@ -311,7 +212,7 @@ gpgsm_agent_pksign (const char *keygrip, const char *desc,
   size_t len;
 
   *r_buf = NULL;
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -386,7 +287,7 @@ inq_ciphertext_cb (void *opaque, const char *keyword)
 /* Call the agent to do a decrypt operation using the key identified by
    the hex string KEYGRIP. */
 int
-gpgsm_agent_pkdecrypt (const char *keygrip, const char *desc,
+gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
                        ksba_const_sexp_t ciphertext, 
                        char **r_buf, size_t *r_buflen )
 {
@@ -406,7 +307,7 @@ gpgsm_agent_pkdecrypt (const char *keygrip, const char *desc,
   if (!ciphertextlen)
     return gpg_error (GPG_ERR_INV_VALUE);
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -484,7 +385,8 @@ inq_genkey_parms (void *opaque, const char *keyword)
 \f
 /* Call the agent to generate a newkey */
 int
-gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
+gpgsm_agent_genkey (ctrl_t ctrl,
+                    ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
 {
   int rc;
   struct genkey_parm_s gk_parm;
@@ -493,7 +395,7 @@ gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
   char *buf;
 
   *r_pubkey = NULL;
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -531,13 +433,13 @@ gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
 /* Ask the agent whether the certificate is in the list of trusted
    keys */
 int
-gpgsm_agent_istrusted (ksba_cert_t cert)
+gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert)
 {
   int rc;
   char *fpr;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -558,13 +460,13 @@ gpgsm_agent_istrusted (ksba_cert_t cert)
 
 /* Ask the agent to mark CERT as a trusted Root-CA one */
 int
-gpgsm_agent_marktrusted (ksba_cert_t cert)
+gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
 {
   int rc;
   char *fpr, *dn;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -595,12 +497,12 @@ gpgsm_agent_marktrusted (ksba_cert_t cert)
 /* Ask the agent whether the a corresponding secret key is available
    for the given keygrip */
 int
-gpgsm_agent_havekey (const char *hexkeygrip)
+gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
 {
   int rc;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -685,14 +587,14 @@ learn_cb (void *opaque, const void *buffer, size_t length)
   
 /* Call the agent to learn about a smartcard */
 int
-gpgsm_agent_learn ()
+gpgsm_agent_learn (ctrl_t ctrl)
 {
   int rc;
   struct learn_parm_s learn_parm;
   membuf_t data;
   size_t len;
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;
 
@@ -714,12 +616,12 @@ gpgsm_agent_learn ()
    HEXKEYGRIP. If DESC is not NULL, display instead of the default
    description message. */
 int
-gpgsm_agent_passwd (const char *hexkeygrip, const char *desc)
+gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
 {
   int rc;
   char line[ASSUAN_LINELENGTH];
 
-  rc = start_agent ();
+  rc = start_agent (ctrl);
   if (rc)
     return rc;