use c99
[oweals/gnunet.git] / src / arm / gnunet-service-arm.c
index ea89b298942a779ea63ef782e3701d14a1e86957..0ccffa27ba03cde8a254929c1b64ec64c3513acd 100644 (file)
@@ -415,13 +415,8 @@ start_process (struct ServiceList *sl,
 {
   char *loprefix;
   char *options;
-  char *optpos;
-  char *optend;
-  const char *next;
   int use_debug;
   int is_simple_service;
-  char b;
-  char *val;
   struct ServiceListeningInfo *sli;
   SOCKTYPE *lsocks;
   unsigned int ls;
@@ -449,61 +444,69 @@ start_process (struct ServiceList *sl,
 
   /* obtain configuration */
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "PREFIX",
-                                            &loprefix))
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             sl->name,
+                                             "PREFIX",
+                                             &loprefix))
     loprefix = GNUNET_strdup (prefix_command);
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "OPTIONS",
-                                            &options))
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             sl->name,
+                                             "OPTIONS",
+                                             &options))
+    options = NULL;
+
+  {
+    char *new_options;
+    char *optpos;
+    char *fin_options;
+
+    fin_options = GNUNET_strdup (final_option);
+    /* replace '{}' with service name */
+    while (NULL != (optpos = strstr (fin_options, "{}")))
+      {
+        /* terminate string at opening parenthesis */
+        *optpos = 0;
+        GNUNET_asprintf (&new_options,
+                         "%s%s%s",
+                         fin_options,
+                         sl->name,
+                         optpos + 2);
+        GNUNET_free (fin_options);
+        fin_options = new_options;
+      }
+    if (NULL != options)
     {
-      options = GNUNET_strdup (final_option);
-      if (NULL == strstr (options, "%"))
-       {
-         /* replace '{}' with service name */
-         while (NULL != (optpos = strstr (options, "{}")))
-           {
-             optpos[0] = '%';
-             optpos[1] = 's';
-             GNUNET_asprintf (&optpos, options, sl->name);
-             GNUNET_free (options);
-             options = optpos;
-           }
-         /* replace '$PATH' with value associated with "PATH" */
-         while (NULL != (optpos = strstr (options, "$")))
-           {
-             optend = optpos + 1;
-             while (isupper ((unsigned char) *optend))
-               optend++;
-             b = *optend;
-             if ('\0' == b)
-               next = "";
-             else
-               next = optend + 1;
-             *optend = '\0';
-             if (GNUNET_OK !=
-                 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
-                                                        optpos + 1, &val))
-               val = GNUNET_strdup ("");
-             *optpos = '\0';
-             GNUNET_asprintf (&optpos, "%s%s%c%s", options, val, b, next);
-             GNUNET_free (options);
-             GNUNET_free (val);
-             options = optpos;
-           }
-       }
+      /* combine "fin_options" with "options" */
+      optpos = options;
+      GNUNET_asprintf (&options,
+                       "%s %s",
+                       fin_options,
+                       optpos);
+      GNUNET_free (optpos);
     }
-  use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG");
-
+    else
+    {
+      /* only have "fin_options", use that */
+      options = fin_options;
+    }
+  }
+  options = GNUNET_CONFIGURATION_expand_dollar (cfg,
+                                                options);
+  use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                                    sl->name,
+                                                    "DEBUG");
   {
     const char *service_type = NULL;
     const char *choices[] = { "GNUNET", "SIMPLE", NULL };
+
     is_simple_service = GNUNET_NO;
     if ( (GNUNET_OK ==
-            GNUNET_CONFIGURATION_get_value_choice (cfg,
-                                                   sl->name,
-                                                   "TYPE",
-                                                   choices,
-                                                   &service_type)) &&
+          GNUNET_CONFIGURATION_get_value_choice (cfg,
+                                                 sl->name,
+                                                 "TYPE",
+                                                 choices,
+                                                 &service_type)) &&
          (0 == strcasecmp (service_type, "SIMPLE")) )
       is_simple_service = GNUNET_YES;
   }
@@ -514,6 +517,7 @@ start_process (struct ServiceList *sl,
     /* A simple service will receive no GNUnet specific
        command line options. */
     binary = GNUNET_strdup (sl->binary);
+    binary = GNUNET_CONFIGURATION_expand_dollar (cfg, binary);
     GNUNET_asprintf (&quotedbinary,
                      "\"%s\"",
                      sl->binary);
@@ -527,8 +531,11 @@ start_process (struct ServiceList *sl,
     sl->proc =
       GNUNET_OS_start_process_s (sl->pipe_control,
                                  GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                 lsocks, loprefix, quotedbinary,
-                                 options, NULL);
+                                 lsocks,
+                                 loprefix,
+                                 quotedbinary,
+                                 options,
+                                 NULL);
   }
   else
   {
@@ -547,15 +554,23 @@ start_process (struct ServiceList *sl,
         sl->proc =
           GNUNET_OS_start_process_s (sl->pipe_control,
                                      GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                     lsocks, loprefix, quotedbinary, "-L",
-                                     "DEBUG", options, NULL);
+                                     lsocks,
+                                     loprefix,
+                                     quotedbinary,
+                                     "-L", "DEBUG",
+                                     options,
+                                     NULL);
       else
         sl->proc =
             GNUNET_OS_start_process_s (sl->pipe_control,
                                        GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                       lsocks, loprefix, quotedbinary, "-c",
-                                       sl->config, "-L",
-                                       "DEBUG", options, NULL);
+                                       lsocks,
+                                       loprefix,
+                                       quotedbinary,
+                                       "-c", sl->config,
+                                       "-L", "DEBUG",
+                                       options,
+                                       NULL);
     }
     else
     {
@@ -563,14 +578,21 @@ start_process (struct ServiceList *sl,
         sl->proc =
             GNUNET_OS_start_process_s (sl->pipe_control,
                                        GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                       lsocks, loprefix, quotedbinary,
-                                       options, NULL);
+                                       lsocks,
+                                       loprefix,
+                                       quotedbinary,
+                                       options,
+                                       NULL);
       else
         sl->proc =
             GNUNET_OS_start_process_s (sl->pipe_control,
                                        GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                       lsocks, loprefix, quotedbinary, "-c",
-                                       sl->config, options, NULL);
+                                       lsocks,
+                                       loprefix,
+                                       quotedbinary,
+                                       "-c", sl->config,
+                                       options,
+                                       NULL);
     }
   }
   GNUNET_free (binary);
@@ -630,18 +652,15 @@ find_service (const char *name)
  * create the service in order to relay the incoming connection to it
  *
  * @param cls callback data, `struct ServiceListeningInfo` describing a listen socket
- * @param tc context
  */
 static void
-accept_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+accept_connection (void *cls)
 {
   struct ServiceListeningInfo *sli = cls;
   struct ServiceList *sl = sli->sl;
 
   sli->accept_task = NULL;
   GNUNET_assert (GNUNET_NO == in_shutdown);
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-    return;
   start_process (sl, NULL, 0);
 }
 
@@ -759,7 +778,9 @@ create_listen_socket (struct sockaddr *sa,
   sli->accept_task =
     GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock,
                                   &accept_connection, sli);
-  GNUNET_CONTAINER_DLL_insert (sl->listen_head, sl->listen_tail, sli);
+  GNUNET_CONTAINER_DLL_insert (sl->listen_head,
+                              sl->listen_tail,
+                              sli);
 }
 
 
@@ -845,11 +866,9 @@ handle_start (void *cls,
  * Start a shutdown sequence.
  *
  * @param cls closure (refers to service)
- * @param tc task context
  */
 static void
-trigger_shutdown (void *cls,
-                  const struct GNUNET_SCHEDULER_TaskContext *tc)
+trigger_shutdown (void *cls)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Triggering shutdown\n");
@@ -893,17 +912,24 @@ handle_stop (void *cls,
              servicename);
   if (0 == strcasecmp (servicename, "arm"))
   {
-    broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
-    signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
+    broadcast_status (servicename,
+                     GNUNET_ARM_SERVICE_STOPPING, NULL);
+    signal_result (client,
+                  servicename,
+                  request_id,
+                  GNUNET_ARM_RESULT_STOPPING);
     GNUNET_SERVER_client_persist_ (client);
-    GNUNET_SCHEDULER_add_now (trigger_shutdown, NULL);
+    GNUNET_SCHEDULER_add_now (&trigger_shutdown, NULL);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
   sl = find_service (servicename);
   if (sl == NULL)
     {
-      signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IS_NOT_KNOWN);
+      signal_result (client,
+                    servicename,
+                    request_id,
+                    GNUNET_ARM_RESULT_IS_NOT_KNOWN);
       GNUNET_SERVER_receive_done (client, GNUNET_OK);
       return;
     }
@@ -911,14 +937,19 @@ handle_stop (void *cls,
   if (GNUNET_YES == in_shutdown)
     {
       /* shutdown in progress */
-      signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IN_SHUTDOWN);
+      signal_result (client,
+                    servicename,
+                    request_id,
+                    GNUNET_ARM_RESULT_IN_SHUTDOWN);
       GNUNET_SERVER_receive_done (client, GNUNET_OK);
       return;
     }
   if (NULL != sl->killing_client)
   {
     /* killing already in progress */
-    signal_result (client, servicename, request_id,
+    signal_result (client,
+                  servicename,
+                  request_id,
                   GNUNET_ARM_RESULT_IS_STOPPING_ALREADY);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
@@ -926,7 +957,9 @@ handle_stop (void *cls,
   if (NULL == sl->proc)
   {
     /* process is down */
-    signal_result (client, servicename, request_id,
+    signal_result (client,
+                  servicename,
+                  request_id,
                   GNUNET_ARM_RESULT_IS_STOPPED_ALREADY);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
@@ -934,7 +967,9 @@ handle_stop (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending kill signal to service `%s', waiting for process to die.\n",
              servicename);
-  broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
+  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, GNUNET_TERM_SIG))
@@ -1060,11 +1095,9 @@ list_count (struct ServiceList *running_head)
  * Task run for shutdown.
  *
  * @param cls closure, NULL if we need to self-restart
- * @param tc context
  */
 static void
-shutdown_task (void *cls,
-               const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls)
 {
   struct ServiceList *pos;
   struct ServiceList *nxt;
@@ -1084,7 +1117,8 @@ shutdown_task (void *cls,
     while (NULL != (sli = pos->listen_head))
       {
        GNUNET_CONTAINER_DLL_remove (pos->listen_head,
-                                    pos->listen_tail, sli);
+                                    pos->listen_tail,
+                                    sli);
        if (NULL != sli->accept_task)
          {
            GNUNET_SCHEDULER_cancel (sli->accept_task);
@@ -1101,7 +1135,7 @@ shutdown_task (void *cls,
   while (NULL != (pos = nxt))
   {
     nxt = pos->next;
-    if (pos->proc != NULL)
+    if (NULL != pos->proc)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                  "Stopping service `%s'\n",
@@ -1116,7 +1150,7 @@ shutdown_task (void *cls,
     }
   }
   /* finally, should all service processes be already gone, terminate for real */
-  if (running_head == NULL)
+  if (NULL == running_head)
     do_shutdown ();
   else
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1129,19 +1163,16 @@ shutdown_task (void *cls,
  * Task run whenever it is time to restart a child that died.
  *
  * @param cls closure, always NULL
- * @param tc context
  */
 static void
-delayed_restart_task (void *cls,
-                     const struct GNUNET_SCHEDULER_TaskContext *tc)
+delayed_restart_task (void *cls)
+
 {
   struct ServiceList *sl;
   struct GNUNET_TIME_Relative lowestRestartDelay;
   struct ServiceListeningInfo *sli;
 
   child_restart_task = NULL;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
   GNUNET_assert (GNUNET_NO == in_shutdown);
   lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
 
@@ -1172,7 +1203,8 @@ delayed_restart_task (void *cls,
            /* accept was actually paused, so start it again */
            sli->accept_task =
              GNUNET_SCHEDULER_add_read_net
-             (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket,
+             (GNUNET_TIME_UNIT_FOREVER_REL,
+              sli->listen_socket,
               &accept_connection, sli);
          }
       }
@@ -1204,11 +1236,9 @@ delayed_restart_task (void *cls,
  * process died).
  *
  * @param cls closure, NULL if we need to self-restart
- * @param tc context
  */
 static void
-maint_child_death (void *cls,
-                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+maint_child_death (void *cls)
 {
   struct ServiceList *pos;
   struct ServiceList *next;
@@ -1221,18 +1251,9 @@ maint_child_death (void *cls,
   unsigned long statusCode;
   const struct GNUNET_DISK_FileHandle *pr;
 
-  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
+  pr = GNUNET_DISK_pipe_handle (sigpipe,
+                               GNUNET_DISK_PIPE_END_READ);
   child_death_task = NULL;
-  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
-  {
-    /* shutdown scheduled us, ignore! */
-    child_death_task =
-      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      pr,
-                                      &maint_child_death,
-                                      NULL);
-    return;
-  }
   /* consume the signal */
   GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));
 
@@ -1381,14 +1402,13 @@ maint_child_death (void *cls,
       }
       else
       {
-        if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-          GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                      _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
-                      pos->name,
-                      statstr,
-                      statcode,
-                      GNUNET_STRINGS_relative_time_to_string (pos->backoff,
-                                                              GNUNET_YES));
+       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                   _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
+                   pos->name,
+                   statstr,
+                   statcode,
+                   GNUNET_STRINGS_relative_time_to_string (pos->backoff,
+                                                           GNUNET_YES));
         /* schedule restart */
         pos->restart_at = GNUNET_TIME_relative_to_absolute (pos->backoff);
         pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff);
@@ -1497,7 +1517,7 @@ setup_service (void *cls,
   if (( (GNUNET_OK !=
         GNUNET_CONFIGURATION_get_value_filename (cfg, section,
                                                   "CONFIG",
-                                                 &config)) &&
+                                                  &config)) &&
        (GNUNET_OK !=
         GNUNET_CONFIGURATION_get_value_filename (cfg,
                                                   "PATHS",
@@ -1523,8 +1543,12 @@ setup_service (void *cls,
 #if WINDOWS
   sl->pipe_control = GNUNET_YES;
 #else
-  if (GNUNET_CONFIGURATION_have_value (cfg, section, "PIPECONTROL"))
-    sl->pipe_control = GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "PIPECONTROL");
+  if (GNUNET_CONFIGURATION_have_value (cfg,
+                                       section,
+                                       "PIPECONTROL"))
+    sl->pipe_control = GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                                             section,
+                                                             "PIPECONTROL");
 #endif
   GNUNET_CONTAINER_DLL_insert (running_head,
                                running_tail,
@@ -1629,9 +1653,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
   cfg = c;
   server = serv;
   GNUNET_assert (NULL != serv);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                &shutdown_task,
-                               NULL);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                NULL);
   child_death_task =
     GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
                                    GNUNET_DISK_pipe_handle (sigpipe,
@@ -1655,21 +1678,29 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
   }
 #endif
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_PREFIX",
-                                            &prefix_command))
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "ARM",
+                                             "GLOBAL_PREFIX",
+                                             &prefix_command))
     prefix_command = GNUNET_strdup ("");
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_POSTFIX",
-                                            &final_option))
+      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_CONFIGURATION_get_value_yesno (cfg,
+                                            "ARM",
+                                            "USER_ONLY"))
   {
     GNUNET_break (GNUNET_YES == start_user);
     start_system = GNUNET_NO;
   }
   if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "SYSTEM_ONLY"))
+      GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                            "ARM",
+                                            "SYSTEM_ONLY"))
   {
     GNUNET_break (GNUNET_YES == start_system);
     start_user = GNUNET_NO;