- doc clarification (identity manages egos, not identities)
[oweals/gnunet.git] / src / arm / gnunet-service-arm.c
index 1196b20aa7242716a4bc1910348684d70a92a9c0..f5323c04240860c7c3f147e26de3dbcf59ea8d20 100644 (file)
@@ -36,6 +36,7 @@
  */
 #define MAX_NOTIFY_QUEUE 1024
 
+
 /**
  * List of our services.
  */
@@ -159,7 +160,7 @@ struct ServiceList
 
   /**
    * Is this service to be started by default (or did a client tell us explicitly
-   * to start it)?  GNUNET_NO if the service is started only upon 'accept' on a
+   * to start it)?  #GNUNET_NO if the service is started only upon 'accept' on a
    * listen socket or possibly explicitly by a client changing the value.
    */
   int is_default;
@@ -217,6 +218,16 @@ static struct GNUNET_DISK_PipeHandle *sigpipe;
  */
 static int in_shutdown;
 
+/**
+ * Are we starting user services?
+ */
+static int start_user = GNUNET_YES;
+
+/**
+ * Are we starting system services?
+ */
+static int start_system = GNUNET_YES;
+
 /**
  * Handle to our server instance.  Our server is a bit special in that
  * its service is not immediately stopped once we get a shutdown
@@ -387,7 +398,9 @@ broadcast_status (const char *name,
  *                   being started. 0 if starting was not requested.
  */
 static void
-start_process (struct ServiceList *sl, struct GNUNET_SERVER_Client *client, uint64_t request_id)
+start_process (struct ServiceList *sl,
+               struct GNUNET_SERVER_Client *client,
+               uint64_t request_id)
 {
   char *loprefix;
   char *options;
@@ -582,34 +595,36 @@ create_listen_socket (struct sockaddr *sa, socklen_t addr_len,
   static int on = 1;
   struct GNUNET_NETWORK_Handle *sock;
   struct ServiceListeningInfo *sli;
+  int match_uid;
+  int match_gid;
 
   switch (sa->sa_family)
-    {
-    case AF_INET:
-      sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
-      break;
-    case AF_INET6:
-      sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
-      break;
-    case AF_UNIX:
-      if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0)        /* Do not bind to blank UNIX path! */
-       return;
-      sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
-      break;
-    default:
-      GNUNET_break (0);
-      sock = NULL;
-      errno = EAFNOSUPPORT;
-      break;
-    }
-  if (NULL == sock)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Unable to create socket for service `%s': %s\n"),
-                 sl->name, STRERROR (errno));
-      GNUNET_free (sa);
+  {
+  case AF_INET:
+    sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
+    break;
+  case AF_INET6:
+    sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
+    break;
+  case AF_UNIX:
+    if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0)  /* Do not bind to blank UNIX path! */
       return;
-    }
+    sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
+    break;
+  default:
+    GNUNET_break (0);
+    sock = NULL;
+    errno = EAFNOSUPPORT;
+    break;
+  }
+  if (NULL == sock)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Unable to create socket for service `%s': %s\n"),
+                sl->name, STRERROR (errno));
+    GNUNET_free (sa);
+    return;
+  }
   if (GNUNET_NETWORK_socket_setsockopt
       (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
@@ -622,24 +637,39 @@ create_listen_socket (struct sockaddr *sa, socklen_t addr_len,
                         "setsockopt");
 #endif
 
-  if (GNUNET_NETWORK_socket_bind
-      (sock, (const struct sockaddr *) sa, addr_len, 0) != GNUNET_OK)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                 _
-                 ("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
-                 sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno));
-      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
-      GNUNET_free (sa);
-      return;
-    }
+  if (GNUNET_OK !=
+      GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _
+                ("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
+                sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno));
+    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
+    GNUNET_free (sa);
+    return;
+  }
+#ifndef WINDOWS
+  if (AF_UNIX == sa->sa_family)
+  {
+    match_uid =
+      GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name,
+                                            "UNIX_MATCH_UID");
+    match_gid =
+      GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name,
+                                            "UNIX_MATCH_GID");
+    GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sa)->sun_path,
+                                 match_uid,
+                                 match_gid);
+
+  }
+#endif
   if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK)
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
-      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
-      GNUNET_free (sa);
-      return;
-    }
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
+    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
+    GNUNET_free (sa);
+    return;
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              _("ARM now monitors connections to service `%s' at `%s'\n"),
              sl->name, GNUNET_a2s (sa, addr_len));
@@ -821,7 +851,7 @@ handle_stop (void *cls, struct GNUNET_SERVER_Client *client,
   broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
   /* no signal_start - only when it's STOPPED */
   sl->killed_at = GNUNET_TIME_absolute_get ();
-  if (0 != GNUNET_OS_process_kill (sl->proc, SIGTERM))
+  if (0 != GNUNET_OS_process_kill (sl->proc, GNUNET_TERM_SIG))
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
   sl->killing_client = client;
   sl->killing_client_request_id = request_id;
@@ -983,7 +1013,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                  "Stopping service `%s'\n",
                  pos->name);
       pos->killed_at = GNUNET_TIME_absolute_get ();
-      if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM))
+      if (0 != GNUNET_OS_process_kill (pos->proc, GNUNET_TERM_SIG))
        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
     }
     else
@@ -1256,6 +1286,19 @@ setup_service (void *cls, const char *section)
       /* not a service section */
       return;
     }
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_have_value (cfg, section, "USER_SERVICE")) &&
+      (GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "USER_SERVICE")))
+  {
+    if (GNUNET_NO == start_user)
+      return; /* user service, and we don't deal with those */
+  }
+  else
+  {
+    if (GNUNET_NO == start_system)
+      return; /* system service, and we don't deal with those */
+  }
   sl = find_service (section);
   if (NULL != sl)
   {
@@ -1295,6 +1338,7 @@ setup_service (void *cls, const char *section)
     sl->pipe_control = GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "PIPECONTROL");
 #endif
   GNUNET_CONTAINER_DLL_insert (running_head, running_tail, sl);
+
   if (GNUNET_YES !=
       GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "AUTOSTART"))
     return;
@@ -1392,7 +1436,20 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
       GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_POSTFIX",
                                             &final_option))
     final_option = GNUNET_strdup ("");
-
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "USER_ONLY"))
+  {
+    GNUNET_break (GNUNET_YES == start_user);
+    start_system = GNUNET_NO;
+    return;
+  }
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "SYSTEM_ONLY"))
+  {
+    GNUNET_break (GNUNET_YES == start_system);
+    start_user = GNUNET_NO;
+    return;
+  }
   GNUNET_CONFIGURATION_iterate_sections (cfg, &setup_service, NULL);
 
   /* start default services... */