Update plibc header
[oweals/gnunet.git] / src / util / service.c
index 2e75125cedfb4b85816bd5b07671e2db07069c79..d8ca5eba6cee817b8e97f21fdad80fdc1e4d8485 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
  * @author Christian Grothoff
  */
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_configuration_lib.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_directories.h"
-#include "gnunet_disk_lib.h"
-#include "gnunet_getopt_lib.h"
-#include "gnunet_os_lib.h"
+#include "gnunet_util_lib.h"
 #include "gnunet_protocols.h"
+#include "gnunet_directories.h"
 #include "gnunet_resolver_service.h"
-#include "gnunet_server_lib.h"
-#include "gnunet_service_lib.h"
+
+#if HAVE_MALLINFO
+#include <malloc.h>
+#include "gauger.h"
+#endif
+
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
@@ -62,6 +61,7 @@ struct IPv4NetworkSet
 };
 
 /**
+
  * @brief network in CIDR notation for IPV6.
  */
 struct IPv6NetworkSet
@@ -78,10 +78,19 @@ struct IPv6NetworkSet
 };
 
 
+/**
+ * Start task that may speed up our system clock artificially
+ *
+ * @param cfg configuration to use
+ * @return GNUNET_OK on success, GNUNET_SYSERR if the speedup was not configured
+ */
 int
 GNUNET_SPEEDUP_start_ (const struct GNUNET_CONFIGURATION_Handle *cfg);
 
-int
+/**
+ * Stop tasks that modify clock behavior.
+ */
+void
 GNUNET_SPEEDUP_stop_ (void);
 
 
@@ -92,7 +101,7 @@ GNUNET_SPEEDUP_stop_ (void);
  * with a semicolon). The network must be given in dotted-decimal
  * notation. The netmask can be given in CIDR notation (/16) or
  * in dotted-decimal (/255.255.0.0).
- * 
+ *
  * @param routeList a string specifying the forbidden networks
  * @return the converted list, NULL if the synatx is flawed
  */
@@ -245,7 +254,7 @@ parse_ipv4_specification (const char *routeList)
  * with a semicolon). The network must be given in colon-hex
  * notation.  The netmask must be given in CIDR notation (/16) or
  * can be omitted to specify a single host.
- * 
+ *
  * @param routeListX a string specifying the forbidden networks
  * @return the converted list, NULL if the synatx is flawed
  */
@@ -650,16 +659,18 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
 #ifndef WINDOWS
   case AF_UNIX:
     ret = GNUNET_OK;            /* always OK for now */
-    if (GNUNET_YES == sctx->match_uid) 
+    if (GNUNET_YES == sctx->match_uid)
     {
       /* UID match required */
-      ret = (NULL != uc) && (uc->uid == geteuid ());
+      ret = (NULL != uc) && ( (0 == uc->uid) || (uc->uid == geteuid ()) );
     }
     else if ( (GNUNET_YES == sctx->match_gid) &&
-             ( (NULL == uc) || (uc->uid != geteuid ()) ) )
+             ( (NULL == uc) ||
+               ( (0 != uc->uid) &&
+                 (uc->uid != geteuid ()) ) ) )
     {
       /* group match required and UID does not match */
-      if (NULL == uc) 
+      if (NULL == uc)
       {
        /* no credentials, group match not possible */
        ret = GNUNET_NO;
@@ -707,7 +718,7 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
   if (GNUNET_OK != ret)
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
-         _("Access from `%s' denied to service `%s'\n"), 
+         _("Access from `%s' denied to service `%s'\n"),
         GNUNET_a2s (addr, addrlen),
          sctx->service_name);
   }
@@ -739,9 +750,9 @@ get_pid_file_name (struct GNUNET_SERVICE_Context *sctx)
  * Parse an IPv4 access control list.
  *
  * @param ret location where to write the ACL (set)
- * @param sctx service context to use to get the configuration 
+ * @param sctx service context to use to get the configuration
  * @param option name of the ACL option to parse
- * @return GNUNET_SYSERR on parse error, GNUNET_OK on success (including 
+ * @return GNUNET_SYSERR on parse error, GNUNET_OK on success (including
  *         no ACL configured)
  */
 static int
@@ -752,7 +763,7 @@ process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
 
   if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option))
   {
-    *ret = NULL;    
+    *ret = NULL;
     return GNUNET_OK;
   }
   GNUNET_break (GNUNET_OK ==
@@ -776,9 +787,9 @@ process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx,
  * Parse an IPv6 access control list.
  *
  * @param ret location where to write the ACL (set)
- * @param sctx service context to use to get the configuration 
+ * @param sctx service context to use to get the configuration
  * @param option name of the ACL option to parse
- * @return GNUNET_SYSERR on parse error, GNUNET_OK on success (including 
+ * @return GNUNET_SYSERR on parse error, GNUNET_OK on success (including
  *         no ACL configured)
  */
 static int
@@ -973,12 +984,14 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name,
     {
       LOG (GNUNET_ERROR_TYPE_WARNING,
            _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
-           sizeof (s_un.sun_path));
-      GNUNET_free_non_null (hostname);
-      GNUNET_free (unixpath);
-      return GNUNET_SYSERR;
+           (unsigned long long) sizeof (s_un.sun_path));
+      unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
+      LOG (GNUNET_ERROR_TYPE_INFO,
+          _("Using `%s' instead\n"), unixpath);
     }
-
+  }
+  if (NULL != unixpath)
+  {
     desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
     if (NULL == desc)
     {
@@ -1280,8 +1293,6 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
   int tolerant;
 
 #ifndef MINGW
-  const char *lpid;
-  unsigned int pid;
   const char *nfds;
   unsigned int cnt;
   int flags;
@@ -1322,9 +1333,7 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
 
 #ifndef MINGW
   errno = 0;
-  if ((NULL != (lpid = getenv ("LISTEN_PID"))) &&
-      (1 == SSCANF (lpid, "%u", &pid)) && (getpid () == (pid_t) pid) &&
-      (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
+  if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
       (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
       (cnt + 4 < FD_SETSIZE))
   {
@@ -1349,7 +1358,6 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
         break;
       }
     }
-    unsetenv ("LISTEN_PID");
     unsetenv ("LISTEN_FDS");
   }
 #else
@@ -1428,7 +1436,7 @@ write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
   {
     /* we get to create a directory -- and claim it
      * as ours! */
-    GNUNET_DISK_directory_create (rdir);
+    (void) GNUNET_DISK_directory_create (rdir);
     if ((NULL != user) && (0 < strlen (user)))
       GNUNET_DISK_file_change_owner (rdir, user);
   }
@@ -1492,6 +1500,9 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct GNUNET_SERVICE_Context *sctx = cls;
   unsigned int i;
 
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+    return;
+  (void) GNUNET_SPEEDUP_start_ (sctx->cfg);
   GNUNET_RESOLVER_connect (sctx->cfg);
   if (NULL != sctx->lsocks)
     sctx->server =
@@ -1554,7 +1565,7 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  * Detach from terminal.
  *
  * @param sctx service context
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
 detach_terminal (struct GNUNET_SERVICE_Context *sctx)
@@ -1717,6 +1728,7 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name,
 #define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0)
 
   int err;
+  int ret;
   char *cfg_fn;
   char *loglev;
   char *logfile;
@@ -1736,7 +1748,7 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name,
     GNUNET_GETOPT_OPTION_HELP (NULL),
     GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev),
     GNUNET_GETOPT_OPTION_LOGFILE (&logfile),
-    GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION),
+    GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION),
     GNUNET_GETOPT_OPTION_END
   };
   err = 1;
@@ -1753,14 +1765,29 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name,
   sctx.task_cls = task_cls;
   sctx.service_name = service_name;
   sctx.cfg = cfg = GNUNET_CONFIGURATION_create ();
+
   /* setup subsystems */
-  if (GNUNET_SYSERR ==
-      GNUNET_GETOPT_run (service_name, service_options, argc, argv))
+  ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv);
+  if (GNUNET_SYSERR == ret)
+    goto shutdown;
+  if (GNUNET_NO == ret)
+  {
+    err = 0;
     goto shutdown;
+  }
   if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile))
     HANDLE_ERROR;
-  if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_fn))
-    goto shutdown;
+  if (GNUNET_YES ==
+      GNUNET_DISK_file_test (cfg_fn))
+    (void) GNUNET_CONFIGURATION_load (cfg, cfg_fn);
+  else
+  {
+    (void) GNUNET_CONFIGURATION_load (cfg, NULL);
+    if (0 != strcmp (cfg_fn, GNUNET_DEFAULT_USER_CONFIG_FILE))
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Could not access configuration file `%s'\n"),
+                 cfg_fn);
+  }
   if (GNUNET_OK != setup_service (&sctx))
     goto shutdown;
   if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sctx)))
@@ -1783,7 +1810,6 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name,
   /* actually run service */
   err = 0;
   GNUNET_SCHEDULER_run (&service_task, &sctx);
-  GNUNET_SPEEDUP_start_ (cfg);
   /* shutdown */
   if ((1 == do_daemonize) && (NULL != sctx.server))
     pid_file_delete (&sctx);
@@ -1796,7 +1822,26 @@ shutdown:
       LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
     GNUNET_break (0 == CLOSE (sctx.ready_confirm_fd));
   }
+#if HAVE_MALLINFO
+  {
+    char *counter;
+
+    if ( (GNUNET_YES ==
+         GNUNET_CONFIGURATION_have_value (sctx.cfg, service_name,
+                                          "GAUGER_HEAP")) &&
+        (GNUNET_OK ==
+         GNUNET_CONFIGURATION_get_value_string (sctx.cfg, service_name,
+                                                "GAUGER_HEAP",
+                                                &counter)) )
+    {
+      struct mallinfo mi;
 
+      mi = mallinfo ();
+      GAUGER (service_name, counter, mi.usmblks, "blocks");
+      GNUNET_free (counter);
+    }
+  }
+#endif
   GNUNET_SPEEDUP_stop_ ();
   GNUNET_CONFIGURATION_destroy (cfg);
   i = 0;
@@ -1896,6 +1941,26 @@ GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx)
 {
   unsigned int i;
 
+#if HAVE_MALLINFO
+  {
+    char *counter;
+
+    if ( (GNUNET_YES ==
+         GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name,
+                                          "GAUGER_HEAP")) &&
+        (GNUNET_OK ==
+         GNUNET_CONFIGURATION_get_value_string (sctx->cfg, sctx->service_name,
+                                                "GAUGER_HEAP",
+                                                &counter)) )
+    {
+      struct mallinfo mi;
+
+      mi = mallinfo ();
+      GAUGER (sctx->service_name, counter, mi.usmblks, "blocks");
+      GNUNET_free (counter);
+    }
+  }
+#endif
   if (GNUNET_SCHEDULER_NO_TASK != sctx->shutdown_task)
   {
     GNUNET_SCHEDULER_cancel (sctx->shutdown_task);