]> mj.ucw.cz Git - libucw.git/blobdiff - ucw/conf-input.c
Resources: res_new() requires an active pool
[libucw.git] / ucw / conf-input.c
index 59468de6dad87480e49421d18b10de580f149586..fffc6d57e5cd5d8088755bb9c0730768c63cc421 100644 (file)
@@ -2,7 +2,7 @@
  *     UCW Library -- Configuration files: parsing input streams
  *
  *     (c) 2001--2006 Robert Spalek <robert@ucw.cz>
  *     UCW Library -- Configuration files: parsing input streams
  *
  *     (c) 2001--2006 Robert Spalek <robert@ucw.cz>
- *     (c) 2003--2006 Martin Mares <mj@ucw.cz>
+ *     (c) 2003--2009 Martin Mares <mj@ucw.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
@@ -12,6 +12,7 @@
 #include "ucw/conf.h"
 #include "ucw/getopt.h"
 #include "ucw/conf-internal.h"
 #include "ucw/conf.h"
 #include "ucw/getopt.h"
 #include "ucw/conf-internal.h"
+#include "ucw/clists.h"
 #include "ucw/mempool.h"
 #include "ucw/fastbuf.h"
 #include "ucw/chartype.h"
 #include "ucw/mempool.h"
 #include "ucw/fastbuf.h"
 #include "ucw/chartype.h"
@@ -222,7 +223,7 @@ parse_fastbuf(const char *name_fb, struct fastbuf *fb, uns depth)
       else if (depth > 8)
        err = "Too many nested files";
       else if (*line && *line != '#')          // because the contents of line_buf is not re-entrant and will be cleared
       else if (depth > 8)
        err = "Too many nested files";
       else if (*line && *line != '#')          // because the contents of line_buf is not re-entrant and will be cleared
-       err = "The input command must be the last one on a line";
+       err = "The include command must be the last one on a line";
       if (err)
        goto error;
       struct fastbuf *new_fb = bopen_try(pars[0], O_RDONLY, 1<<14);
       if (err)
        goto error;
       struct fastbuf *new_fb = bopen_try(pars[0], O_RDONLY, 1<<14);
@@ -254,7 +255,7 @@ parse_fastbuf(const char *name_fb, struct fastbuf *fb, uns depth)
                    default: op = OP_ALL;
                  }; break;
        case 'p': op = OP_PREPEND; break;
                    default: op = OP_ALL;
                  }; break;
        case 'p': op = OP_PREPEND; break;
-       case 'r': op = OP_REMOVE; break;
+       case 'r': op = (c[1] && Clocase(c[2]) == 'm') ? OP_REMOVE : OP_RESET; break;
        case 'e': op = OP_EDIT; break;
        case 'b': op = OP_BEFORE; break;
        default: op = OP_SET; break;
        case 'e': op = OP_EDIT; break;
        case 'b': op = OP_BEFORE; break;
        default: op = OP_SET; break;
@@ -284,6 +285,7 @@ error:
 #define DEFAULT_CONFIG NULL
 #endif
 char *cf_def_file = DEFAULT_CONFIG;
 #define DEFAULT_CONFIG NULL
 #endif
 char *cf_def_file = DEFAULT_CONFIG;
+static int cf_def_loaded;
 
 #ifndef ENV_VAR_CONFIG
 #define ENV_VAR_CONFIG NULL
 
 #ifndef ENV_VAR_CONFIG
 #define ENV_VAR_CONFIG NULL
@@ -316,10 +318,7 @@ load_file(const char *file)
   }
   char *err_msg = parse_fastbuf(file, fb, 0);
   bclose(fb);
   }
   char *err_msg = parse_fastbuf(file, fb, 0);
   bclose(fb);
-  int err = !!err_msg || done_stack();
-  if (!err)
-    cf_def_file = NULL;
-  return err;
+  return !!err_msg || done_stack();
 }
 
 static int
 }
 
 static int
@@ -334,6 +333,30 @@ load_string(const char *string)
 
 /* Safe loading and reloading */
 
 
 /* Safe loading and reloading */
 
+struct conf_entry {    /* We remember a list of actions to apply upon reload */
+  cnode n;
+  enum {
+    CE_FILE = 1,
+    CE_STRING = 2,
+  } type;
+  char *arg;
+};
+
+static clist conf_entries;
+
+static void
+cf_remember_entry(uns type, const char *arg)
+{
+  if (!cf_need_journal)
+    return;
+  if (!postpone_commit)
+    return;
+  struct conf_entry *ce = cf_malloc(sizeof(*ce));
+  ce->type = type;
+  ce->arg = cf_strdup(arg);
+  clist_add_tail(&conf_entries, &ce->n);
+}
+
 int
 cf_reload(const char *file)
 {
 int
 cf_reload(const char *file)
 {
@@ -341,17 +364,39 @@ cf_reload(const char *file)
   struct cf_journal_item *oldj = cf_journal_new_transaction(1);
   uns ec = everything_committed;
   everything_committed = 0;
   struct cf_journal_item *oldj = cf_journal_new_transaction(1);
   uns ec = everything_committed;
   everything_committed = 0;
-  int err = load_file(file);
+
+  if (!conf_entries.head.next)
+    clist_init(&conf_entries);
+  clist old_entries;
+  clist_move(&old_entries, &conf_entries);
+  postpone_commit = 1;
+
+  int err = 0;
+  if (file)
+    err = load_file(file);
+  else
+    CLIST_FOR_EACH(struct conf_entry *, ce, old_entries) {
+      if (ce->type == CE_FILE)
+       err |= load_file(ce->arg);
+      else
+       err |= load_string(ce->arg);
+      if (err)
+       break;
+      cf_remember_entry(ce->type, ce->arg);
+    }
+
+  postpone_commit = 0;
   if (!err)
   if (!err)
-  {
+    err |= done_stack();
+
+  if (!err) {
     cf_journal_delete();
     cf_journal_commit_transaction(1, NULL);
     cf_journal_delete();
     cf_journal_commit_transaction(1, NULL);
-  }
-  else
-  {
+  } else {
     everything_committed = ec;
     cf_journal_rollback_transaction(1, oldj);
     cf_journal_swap();
     everything_committed = ec;
     cf_journal_rollback_transaction(1, oldj);
     cf_journal_swap();
+    clist_move(&conf_entries, &old_entries);
   }
   return err;
 }
   }
   return err;
 }
@@ -361,9 +406,11 @@ cf_load(const char *file)
 {
   struct cf_journal_item *oldj = cf_journal_new_transaction(1);
   int err = load_file(file);
 {
   struct cf_journal_item *oldj = cf_journal_new_transaction(1);
   int err = load_file(file);
-  if (!err)
+  if (!err) {
     cf_journal_commit_transaction(1, oldj);
     cf_journal_commit_transaction(1, oldj);
-  else
+    cf_remember_entry(CE_FILE, file);
+    cf_def_loaded = 1;
+  } else
     cf_journal_rollback_transaction(1, oldj);
   return err;
 }
     cf_journal_rollback_transaction(1, oldj);
   return err;
 }
@@ -373,9 +420,10 @@ cf_set(const char *string)
 {
   struct cf_journal_item *oldj = cf_journal_new_transaction(0);
   int err = load_string(string);
 {
   struct cf_journal_item *oldj = cf_journal_new_transaction(0);
   int err = load_string(string);
-  if (!err)
+  if (!err) {
     cf_journal_commit_transaction(0, oldj);
     cf_journal_commit_transaction(0, oldj);
-  else
+    cf_remember_entry(CE_STRING, string);
+  } else
     cf_journal_rollback_transaction(0, oldj);
   return err;
 }
     cf_journal_rollback_transaction(0, oldj);
   return err;
 }
@@ -385,6 +433,8 @@ cf_set(const char *string)
 static void
 load_default(void)
 {
 static void
 load_default(void)
 {
+  if (cf_def_loaded++)
+    return;
   if (cf_def_file)
     {
       char *env;
   if (cf_def_file)
     {
       char *env;
@@ -398,8 +448,11 @@ load_default(void)
     }
   else
     {
     }
   else
     {
-      // We need to create an empty pool
-      cf_journal_commit_transaction(1, cf_journal_new_transaction(1));
+      // We need to create an empty pool and initialize all configuration items
+      struct cf_journal_item *oldj = cf_journal_new_transaction(1);
+      cf_init_stack();
+      done_stack();
+      cf_journal_commit_transaction(1, oldj);
     }
 }
 
     }
 }
 
@@ -416,6 +469,9 @@ final_commit(void)
 int
 cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
 {
 int
 cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
 {
+  clist_init(&conf_entries);
+  postpone_commit = 1;
+
   static int other_options = 0;
   while (1) {
     int res = getopt_long (argc, argv, short_opts, long_opts, long_index);
   static int other_options = 0;
   while (1) {
     int res = getopt_long (argc, argv, short_opts, long_opts, long_index);
@@ -424,12 +480,10 @@ cf_getopt(int argc, char * const argv[], const char *short_opts, const struct op
       if (other_options)
        die("The -S and -C options must precede all other arguments");
       if (res == 'S') {
       if (other_options)
        die("The -S and -C options must precede all other arguments");
       if (res == 'S') {
-       postpone_commit = 1;
        load_default();
        if (cf_set(optarg))
          die("Cannot set %s", optarg);
       } else if (res == 'C') {
        load_default();
        if (cf_set(optarg))
          die("Cannot set %s", optarg);
       } else if (res == 'C') {
-       postpone_commit = 1;
        if (cf_load(optarg))
          die("Cannot load config file %s", optarg);
       }
        if (cf_load(optarg))
          die("Cannot load config file %s", optarg);
       }
@@ -445,12 +499,12 @@ cf_getopt(int argc, char * const argv[], const char *short_opts, const struct op
 #endif
     } else {
       /* unhandled option or end of options */
 #endif
     } else {
       /* unhandled option or end of options */
-      if (res != ':' && res != '?')
+      if (res != ':' && res != '?') {
        load_default();
        load_default();
-      final_commit();
+       final_commit();
+      }
       other_options++;
       return res;
     }
   }
 }
       other_options++;
       return res;
     }
   }
 }
-