fixed a crashing bug in silcd/serverconfig.c
authorGiovanni Giacobbi <johnny@silcnet.org>
Wed, 13 Feb 2002 22:30:18 +0000 (22:30 +0000)
committerGiovanni Giacobbi <johnny@silcnet.org>
Wed, 13 Feb 2002 22:30:18 +0000 (22:30 +0000)
now silc_config_register and silc_config_register_table return bool

apps/silcd/serverconfig.c
lib/silcutil/silcconfig.c
lib/silcutil/silcconfig.h

index 7cb2a9e5495c47d8ee8bb83e8c1d99464e442314..f34616bfa100a4a688e3039bc847a002aa484c95 100644 (file)
@@ -520,6 +520,7 @@ SILC_CONFIG_CALLBACK(fetch_client)
   silc_free(tmp->host);
   my_free_authdata(tmp->passphrase, tmp->publickey);
   silc_free(tmp);
+  config->tmp = NULL;
   return got_errno;
 }
 
@@ -584,6 +585,7 @@ SILC_CONFIG_CALLBACK(fetch_admin)
   silc_free(tmp->nick);
   my_free_authdata(tmp->passphrase, tmp->publickey);
   silc_free(tmp);
+  config->tmp = NULL;
   return got_errno;
 }
 
@@ -636,6 +638,7 @@ SILC_CONFIG_CALLBACK(fetch_deny)
   silc_free(tmp->host);
   silc_free(tmp->reason);
   silc_free(tmp);
+  config->tmp = NULL;
   return got_errno;
 }
 
@@ -704,6 +707,7 @@ SILC_CONFIG_CALLBACK(fetch_server)
   silc_free(tmp->version);
   my_free_authdata(tmp->passphrase, tmp->publickey);
   silc_free(tmp);
+  config->tmp = NULL;
   return got_errno;
 }
 
@@ -783,6 +787,7 @@ SILC_CONFIG_CALLBACK(fetch_router)
   silc_free(tmp->backup_replace_ip);
   my_free_authdata(tmp->passphrase, tmp->publickey);
   silc_free(tmp);
+  config->tmp = NULL;
   return got_errno;
 }
 
index 188ffa2b66a46e171b703db2a92162281b537d72..8731aa1dbd7b54c766b0640ddc5e029819e1e200 100644 (file)
@@ -72,7 +72,7 @@ static char *errorstrs[] = {
   "Expected data but not found",               /* SILC_CONFIG_EEXPECTED */
   "Expected '='",                              /* SILC_CONFIG_EEXPECTEDEQUAL */
   "Unexpected data",                           /* SILC_CONFIG_EUNEXPECTED */
-  "Missing needed fields",                     /* SILC_CONFIG_EMISSFIELDS */
+  "Missing mandatory fields",                  /* SILC_CONFIG_EMISSFIELDS */
   "Missing ';'",                               /* SILC_CONFIG_EMISSCOLON */
 };
 
@@ -377,9 +377,10 @@ static void silc_config_destroy(SilcConfigEntity ent)
   silc_free(ent);
 }
 
-/* Registers a new option in the specified entity */
+/* Registers a new option in the specified entity.
+ * Returns TRUE on success, FALSE if already registered. */
 
-void silc_config_register(SilcConfigEntity ent, const char *name,
+bool silc_config_register(SilcConfigEntity ent, const char *name,
                          SilcConfigType type, SilcConfigCallback cb,
                          const SilcConfigTable *subtable, void *context)
 {
@@ -387,17 +388,18 @@ void silc_config_register(SilcConfigEntity ent, const char *name,
   SILC_CONFIG_DEBUG(("Register new option=\"%s\" type=%u cb=0x%08x context=0x%08x",
                name, type, (uint32) cb, (uint32) context));
 
-  if (!ent || !name)
-    return;
   /* if we are registering a block, make sure there is a specified sub-table */
-  if ((type == SILC_CONFIG_ARG_BLOCK) && !subtable)
-    return;
-  /* refuse special tag */
+  if (!ent || !name || ((type == SILC_CONFIG_ARG_BLOCK) && !subtable))
+    return FALSE;
+
+  /* don't register a reserved tag */
   if (!strcasecmp(name, "include"))
-    return;
+    return FALSE;
+
+  /* check if an option was previously registered */
   if (silc_config_find_option(ent, name)) {
-    fprintf(stderr, "Internal Error: Option double registered\n");
-    abort();
+    SILC_LOG_DEBUG(("Error: Can't register \"%s\" twice.", name));
+    return FALSE;
   }
 
   /* allocate and append the new option */
@@ -408,6 +410,7 @@ void silc_config_register(SilcConfigEntity ent, const char *name,
   newopt->subtable = subtable;
   newopt->context = context;
 
+  /* append this option to the list */
   if (!ent->opts)
     ent->opts = newopt;
   else {
@@ -415,21 +418,25 @@ void silc_config_register(SilcConfigEntity ent, const char *name,
     for (tmp = ent->opts; tmp->next; tmp = tmp->next);
     tmp->next = newopt;
   }
+  return TRUE;
 }
 
 /* Register a new option table in the specified config entity */
 
-void silc_config_register_table(SilcConfigEntity ent,
+bool silc_config_register_table(SilcConfigEntity ent,
                                const SilcConfigTable table[], void *context)
 {
   int i;
-  if (!ent || !table) return;
+  if (!ent || !table)
+    return FALSE;
   SILC_CONFIG_DEBUG(("Registering table"));
-  /* FIXME: some potability checks needed */
+  /* XXX FIXME: some potability checks needed - really? */
   for (i = 0; table[i].name; i++) {
-    silc_config_register(ent, table[i].name, table[i].type,
-                        table[i].callback, table[i].subtable, context);
+    if (!silc_config_register(ent, table[i].name, table[i].type,
+                             table[i].callback, table[i].subtable, context))
+      return FALSE;
   }
+  return TRUE;
 }
 
 /* ... */
@@ -544,9 +551,14 @@ static int silc_config_main_internal(SilcConfigEntity ent)
 
       /* now call block clean-up callback (if any) */
       if (thisopt->cb) {
-       SILC_CONFIG_DEBUG(("Now calling clean-up callback (if any)"));
-       thisopt->cb(thisopt->type, thisopt->name, file->line,
-                   NULL, thisopt->context);
+       int ret;
+       SILC_CONFIG_DEBUG(("Now calling clean-up callback"));
+       ret = thisopt->cb(thisopt->type, thisopt->name, file->line, NULL,
+                         thisopt->context);
+       if (ret) {
+         SILC_CONFIG_DEBUG(("Callback refused the value [ret=%d]", ret));
+         return ret;
+       }
       }
       /* Do we want ';' to be mandatory after close brace? */
       if (*(*p)++ != ';')
index 87db1cf84fdaec31326dd283d39c1e159a740284..132657349acc5d0c3be6427875711db70da8d9e8 100644 (file)
@@ -104,7 +104,7 @@ enum {
   SILC_CONFIG_EEXPECTED,       /* Expected data but not found */
   SILC_CONFIG_EEXPECTEDEQUAL,  /* Expected '=' */
   SILC_CONFIG_EUNEXPECTED,     /* Unexpected data */
-  SILC_CONFIG_EMISSFIELDS,     /* Missing needed fields */
+  SILC_CONFIG_EMISSFIELDS,     /* Missing mandatory fields */
   SILC_CONFIG_EMISSCOLON,      /* Missing ';' */
 };
 /***/
@@ -383,7 +383,7 @@ char *silc_config_read_current_line(SilcConfigFile *file);
  *
  * SYNOPSIS
  *
- *    void silc_config_register(SilcConfigEntity ent, const char *name,
+ *    bool silc_config_register(SilcConfigEntity ent, const char *name,
  *                              SilcConfigType type, SilcConfigCallback cb,
  *                              const SilcConfigTable *subtable,
  *                              void *context);
@@ -394,14 +394,17 @@ char *silc_config_read_current_line(SilcConfigFile *file);
  *    will be called with the *val pointer pointing to an internally
  *    allocated storage of type described by `type'.
  *    If `type' is SILC_CONFIG_ARG_BLOCK, then `subtable' must be a valid
- *    pointer to a SilcConfigTable array specified the options in the
+ *    pointer to a SilcConfigTable array specifying the options in the
  *    sub-block.
+ *    If the option `name' was already registered in this sub-block or it
+ *    matches the reserved word "Include", then this function returns FALSE,
+ *    otherwise it returns TRUE.
  *
  * SEE ALSO
  *    silc_config_register_table
  *
  ***/
-void silc_config_register(SilcConfigEntity ent, const char *name,
+bool silc_config_register(SilcConfigEntity ent, const char *name,
                          SilcConfigType type, SilcConfigCallback cb,
                          const SilcConfigTable *subtable, void *context);
 
@@ -409,7 +412,7 @@ void silc_config_register(SilcConfigEntity ent, const char *name,
  *
  * SYNOPSIS
  *
- *    void silc_config_register_table(SilcConfigEntity ent,
+ *    bool silc_config_register_table(SilcConfigEntity ent,
  *                                    const SilcConfigTable table[],
  *                                    void *context);
  *
@@ -420,12 +423,16 @@ void silc_config_register(SilcConfigEntity ent, const char *name,
  *    all with the same context `context'.
  *    The `table' array must be terminated with an entry with the name field
  *    set to NULL.
+ *    If the table contains invalid data this function returns FALSE, otherwise
+ *    it returns TRUE.  If a calling to this function failed, you must destroy
+ *    and recreate the entity before retrying, as it's impossible to detect
+ *    the point at the function stopped the registering process.
  *
  * SEE ALSO
  *    SilcConfigTable
  *
  ***/
-void silc_config_register_table(SilcConfigEntity ent,
+bool silc_config_register_table(SilcConfigEntity ent,
                                const SilcConfigTable table[], void *context);
 
 /****f* silcutil/SilcConfigAPI/silc_config_main