Translate dirmngr strings
[gnupg.git] / dirmngr / dirmngr.c
index 12b74bd..8e1aa11 100644 (file)
 #endif
 #include <sys/stat.h>
 #include <unistd.h>
-#include <signal.h>
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif
 #include <pth.h>
 
 
 #define JNLIB_NEED_LOG_LOGV
+#define JNLIB_NEED_AFLOCAL
 #include "dirmngr.h"
 
 #include <assuan.h> 
 #include "misc.h"
 #include "ldapserver.h"
 #include "asshelp.h"
+#include "ldap-wrapper.h"
+
+/* The plain Windows version uses the windows service system.  For
+   example to start the service you may use "sc start dirmngr".
+   WindowsCE does not support this; the service system over there is
+   based on a single process with all services being DLLs - we can't
+   support this easily.  */
+#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
+# define USE_W32_SERVICE 1
+#endif
+
 
 enum cmd_and_opt_values {
   aNull = 0,
@@ -119,7 +133,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_c (aServer,   "server",  N_("run in server mode (foreground)") ),
   ARGPARSE_c (aDaemon,   "daemon",  N_("run in daemon mode (background)") ),
-#ifdef HAVE_W32_SYSTEM
+#ifdef USE_W32_SERVICE
   ARGPARSE_c (aService,  "service", N_("run as windows service (background)")),
 #endif
   ARGPARSE_c (aListCRLs, "list-crls", N_("list the contents of the CRL cache")),
@@ -180,7 +194,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_i (oMaxReplies, "max-replies", 
                 N_("|N|do not return more than N items in one query")),
 
-  ARGPARSE_s_s (oSocketName, "socket-name", N_("|FILE|listen on socket FILE")),
+  ARGPARSE_s_s (oSocketName, "socket-name", "@"),  /* Only for debugging.  */
 
   ARGPARSE_s_u (oFakedSystemTime, "faked-system-time", "@"), /*(epoch time)*/
   ARGPARSE_p_u (oDebug,    "debug", "@"),
@@ -374,39 +388,13 @@ set_debug (void)
 static void
 wrong_args (const char *text)
 {
-  fputs (_("usage: dirmngr [options] "), stderr);
-  fputs (text, stderr);
-  putc ('\n', stderr);
+  es_fputs (_("usage: dirmngr [options] "), es_stderr);
+  es_fputs (text, es_stderr);
+  es_putc ('\n', es_stderr);
   dirmngr_exit (2);
 }
 
 
-/* Helper to start the reaper thread for the ldap wrapper.  */
-static void
-launch_reaper_thread (void)
-{
-  static int done;
-  pth_attr_t tattr;
-
-  if (done)
-    return;
-  done = 1;
-
-  tattr = pth_attr_new();
-  pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
-  pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
-  pth_attr_set (tattr, PTH_ATTR_NAME, "ldap-reaper");
-
-  if (!pth_spawn (tattr, ldap_wrapper_thread, NULL))
-    {
-      log_error (_("error spawning ldap wrapper reaper thread: %s\n"),
-                 strerror (errno) );
-      dirmngr_exit (1);
-    }
-  pth_attr_destroy (tattr);
-}
-
-
 /* Helper to stop the reaper thread for the ldap wrapper.  */
 static void
 shutdown_reaper (void)
@@ -514,7 +502,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
 }
 
 
-#ifdef HAVE_W32_SYSTEM
+#ifdef USE_W32_SERVICE
 /* The global status of our service.  */
 SERVICE_STATUS_HANDLE service_handle;
 SERVICE_STATUS service_status;
@@ -544,7 +532,7 @@ w32_service_control (DWORD control, DWORD event_type, LPVOID event_data,
     }
   return 0;
 }
-#endif /*HAVE_W32_SYSTEM*/
+#endif /*USE_W32_SERVICE*/
 
 #ifndef HAVE_W32_SYSTEM
 static int
@@ -559,14 +547,14 @@ pid_suffix_callback (unsigned long *r_suffix)
 #endif /*!HAVE_W32_SYSTEM*/
 
 
-#ifdef HAVE_W32_SYSTEM
-#define main real_main
+#ifdef USE_W32_SERVICE
+# define main real_main
 #endif
 int
 main (int argc, char **argv)
 {
-#ifdef HAVE_W32_SYSTEM
-#undef main
+#ifdef USE_W32_SERVICE
+# undef main
 #endif
   enum cmd_and_opt_values cmd = 0;
   ARGPARSE_ARGS pargs;
@@ -589,7 +577,7 @@ main (int argc, char **argv)
   int homedir_seen = 0;
   struct assuan_malloc_hooks malloc_hooks;
 
-#ifdef HAVE_W32_SYSTEM
+#ifdef USE_W32_SERVICE
   /* The option will be set by main() below if we should run as a
      system daemon.  */
   if (opt.system_service)
@@ -610,7 +598,7 @@ main (int argc, char **argv)
       service_status.dwWaitHint = 10000; /* 10 seconds timeout.  */
       SetServiceStatus (service_handle, &service_status); 
     }
-#endif /*HAVE_W32_SYSTEM*/
+#endif /*USE_W32_SERVICE*/
 
   set_strusage (my_strusage);
   log_set_prefix ("dirmngr", 1|4); 
@@ -833,7 +821,7 @@ main (int argc, char **argv)
     }
   if (configfp)
     {
-      fclose( configfp );
+      fclose (configfp);
       configfp = NULL;
       /* Keep a copy of the name so that it can be read on SIGHUP. */
       opt.config_filename = configname;
@@ -854,20 +842,28 @@ main (int argc, char **argv)
 
   if (greeting)
     {
-      fprintf (stderr, "%s %s; %s\n",
-               strusage(11), strusage(13), strusage(14) );
-      fprintf (stderr, "%s\n", strusage(15) );
+      es_fprintf (es_stderr, "%s %s; %s\n",
+                  strusage(11), strusage(13), strusage(14) );
+      es_fprintf (es_stderr, "%s\n", strusage(15) );
     }
 
 #ifdef IS_DEVELOPMENT_VERSION
   log_info ("NOTE: this is a development version!\n");
 #endif
 
+  if (!access ("/etc/dirmngr", F_OK) && !strncmp (opt.homedir, "/etc/", 5))
+    log_info 
+      ("NOTE: DirMngr is now a proper part of GnuPG.  The configuration and"
+       " other directory names changed.  Please check that no other version"
+       " of dirmngr is still installed.  To disable this warning, remove the"
+       " directory `/etc/dirmngr'.\n");
+  
   if (gnupg_faked_time_p ())
     {
-      gnupg_isotime_t tbuf;
+      log_info (_("WARNING: running with faked system time: "));
       gnupg_get_isotime (tbuf);
-      log_info (_("WARNING: running with faked system time %s\n"), tbuf);
+      dump_isotime (tbuf);
+      log_printf ("\n");
     }
 
   set_debug ();
@@ -902,6 +898,7 @@ main (int argc, char **argv)
 
   if (cmd == aServer)
     {
+      /* Note that this server mode is maily useful for debugging.  */
       if (argc)
         wrong_args ("--server");
 
@@ -919,7 +916,7 @@ main (int argc, char **argv)
           log_debug ("... okay\n");
         }
 
-      launch_reaper_thread ();
+      ldap_wrapper_launch_thread ();
       cert_cache_init ();
       crl_cache_init ();
       start_command_handler (ASSUAN_INVALID_FD);
@@ -969,13 +966,18 @@ main (int argc, char **argv)
       memset (&serv_addr, 0, sizeof serv_addr);
       serv_addr.sun_family = AF_UNIX;
       strcpy (serv_addr.sun_path, socket_name);
-      len = (offsetof (struct sockaddr_un, sun_path)
-             + strlen (serv_addr.sun_path) + 1);
+      len = SUN_LEN (&serv_addr);
 
       rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
-      if (rc == -1 && errno == EADDRINUSE)
+      if (rc == -1 
+          && (errno == EADDRINUSE
+#ifdef HAVE_W32_SYSTEM
+              || errno == EEXIST
+#endif
+              ))
        {
-         remove (socket_name);
+          /* Fixme: We should test whether a dirmngr is already running. */
+         gnupg_remove (socket_name);
          rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
        }
       if (rc != -1 
@@ -1000,8 +1002,11 @@ main (int argc, char **argv)
       if (opt.verbose)
         log_info (_("listening on socket `%s'\n"), socket_name );
 
-      fflush (NULL);
+      es_fflush (NULL);
 
+      /* Note: We keep the dirmngr_info output only for the sake of
+         existing scripts which might use this to detect a successful
+         start of the dirmngr.  */
 #ifdef HAVE_W32_SYSTEM
       pid = getpid ();
       printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid);
@@ -1009,7 +1014,7 @@ main (int argc, char **argv)
       pid = pth_fork ();
       if (pid == (pid_t)-1) 
         {
-          log_fatal (_("fork failed: %s\n"), strerror (errno) );
+          log_fatal (_("error forking process: %s\n"), strerror (errno));
           dirmngr_exit (1);
         }
 
@@ -1032,7 +1037,7 @@ main (int argc, char **argv)
               dirmngr_exit (1);
             }
           /* Print the environment string, so that the caller can use
-             shell's eval to set it */
+             shell's eval to set it.  But see above.  */
           if (csh_style)
             {
               *strchr (infostr, '=') = ' ';
@@ -1066,7 +1071,7 @@ main (int argc, char **argv)
             }
           if (setsid() == -1)
             {
-              log_error (_("setsid() failed: %s\n"), strerror(errno) );
+              log_error ("setsid() failed: %s\n", strerror(errno) );
               dirmngr_exit (1);
             }
 
@@ -1076,16 +1081,16 @@ main (int argc, char **argv)
 
           if (chdir("/"))
             {
-              log_error (_("chdir to / failed: %s\n"), strerror (errno));
+              log_error ("chdir to / failed: %s\n", strerror (errno));
               dirmngr_exit (1);
             }
         }
 #endif
 
-      launch_reaper_thread ();
+      ldap_wrapper_launch_thread ();
       cert_cache_init ();
       crl_cache_init ();
-#ifdef HAVE_W32_SYSTEM
+#ifdef USE_W32_SERVICE
       if (opt.system_service)
        {
          service_status.dwCurrentState = SERVICE_RUNNING;
@@ -1095,7 +1100,7 @@ main (int argc, char **argv)
       handle_connections (fd);
       assuan_sock_close (fd);
       shutdown_reaper ();
-#ifdef HAVE_W32_SYSTEM
+#ifdef USE_W32_SERVICE
       if (opt.system_service)
        {
          service_status.dwCurrentState = SERVICE_STOPPED;
@@ -1108,9 +1113,9 @@ main (int argc, char **argv)
       /* Just list the CRL cache and exit. */
       if (argc)
         wrong_args ("--list-crls");
-      launch_reaper_thread ();
+      ldap_wrapper_launch_thread ();
       crl_cache_init ();
-      crl_cache_list (stdout);
+      crl_cache_list (es_stdout);
     }
   else if (cmd == aLoadCRL)
     {
@@ -1119,7 +1124,7 @@ main (int argc, char **argv)
       memset (&ctrlbuf, 0, sizeof ctrlbuf);
       dirmngr_init_default_ctrl (&ctrlbuf);
 
-      launch_reaper_thread ();
+      ldap_wrapper_launch_thread ();
       cert_cache_init ();
       crl_cache_init ();
       if (!argc)
@@ -1141,7 +1146,7 @@ main (int argc, char **argv)
       memset (&ctrlbuf, 0, sizeof ctrlbuf);
       dirmngr_init_default_ctrl (&ctrlbuf);
 
-      launch_reaper_thread ();
+      ldap_wrapper_launch_thread ();
       cert_cache_init ();
       crl_cache_init ();
       rc = crl_fetch (&ctrlbuf, argv[0], &reader);
@@ -1260,7 +1265,7 @@ main (int argc, char **argv)
 }
 
 
-#ifdef HAVE_W32_SYSTEM
+#ifdef USE_W32_SERVICE
 int
 main (int argc, char *argv[])
 {
@@ -1291,7 +1296,7 @@ main (int argc, char *argv[])
       return 0;
     }
 }
-#endif
+#endif /*USE_W32_SERVICE*/
 
 
 static void
@@ -1307,7 +1312,7 @@ cleanup (void)
     {
       cleanup_socket = 0;
       if (socket_name && *socket_name)
-        remove (socket_name);
+        gnupg_remove (socket_name);
     }
 }
 
@@ -1351,9 +1356,9 @@ parse_ldapserver_file (const char* filename)
   ldap_server_t server, serverstart, *serverend;
   int c;
   unsigned int lineno = 0;
-  FILE *fp;
+  estream_t fp;
 
-  fp = fopen (filename, "r");
+  fp = es_fopen (filename, "r");
   if (!fp)
     {
       log_error (_("error opening `%s': %s\n"), filename, strerror (errno));
@@ -1362,18 +1367,18 @@ parse_ldapserver_file (const char* filename)
 
   serverstart = NULL;
   serverend = &serverstart;
-  while (fgets (buffer, sizeof buffer, fp))
+  while (es_fgets (buffer, sizeof buffer, fp))
     {
       lineno++;
       if (!*buffer || buffer[strlen(buffer)-1] != '\n')
         {
-          if (*buffer && feof (fp))
+          if (*buffer && es_feof (fp))
             ; /* Last line not terminated - continue. */
           else
             {
               log_error (_("%s:%u: line too long - skipped\n"),
                          filename, lineno);
-              while ( (c=fgetc (fp)) != EOF && c != '\n')
+              while ( (c=es_fgetc (fp)) != EOF && c != '\n')
                 ; /* Skip until end of line. */
               continue;
             }
@@ -1393,9 +1398,9 @@ parse_ldapserver_file (const char* filename)
         }
     } 
   
-  if (ferror (fp))
+  if (es_ferror (fp))
     log_error (_("error reading `%s': %s\n"), filename, strerror (errno));
-  fclose (fp);
+  es_fclose (fp);
 
   return serverstart;
 }
@@ -1406,7 +1411,7 @@ parse_ocsp_signer (const char *string)
 {
   gpg_error_t err;
   char *fname;
-  FILE *fp;
+  estream_t fp;
   char line[256];
   char *p;
   fingerprint_list_t list, *list_tail, item;
@@ -1444,7 +1449,7 @@ parse_ocsp_signer (const char *string)
       fname = make_filename (opt.homedir, string, NULL);
     }
 
-  fp = fopen (fname, "r");
+  fp = es_fopen (fname, "r");
   if (!fp)
     {
       err = gpg_error_from_syserror ();
@@ -1457,16 +1462,16 @@ parse_ocsp_signer (const char *string)
   list_tail = &list;
   for (;;)
     {
-      if (!fgets (line, DIM(line)-1, fp) )
+      if (!es_fgets (line, DIM(line)-1, fp) )
         {
-          if (!feof (fp))
+          if (!es_feof (fp))
             {
               err = gpg_error_from_syserror ();
               log_error (_("%s:%u: read error: %s\n"),
                          fname, lnr, gpg_strerror (err));
               errflag = 1;
             }
-          fclose (fp);
+          es_fclose (fp);
           if (errflag)
             {
               while (list)
@@ -1484,7 +1489,7 @@ parse_ocsp_signer (const char *string)
       if (!*line || line[strlen(line)-1] != '\n')
         {
           /* Eat until end of line. */
-          while ( (c=getc (fp)) != EOF && c != '\n')
+          while ( (c=es_getc (fp)) != EOF && c != '\n')
             ;
           err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
                            /* */: GPG_ERR_INCOMPLETE_LINE);
@@ -1578,6 +1583,21 @@ reread_configuration (void)
 }
 
 
+/* A global function which allows us to trigger the reload stuff from
+   other places.  */
+void
+dirmngr_sighup_action (void)
+{
+  log_info (_("SIGHUP received - "
+              "re-reading configuration and flushing caches\n"));
+  reread_configuration ();
+  cert_cache_deinit (0);
+  crl_cache_deinit ();
+  cert_cache_init ();
+  crl_cache_init ();
+}
+
+
 
 /* The signal handler. */
 static void
@@ -1587,13 +1607,7 @@ handle_signal (int signo)
     {
 #ifndef HAVE_W32_SYSTEM
     case SIGHUP:
-      log_info (_("SIGHUP received - "
-                  "re-reading configuration and flushing caches\n"));
-      reread_configuration ();
-      cert_cache_deinit (0);
-      crl_cache_deinit ();
-      cert_cache_init ();
-      crl_cache_init ();
+      dirmngr_sighup_action ();
       break;
       
     case SIGUSR1: