]> mj.ucw.cz Git - libucw.git/blob - lib/conf2.c
conf2: bugfixes in journaling
[libucw.git] / lib / conf2.c
1 /*
2  *      UCW Library -- Reading of configuration files
3  *
4  *      (c) 2001--2006 Robert Spalek <robert@ucw.cz>
5  *      (c) 2003--2006 Martin Mares <mj@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "lib/lib.h"
12 #include "lib/conf2.h"
13 #include "lib/mempool.h"
14 #include "lib/clists.h"
15 #include "lib/fastbuf.h"
16 #include "lib/chartype.h"
17 #include "lib/lfs.h"
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <stdarg.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25
26 #define TRY(f)  do { byte *_msg = f; if (_msg) return _msg; } while (0)
27
28 /* Memory allocation */
29
30 struct mempool *cf_pool;        // current pool for loading new configuration
31 static struct old_pools {
32   struct old_pools *prev;
33   struct mempool *pool;
34 } *pools;                       // link-list of older cf_pool's
35
36 void *
37 cf_malloc(uns size)
38 {
39   return mp_alloc(cf_pool, size);
40 }
41
42 void *
43 cf_malloc_zero(uns size)
44 {
45   return mp_alloc_zero(cf_pool, size);
46 }
47
48 byte *
49 cf_strdup(byte *s)
50 {
51   return mp_strdup(cf_pool, s);
52 }
53
54 byte *
55 cf_printf(char *fmt, ...)
56 {
57   va_list args;
58   va_start(args, fmt);
59   byte *res = mp_vprintf(cf_pool, fmt, args);
60   va_end(args);
61   return res;
62 }
63
64 /* Undo journal */
65
66 uns cf_need_journal = 1;        // some programs do not need journal
67 static struct journal_item {
68   struct journal_item *prev;
69   byte *ptr;
70   uns len;
71   byte copy[0];
72 } *journal;
73
74 void
75 cf_journal_block(void *ptr, uns len)
76 {
77   if (!cf_need_journal)
78     return;
79   struct journal_item *ji = cf_malloc(sizeof(struct journal_item) + len);
80   ji->prev = journal;
81   ji->ptr = ptr;
82   ji->len = len;
83   memcpy(ji->copy, ptr, len);
84   journal = ji;
85 }
86
87 static void
88 journal_swap(void)
89   // swaps the contents of the memory and the journal, and reverses the list
90 {
91   struct journal_item *curr, *prev, *next;
92   for (next=NULL, curr=journal; curr; next=curr, curr=prev)
93   {
94     prev = curr->prev;
95     curr->prev = next;
96     for (uns i=0; i<curr->len; i++)
97     {
98       byte x = curr->copy[i];
99       curr->copy[i] = curr->ptr[i];
100       curr->ptr[i] = x;
101     }
102   }
103   journal = next;
104 }
105
106 static struct journal_item *
107 journal_new_section(uns new_pool)
108 {
109   if (new_pool)
110     cf_pool = mp_new(1<<14);
111   struct journal_item *oldj = journal;
112   journal = NULL;
113   return oldj;
114 }
115
116 static void
117 journal_commit_section(uns new_pool, struct journal_item *oldj)
118 {
119   if (new_pool)
120   {
121     struct old_pools *p = cf_malloc(sizeof(struct old_pools));
122     p->prev = pools;
123     p->pool = cf_pool;
124     pools = p;
125   }
126   if (oldj)
127   {
128     struct journal_item **j = &journal;
129     while (*j)
130       j = &(*j)->prev;
131     *j = oldj;
132   }
133 }
134
135 static void
136 journal_rollback_section(uns new_pool, struct journal_item *oldj)
137 {
138   if (!cf_need_journal)
139     die("Cannot rollback the configuration, because the journal is disabled.");
140   journal_swap();
141   journal = oldj;
142   if (new_pool)
143   {
144     mp_delete(cf_pool);
145     cf_pool = pools ? pools->pool : NULL;
146   }
147 }
148
149 /* Initialization */
150
151 #define SEC_FLAG_DYNAMIC        0x80000000      // contains a dynamic attribute
152 #define SEC_FLAG_UNKNOWN        0x40000000      // ignore unknown entriies
153 #define SEC_FLAG_NUMBER         0x0fffffff      // number of entries
154
155 static struct cf_section sections;      // root section
156
157 static struct cf_item *
158 find_subitem(struct cf_section *sec, byte *name)
159 {
160   struct cf_item *ci = sec->cfg;
161   for (; ci->cls; ci++)
162     if (!strcasecmp(ci->name, name))
163       return ci;
164   return ci;
165 }
166
167 static void
168 inspect_section(struct cf_section *sec)
169 {
170   sec->flags = 0;
171   struct cf_item *ci;
172   for (ci=sec->cfg; ci->cls; ci++)
173     if (ci->cls == CC_SECTION) {
174       inspect_section(ci->u.sec);
175       sec->flags |= ci->u.sec->flags & SEC_FLAG_DYNAMIC;
176     } else if (ci->cls == CC_LIST) {
177       inspect_section(ci->u.sec);
178       sec->flags |= SEC_FLAG_DYNAMIC;
179     } else if (ci->cls == CC_DYNAMIC || ci->cls == CC_PARSER && ci->number < 0)
180       sec->flags |= SEC_FLAG_DYNAMIC;
181   sec->flags |= ci - sec->cfg;          // record the number of entries
182 }
183
184 void
185 cf_declare_section(byte *name, struct cf_section *sec, uns allow_unknown)
186 {
187   if (!sections.cfg)
188   {
189     sections.size = 50;
190     sections.cfg = xmalloc_zero(sections.size * sizeof(struct cf_item));
191   }
192   struct cf_item *ci = find_subitem(&sections, name);
193   if (ci->cls)
194     die("Cannot register section %s twice", name);
195   ci->cls = CC_SECTION;
196   ci->name = name;
197   ci->number = 1;
198   ci->ptr = NULL;
199   ci->u.sec = sec;
200   inspect_section(sec);
201   if (allow_unknown)
202     sec->flags |= SEC_FLAG_UNKNOWN;
203   ci++;
204   if (ci - sections.cfg >= (int) sections.size)
205   {
206     sections.cfg = xrealloc(sections.cfg, 2*sections.size * sizeof(struct cf_item));
207     bzero(sections.cfg + sections.size, sections.size * sizeof(struct cf_item));
208     sections.size *= 2;
209   }
210 }
211
212 void
213 cf_init_section(byte *name, struct cf_section *sec, void *ptr, uns do_bzero)
214 {
215   if (do_bzero) {
216     ASSERT(sec->size);
217     bzero(ptr, sec->size);
218   }
219   for (uns i=0; sec->cfg[i].cls; i++)
220     if (sec->cfg[i].cls == CC_SECTION)
221       cf_init_section(sec->cfg[i].name, sec->cfg[i].u.sec, ptr + (addr_int_t) sec->cfg[i].ptr, 0);
222     else if (sec->cfg[i].cls == CC_LIST)
223       clist_init(sec->cfg[i].ptr);
224   if (sec->init) {
225     byte *msg = sec->init(ptr);
226     if (msg)
227       die("Cannot initialize section %s: %s", name, msg);
228   }
229 }
230
231 static void
232 global_init(void)
233 {
234   static uns initialized = 0;
235   if (initialized++)
236     return;
237   sections.flags |= SEC_FLAG_UNKNOWN;
238   sections.size = 0;                    // size of allocated array used to be stored here
239   cf_init_section("top-level", &sections, NULL, 0);
240 }
241
242 static int
243 commit_section(byte *name, struct cf_section *sec, void *ptr)
244 {
245   struct cf_item *ci;
246   for (ci=sec->cfg; ci->cls; ci++)
247     if (ci->cls == CC_SECTION)
248       if (commit_section(ci->name, ci->u.sec, ptr + (addr_int_t) ci->ptr))
249         return 1;
250     else if (ci->cls == CC_LIST) {
251       struct cnode *n;
252       CLIST_WALK(n, * (clist*) (ptr + (addr_int_t) ci->ptr))
253         if (commit_section(ci->name, ci->u.sec, n))
254           return 1;
255     }
256   if (sec->commit) {
257     byte *msg = sec->commit(ptr);
258     if (msg) {
259       log(L_ERROR, "Cannot commit section %s: %s", name, msg);
260       return 1;
261     }
262   }
263   return 0;
264 }
265
266 static struct cf_item *
267 find_item(struct cf_section *curr_sec, byte *name, byte **msg, void **ptr)
268 {
269   *msg = NULL;
270   if (name[0] == '^')                           // absolute name instead of relative
271     name++, curr_sec = &sections, *ptr = NULL;
272   if (!curr_sec)                                // don't even search in an unknown section
273     return NULL;
274   while (1)
275   {
276     byte *c = strchr(name, '.');
277     if (c)
278       *c++ = 0;
279     struct cf_item *ci = find_subitem(curr_sec, name);
280     if (!ci->cls)
281     {
282       if (!(curr_sec->flags & SEC_FLAG_UNKNOWN))        // ignore silently unknown top-level sections and unknown attributes in flagged sections
283         *msg = cf_printf("Unknown item %s", name);
284       return NULL;
285     }
286     *ptr += (addr_int_t) ci->ptr;
287     if (!c)
288       return ci;
289     if (ci->cls != CC_SECTION)
290     {
291       *msg = cf_printf("Item %s is not a section", name);
292       return NULL;
293     }
294     curr_sec = ci->u.sec;
295     name = c;
296   }
297 }
298
299 byte *
300 cf_find_item(byte *name, struct cf_item *item)
301 {
302   byte *msg;
303   void *ptr;
304   struct cf_item *ci = find_item(&sections, name, &msg, &ptr);
305   if (msg)
306     return msg;
307   *item = *ci;
308   item->ptr = ptr;
309   return NULL;
310 }
311
312 /* Safe loading and reloading */
313
314 static int load_file(byte *file);
315 static int load_string(byte *string);
316
317 int
318 cf_reload(byte *file)
319 {
320   journal_swap();
321   struct journal_item *oldj = journal_new_section(1);
322   int err = load_file(file);
323   if (!err)
324   {
325     for (struct old_pools *p=pools; p; p=pools)
326     {
327       pools = p->prev;
328       mp_delete(p->pool);
329     }
330     journal_commit_section(1, NULL);
331   }
332   else
333   {
334     journal_rollback_section(1, oldj);
335     journal_swap();
336   }
337   return err;
338 }
339
340 int
341 cf_load(byte *file)
342 {
343   struct journal_item *oldj = journal_new_section(1);
344   int err = load_file(file);
345   if (!err)
346     journal_commit_section(1, oldj);
347   else
348     journal_rollback_section(1, oldj);
349   return err;
350 }
351
352 int
353 cf_set(byte *string)
354 {
355   struct journal_item *oldj = journal_new_section(0);
356   int err = load_string(string);
357   if (!err)
358     journal_commit_section(0, oldj);
359   else
360     journal_rollback_section(0, oldj);
361   return err;
362 }
363
364 /* Parsers for standard types */
365
366 struct unit {
367   uns name;                     // one-letter name of the unit
368   uns num, den;                 // fraction
369 };
370
371 static const struct unit units[] = {
372   { 'd', 86400, 1 },
373   { 'h', 3600, 1 },
374   { 'k', 1000, 1 },
375   { 'm', 1000000, 1 },
376   { 'g', 1000000000, 1 },
377   { 'K', 1024, 1 },
378   { 'M', 1048576, 1 },
379   { 'G', 1073741824, 1 },
380   { '%', 1, 100 },
381   { 0, 0, 0 }
382 };
383
384 static const struct unit *
385 lookup_unit(byte *value, byte *end, byte **msg)
386 {
387   if (end && *end) {
388     if (end == value || end[1] || *end >= '0' && *end <= '9')
389       *msg = "Invalid number";
390     else {
391       for (const struct unit *u=units; u->name; u++)
392         if (u->name == *end)
393           return u;
394       *msg = "Invalid unit";
395     }
396   }
397   return NULL;
398 }
399
400 static char cf_rngerr[] = "Number out of range";
401
402 byte *
403 cf_parse_int(byte *str, int *ptr)
404 {
405   byte *msg = NULL;
406   if (!*str)
407     msg = "Missing number";
408   else {
409     const struct unit *u;
410     char *end;
411     errno = 0;
412     uns x = strtoul(str, &end, 0);
413     if (errno == ERANGE)
414       msg = cf_rngerr;
415     else if (u = lookup_unit(str, end, &msg)) {
416       u64 y = (u64)x * u->num;
417       if (y % u->den)
418         msg = "Number is not an integer";
419       else {
420         y /= u->den;
421         if (y > 0xffffffff)
422           msg = cf_rngerr;
423         *ptr = y;
424       }
425     } else
426       *ptr = x;
427   }
428   return msg;
429 }
430
431 byte *
432 cf_parse_u64(byte *str, u64 *ptr)
433 {
434   byte *msg = NULL;
435   if (!*str)
436     msg = "Missing number";
437   else {
438     const struct unit *u;
439     char *end;
440     errno = 0;
441     u64 x = strtoull(str, &end, 0);
442     if (errno == ERANGE)
443       msg = cf_rngerr;
444     else if (u = lookup_unit(str, end, &msg)) {
445       if (x > ~(u64)0 / u->num)
446         msg = "Number out of range";
447       else {
448         x *= u->num;
449         if (x % u->den)
450           msg = "Number is not an integer";
451         else
452           *ptr = x / u->den;
453       }
454     } else
455       *ptr = x;
456   }
457   return msg;
458 }
459
460 byte *
461 cf_parse_double(byte *str, double *ptr)
462 {
463   byte *msg = NULL;
464   if (!*str)
465     msg = "Missing number";
466   else {
467     const struct unit *u;
468     double x;
469     uns read_chars;
470     if (sscanf(str, "%lf%n", &x, &read_chars) != 1)
471       msg = "Invalid number";
472     else if (u = lookup_unit(str, str + read_chars, &msg))
473       *ptr = x * u->num / u->den;
474     else
475       *ptr = x;
476   }
477   return msg;
478 }
479
480 byte *
481 cf_parse_ip(byte *p, u32 *varp)
482 {
483   if (!*p)
484     return "Missing IP address";
485   uns x = 0;
486   char *p2;
487   if (*p == '0' && p[1] | 32 == 'X') {
488     errno = 0;
489     x = strtoul(p + 2, &p2, 16);
490     if (errno == ERANGE || p2 == (char*) (p+2) || x > 0xffffffff)
491       goto error;
492     p = p2;
493   }
494   else
495     for (uns i = 0; i < 4; i++) {
496       if (i) {
497         if (*p++ != '.')
498           goto error;
499       }
500       errno = 0;
501       uns y = strtoul(p, &p2, 10);
502       if (errno == ERANGE || p2 == (char*) p || y > 255)
503         goto error;
504       p = p2;
505       x = (x << 8) + y;
506     }
507   *varp = x;
508   return *p ? "Trailing characters" : NULL;
509 error:
510   return "Invalid IP address";
511 }
512
513 static byte *
514 cf_parse_string(byte *str, byte **ptr)
515 {
516   *ptr = cf_strdup(str);
517   return NULL;
518 }
519
520 /* Register size of and parser for each basic type */
521
522 typedef byte *cf_basic_parser(byte *str, void *ptr);
523 static struct {
524   uns size;
525   void *parser;
526 } parsers[] = {
527   { sizeof(int), cf_parse_int },
528   { sizeof(u64), cf_parse_u64 },
529   { sizeof(double), cf_parse_double },
530   { sizeof(u32), cf_parse_ip },
531   { sizeof(byte*), cf_parse_string }
532 };
533
534 static byte *
535 cf_parse_ary(uns number, byte **pars, void *ptr, enum cf_type type)
536 {
537   for (uns i=0; i<number; i++)
538   {
539     byte *msg = ((cf_basic_parser*) parsers[type].parser) (pars[i], ptr + i * parsers[type].size);
540     if (msg)
541       return cf_printf("Cannot parse item %d: %s", i+1, msg);
542   }
543   return NULL;
544 }
545
546 /* Interpreter */
547
548 #define T(x) #x,
549 static byte *op_names[] = { CF_OPERATIONS };
550 #undef T
551
552 #define OP_MASK 0xff            // only get the operation
553 #define OP_OPEN 0x100           // here we only get an opening brace instead of parameters
554 #define OP_1ST 0x200            // in the 1st phase selectors are recorded into the mask
555 #define OP_2ND 0x400            // in the 2nd phase real data are entered
556
557 static byte *
558 interpret_set_dynamic(struct cf_item *item, int number, byte **pars, void **ptr)
559 {
560   enum cf_type type = item->u.type;
561   cf_journal_block(ptr, sizeof(void*));
562   // boundary checks done by the caller
563   *ptr = cf_malloc((number+1) * parsers[type].size) + parsers[type].size;
564   * (uns*) (*ptr - parsers[type].size) = number;
565   return cf_parse_ary(number, pars, *ptr, type);
566 }
567
568 static byte *
569 interpret_add_dynamic(struct cf_item *item, int number, byte **pars, int *processed, void **ptr, enum operation op)
570 {
571   enum cf_type type = item->u.type;
572   void *old_p = *ptr;
573   int old_nr = * (int*) (old_p - parsers[type].size);
574   int taken = MIN(number, item->number-old_nr);
575   *processed = taken;
576   // stretch the dynamic array
577   void *new_p = cf_malloc((old_nr + taken + 1) * parsers[type].size) + parsers[type].size;
578   * (uns*) (new_p - parsers[type].size) = old_nr + taken;
579   cf_journal_block(ptr, sizeof(void*));
580   *ptr = new_p;
581   if (op == OP_APPEND) {
582     memcpy(new_p, old_p, old_nr * parsers[type].size);
583     return cf_parse_ary(taken, pars, new_p + old_nr * parsers[type].size, type);
584   } else if (op == OP_PREPEND) {
585     memcpy(new_p + taken * parsers[type].size, old_p, old_nr * parsers[type].size);
586     return cf_parse_ary(taken, pars, new_p, type);
587   } else
588     return cf_printf("Dynamic arrays do not support operation %s", op_names[op]);
589 }
590
591 static byte *interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic);
592
593 static byte *
594 interpret_section(struct cf_section *sec, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
595 {
596   *processed = 0;
597   for (struct cf_item *ci=sec->cfg; ci->cls; ci++)
598   {
599     int taken;
600     byte *msg = interpret_set_item(ci, number, pars, &taken, ptr + (addr_int_t) ci->ptr, allow_dynamic && !ci[1].cls);
601     if (msg)
602       return cf_printf("Item %s: %s", ci->name, msg);
603     *processed += taken;
604     number -= taken;
605     pars += taken;
606     if (!number)                // stop parsing, because many parsers would otherwise complain that number==0
607       break;
608   }
609   return NULL;
610 }
611
612 static void
613 add_to_list(struct cnode *where, struct cnode *new_node, enum operation op)
614 {
615   switch (op)
616   {
617     case OP_EDIT:               // edition has been done in-place
618       break;
619     case OP_REMOVE:
620       cf_journal_block(&where->prev->next, sizeof(void*));
621       cf_journal_block(&where->next->prev, sizeof(void*));
622       clist_remove(where);
623       break;
624     case OP_AFTER:              // implementation dependend (prepend_head = after(list)), and where==list, see clists.h:74
625     case OP_PREPEND:
626       cf_journal_block(&where->next->prev, sizeof(void*));
627       cf_journal_block(&where->next, sizeof(void*));
628       clist_insert_after(new_node, where);
629       break;
630     case OP_BEFORE:             // implementation dependend (append_tail = before(list))
631     case OP_APPEND:
632     case OP_SET:
633       cf_journal_block(&where->prev->next, sizeof(void*));
634       cf_journal_block(&where->prev, sizeof(void*));
635       clist_insert_before(new_node, where);
636       break;
637     default:
638       ASSERT(0);
639   }
640 }
641
642 static byte *
643 interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, enum operation op)
644 {
645   if (op >= OP_REMOVE)
646     return cf_printf("You have to open a block for operation %s", op_names[op]);
647   if (!number)
648     return "Nothing to add to the list";
649   struct cf_section *sec = item->u.sec;
650   *processed = 0;
651   while (number > 0)
652   {
653     void *node = cf_malloc(sec->size);
654     cf_init_section(item->name, sec, node, 1);
655     add_to_list(ptr, node, op);
656     int taken;
657     /* If the node contains any dynamic attribute at the end, we suppress
658      * auto-repetition here and pass the flag inside instead.  */
659     TRY( interpret_section(sec, number, pars, &taken, node, sec->flags & SEC_FLAG_DYNAMIC) );
660     *processed += taken;
661     number -= taken;
662     pars += taken;
663     if (sec->flags & SEC_FLAG_DYNAMIC)
664       break;
665   }
666   return NULL;
667 }
668
669 static byte *
670 interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
671 {
672   int taken;
673   switch (item->cls)
674   {
675     case CC_STATIC:
676       if (!number)
677         return "Missing value";
678       taken = MIN(number, item->number);
679       *processed = taken;
680       cf_journal_block(ptr, taken * parsers[item->u.type].size);
681       return cf_parse_ary(taken, pars, ptr, item->u.type);
682     case CC_DYNAMIC:
683       if (!allow_dynamic)
684         return "Dynamic array cannot be used here";
685       taken = MIN(number, item->number);
686       *processed = taken;
687       return interpret_set_dynamic(item, taken, pars, ptr);
688     case CC_PARSER:
689       if (item->number < 0 && !allow_dynamic)
690         return "Parsers with variable number of parameters cannot be used here";
691       if (item->number > 0 && number < item->number)
692         return "Not enough parameters available for the parser";
693       taken = MIN(number, ABS(item->number));
694       *processed = taken;
695       for (int i=0; i<taken; i++)
696         pars[i] = cf_strdup(pars[i]);
697       return item->u.par(taken, pars, ptr);
698     case CC_SECTION:
699       return interpret_section(item->u.sec, number, pars, processed, ptr, allow_dynamic);
700     case CC_LIST:
701       if (!allow_dynamic)
702         return "Lists cannot be used here";
703       return interpret_add_list(item, number, pars, processed, ptr, OP_SET);
704     default:
705       ASSERT(0);
706   }
707 }
708
709 static byte *
710 interpret_clear(struct cf_item *item, void *ptr)
711 {
712   if (item->cls == CC_LIST) {
713     cf_journal_block(ptr, sizeof(struct clist));
714     clist_init(ptr);
715   } else if (item->cls == CC_DYNAMIC) {
716     cf_journal_block(ptr, sizeof(void *));
717     * (void**) ptr = NULL;
718   } else
719     return "The item is not a list or a dynamic array";
720   return NULL;
721 }
722
723 static int
724 cmp_items(void *i1, void *i2, struct cf_item *item)
725 {
726   ASSERT(item->cls == CC_STATIC);
727   i1 += (addr_int_t) item->ptr;
728   i2 += (addr_int_t) item->ptr;
729   if (item->u.type == CT_STRING)
730     return strcmp(* (byte**) i1, * (byte**) i2);
731   else                          // all numeric types
732     return memcmp(i1, i2, parsers[item->u.type].size);
733 }
734
735 static void *
736 find_list_node(struct clist *list, void *query, struct cf_section *sec, u32 mask)
737 {
738   struct cnode *n;
739   CLIST_WALK(n, *list)
740   {
741     uns found = 1;
742     for (uns i=0; i<32; i++)
743       if (mask & (1<<i))
744         if (cmp_items(n, query, sec->cfg+i))
745         {
746           found = 0;
747           break;
748         }
749     if (found)
750       return n;
751   }
752   return NULL;
753 }
754
755 static byte *
756 record_selector(struct cf_item *item, struct cf_section *sec, u32 *mask)
757 {
758   uns nr = sec->flags & SEC_FLAG_NUMBER;
759   if (item >= sec->cfg && item < sec->cfg + nr) // setting an attribute relative to this section
760   {
761     uns i = item - sec->cfg;
762     if (i >= 32)
763       return "Cannot select list nodes by this attribute";
764     if (sec->cfg[i].cls != CC_STATIC)
765       return "Selection can only be done based on basic attributes";
766     *mask |= 1 << i;
767   }
768   return NULL;
769 }
770
771 #define MAX_STACK_SIZE  100
772 static struct item_stack {
773   struct cf_section *sec;       // nested section
774   void *base_ptr;               // because original pointers are often relative
775   enum operation op;            // it is performed when a closing brace is encountered
776   void *list;                   // list the operations should be done on
777   u32 mask;                     // bit array of selectors searching in a list
778   struct cf_item *item;         // cf_item of the list
779 } stack[MAX_STACK_SIZE];
780 static uns level;
781
782 static byte *
783 opening_brace(struct cf_item *item, void *ptr, enum operation op)
784 {
785   if (level >= MAX_STACK_SIZE-1)
786     return "Too many nested sections";
787   stack[++level] = (struct item_stack) {
788     .sec = NULL,
789     .base_ptr = NULL,
790     .op = op & OP_MASK,
791     .list = NULL,
792     .mask = 0,
793     .item = NULL,
794   };
795   if (!item)                    // unknown is ignored; we just need to trace recursion
796     return NULL;
797   stack[level].sec = item->u.sec;
798   if (item->cls == CC_SECTION)
799   {
800     stack[level].base_ptr = ptr;
801     stack[level].op = OP_EDIT | OP_2ND; // this list operation does nothing
802   }
803   else if (item->cls == CC_LIST)
804   {
805     stack[level].base_ptr = cf_malloc(item->u.sec->size);
806     cf_init_section(item->name, item->u.sec, stack[level].base_ptr, 1);
807     stack[level].list = ptr;
808     stack[level].item = item;
809     stack[level].op |= (op & OP_MASK) < OP_REMOVE ? OP_2ND : OP_1ST;
810   }
811   else
812     return "Opening brace can only be used on sections and lists";
813   return NULL;
814 }
815
816 static byte *
817 closing_brace(struct item_stack *st, enum operation op, int number, byte **pars)
818 {
819   if (st->op == OP_CLOSE)       // top-level
820     return "Unmatched } parenthese";
821   if (!st->sec) {               // dummy run on unknown section
822     if (!(op & OP_OPEN))
823       level--;
824     return NULL;
825   }
826   enum operation pure_op = st->op & OP_MASK;
827   if (st->op & OP_1ST)
828   {
829     st->list = find_list_node(st->list, st->base_ptr, st->sec, st->mask);
830     if (!st->list)
831       return "Cannot find a node matching the query";
832     if (pure_op != OP_REMOVE)
833     {
834       if (pure_op == OP_EDIT)
835         st->base_ptr = st->list;
836       else if (pure_op == OP_AFTER || pure_op == OP_BEFORE)
837         cf_init_section(st->item->name, st->sec, st->base_ptr, 1);
838       else
839         ASSERT(0);
840       if (op & OP_OPEN) {       // stay at the same recursion level
841         st->op = (st->op | OP_2ND) & ~OP_1ST;
842         return NULL;
843       }
844       int taken;                // parse parameters on 1 line immediately
845       TRY( interpret_section(st->sec, number, pars, &taken, st->base_ptr, 1) );
846       number -= taken;
847       pars += taken;
848       // and fall-thru to the 2nd phase
849     }
850   }
851   add_to_list(st->list, st->base_ptr, pure_op);
852   level--;
853   if (number)
854     return "No parameters expected after the }";
855   else if (op & OP_OPEN)
856     return "No { is expected";
857   else
858     return NULL;
859 }
860
861 static byte *
862 interpret_line(byte *name, enum operation op, int number, byte **pars)
863 {
864   byte *msg;
865   if ((op & OP_MASK) == OP_CLOSE)
866     return closing_brace(stack+level, op, number, pars);
867   void *ptr = stack[level].base_ptr;
868   struct cf_item *item = find_item(stack[level].sec, name, &msg, &ptr);
869   if (msg)
870     return msg;
871   if (stack[level].op & OP_1ST)
872     TRY( record_selector(item, stack[level].sec, &stack[level].mask) );
873   if (op & OP_OPEN)             // the operation will be performed after the closing brace
874     return opening_brace(item, ptr, op);
875   if (!item)                    // ignored item in an unknown section
876     return NULL;
877   op &= OP_MASK;
878
879   int taken;                    // process as many parameters as possible
880   if (op == OP_CLEAR)
881     taken = 0, msg = interpret_clear(item, ptr);
882   else if (op == OP_SET)
883     msg = interpret_set_item(item, number, pars, &taken, ptr, 1);
884   else if (item->cls == CC_DYNAMIC)
885     msg = interpret_add_dynamic(item, number, pars, &taken, ptr, op);
886   else if (item->cls == CC_LIST)
887     msg = interpret_add_list(item, number, pars, &taken, ptr, op);
888   else
889     return cf_printf("Operation %s not supported on attribute class %d", op_names[op], item->cls);
890   if (msg)
891     return msg;
892   if (taken < number)
893     return cf_printf("Too many parameters: %d>%d", number, taken);
894
895   return NULL;
896 }
897
898 byte *
899 cf_write_item(struct cf_item *item, enum operation op, int number, byte **pars)
900 {
901   byte *msg;
902   int taken;
903   switch (op) {
904     case OP_SET:
905       msg = interpret_set_item(item, number, pars, &taken, item->ptr, 1);
906       break;
907     case OP_CLEAR:
908       taken = 0;
909       msg = interpret_clear(item, item->ptr);
910       break;
911     case OP_APPEND:
912     case OP_PREPEND:
913       if (item->cls == CC_DYNAMIC)
914         msg = interpret_add_dynamic(item, number, pars, &taken, item->ptr, op);
915       else if (item->cls == CC_LIST)
916         msg = interpret_add_list(item, number, pars, &taken, item->ptr, op);
917       else
918         return "The attribute class does not support append/prepend";
919       break;
920     default:
921       return "Unsupported operation";
922   }
923   if (msg)
924     return msg;
925   if (taken < number)
926     return "Too many parameters";
927   return NULL;
928 }
929
930 static void
931 init_stack(void)
932 {
933   global_init();
934   level = 0;
935   stack[0] = (struct item_stack) {
936     .sec = &sections,
937     .base_ptr = NULL,
938     .op = OP_CLOSE,
939     .list = NULL,
940     .mask = 0,
941     .item = NULL
942   };
943 }
944
945 static int
946 done_stack(void)
947 {
948   if (level > 0) {
949     log(L_ERROR, "Unterminated block");
950     return 1;
951   }
952   if (commit_section("top-level", &sections, NULL))
953     return 1;
954   return 0;
955 }
956
957 /* Text file parser */
958
959 static struct fastbuf *parse_fb;
960 static uns line_num;
961
962 #define MAX_LINE        4096
963 static byte line_buf[MAX_LINE];
964 static byte *line = line_buf;
965
966 #include "lib/bbuf.h"
967 static bb_t copy_buf;
968 static uns copied;
969
970 #define GBUF_TYPE       uns
971 #define GBUF_PREFIX(x)  split_##x
972 #include "lib/gbuf.h"
973 static split_t word_buf;
974 static uns words;
975 static uns ends_by_brace;               // the line is ended by "{"
976
977 static int
978 get_line(void)
979 {
980   if (!bgets(parse_fb, line_buf, MAX_LINE))
981     return 0;
982   line_num++;
983   line = line_buf;
984   while (Cblank(*line))
985     line++;
986   return 1;
987 }
988
989 static void
990 append(byte *start, byte *end)
991 {
992   uns len = end - start;
993   bb_grow(&copy_buf, copied + len + 1);
994   memcpy(copy_buf.ptr + copied, start, len);
995   copied += len + 1;
996   copy_buf.ptr[copied-1] = 0;
997 }
998
999 #define CONTROL_CHAR(x) (x == '{' || x == '}' || x == ';')
1000   // these characters separate words like blanks
1001
1002 static byte *
1003 get_word(uns is_command_name)
1004 {
1005   if (*line == '\'') {
1006     line++;
1007     while (1) {
1008       byte *start = line;
1009       while (*line && *line != '\'')
1010         line++;
1011       append(start, line);
1012       if (*line)
1013         break;
1014       copy_buf.ptr[copied-1] = '\n';
1015       if (!get_line())
1016         return "Unterminated apostrophe word at the end";
1017     }
1018     line++;
1019
1020   } else if (*line == '"') {
1021     line++;
1022     uns start_copy = copied;
1023     while (1) {
1024       byte *start = line;
1025       uns escape = 0;
1026       while (*line) {
1027         if (*line == '"' && !escape)
1028           break;
1029         else if (*line == '\\')
1030           escape ^= 1;
1031         else
1032           escape = 0;
1033         line++;
1034       }
1035       append(start, line);
1036       if (*line)
1037         break;
1038       if (!escape)
1039         copy_buf.ptr[copied-1] = '\n';
1040       else // merge two lines
1041         copied -= 2;
1042       if (!get_line())
1043         return "Unterminated quoted word at the end";
1044     }
1045     line++;
1046
1047     for (byte *c=copy_buf.ptr+start_copy; *c; c++)
1048       if (*c == '%') {
1049         if (c[1] != '%')
1050           return "Formating sequences are not allowed";
1051         else
1052           c++;
1053       }
1054     byte *tmp = cf_printf(copy_buf.ptr + start_copy);
1055     uns l = strlen(tmp);
1056     bb_grow(&copy_buf, start_copy + l + 1);
1057     strcpy(copy_buf.ptr + start_copy, tmp);
1058     copied = start_copy + l + 1;
1059
1060   } else {
1061     // promised that *line is non-null and non-blank
1062     byte *start = line;
1063     while (*line && !Cblank(*line) && !CONTROL_CHAR(*line)
1064         && (*line != '=' || !is_command_name))
1065       line++;
1066     if (*line == '=') {                         // nice for setting from a command-line
1067       if (line == start)
1068         return "Assignment without a variable";
1069       *line = ' ';
1070     }
1071     if (line == start)                          // already the first char is control
1072       line++;
1073     append(start, line);
1074   }
1075   while (Cblank(*line))
1076     line++;
1077   return NULL;
1078 }
1079
1080 static byte *
1081 get_token(uns is_command_name, byte **msg)
1082 {
1083   *msg = NULL;
1084   while (1) {
1085     if (!*line || *line == '#') {
1086       if (!is_command_name || !get_line())
1087         return NULL;
1088     } else if (*line == ';') {
1089       *msg = get_word(0);
1090       if (!is_command_name || *msg)
1091         return NULL;
1092     } else if (*line == '\\' && !line[1]) {
1093       if (!get_line()) {
1094         *msg = "Last line ends by a backslash";
1095         return NULL;
1096       }
1097       if (!*line || *line == '#')
1098         log(L_WARN, "The line following the backslash is empty");
1099     } else {
1100       split_grow(&word_buf, words+1);
1101       uns start = copied;
1102       word_buf.ptr[words++] = copied;
1103       *msg = get_word(is_command_name);
1104       return *msg ? NULL : copy_buf.ptr + start;
1105     }
1106   }
1107 }
1108
1109 static byte *
1110 split_command(void)
1111 {
1112   words = copied = ends_by_brace = 0;
1113   byte *msg, *start_word;
1114   if (!(start_word = get_token(1, &msg)))
1115     return msg;
1116   if (*start_word == '{')                       // only one opening brace
1117     return "Unexpected opening brace";
1118   while (*line != '}')                          // stays for the next time
1119   {
1120     if (!(start_word = get_token(0, &msg)))
1121       return msg;
1122     if (*start_word == '{') {
1123       words--;                                  // discard the brace
1124       ends_by_brace = 1;
1125       break;
1126     }
1127   }
1128   return NULL;
1129 }
1130
1131 /* Parsing multiple files */
1132
1133 static struct fastbuf *
1134 bopen_safe(byte *name)
1135 {
1136   int fd = sh_open(name, O_RDONLY);
1137   if (fd < 0) {
1138     log(L_ERROR, "Cannot open %s", name);
1139     return NULL;
1140   }
1141   return bopen(name, O_RDONLY, 1<<14);
1142 }
1143
1144 static byte *
1145 parse_fastbuf(byte *name_fb, struct fastbuf *fb, uns depth)
1146 {
1147   byte *msg;
1148   parse_fb = fb;
1149   line_num = 0;
1150   line = line_buf;
1151   *line = 0;
1152   while (1)
1153   {
1154     msg = split_command();
1155     if (msg)
1156       goto error;
1157     if (!words)
1158       return NULL;
1159     byte *name = copy_buf.ptr + word_buf.ptr[0];
1160     byte *pars[words-1];
1161     for (uns i=1; i<words; i++)
1162       pars[i-1] = copy_buf.ptr + word_buf.ptr[i];
1163     if (!strcasecmp(name, "include"))
1164     {
1165       if (words != 2) {
1166         msg = "Expecting one filename";
1167         goto error;
1168       }
1169       if (depth > 8) {
1170         msg = "Too many nested files";
1171         goto error;
1172       }
1173       struct fastbuf *new_fb = bopen_safe(pars[0]);
1174       if (!new_fb) {
1175         msg = "Cannot open file";
1176         goto error;
1177       }
1178       uns ll = line_num;
1179       msg = parse_fastbuf(pars[0], new_fb, depth+1);
1180       bclose(new_fb);
1181       if (msg)
1182         goto error;
1183       line_num = ll;
1184       parse_fb = fb;
1185     }
1186     enum operation op;
1187     byte *c = strchr(name, ':');
1188     if (!c)
1189       op = strcmp(name, "}") ? OP_SET : OP_CLOSE;
1190     else {
1191       *c++ = 0;
1192       switch (Clocase(*c)) {
1193         case 's': op = OP_SET; break;
1194         case 'c': op = OP_CLEAR; break;
1195         case 'a': op = Clocase(c[1]) == 'p' ? OP_APPEND : OP_AFTER; break;
1196         case 'p': op = OP_PREPEND; break;
1197         case 'r': op = OP_REMOVE; break;
1198         case 'e': op = OP_EDIT; break;
1199         case 'b': op = OP_BEFORE; break;
1200         default: op = OP_SET; break;
1201       }
1202       if (strcasecmp(c, op_names[op])) {
1203         msg = cf_printf("Unknown operation %s", c);
1204         goto error;
1205       }
1206     }
1207     if (ends_by_brace)
1208       op |= OP_OPEN;
1209     msg = interpret_line(name, op, words-1, pars);
1210     if (msg)
1211       goto error;
1212   }
1213 error:
1214   log(L_ERROR, "File %s, line %d: %s", name_fb, line_num, msg);
1215   return "included from here";
1216 }
1217
1218 #ifndef DEFAULT_CONFIG
1219 #define DEFAULT_CONFIG NULL
1220 #endif
1221 byte *cf_def_file = DEFAULT_CONFIG;
1222
1223 static int
1224 load_file(byte *file)
1225 {
1226   init_stack();
1227   struct fastbuf *fb = bopen_safe(file);
1228   if (!fb)
1229     return 1;
1230   byte *msg = parse_fastbuf(file, fb, 0);
1231   bclose(fb);
1232   int err = !!msg || done_stack();
1233   if (!err)
1234     cf_def_file = NULL;
1235   return err;
1236 }
1237
1238 static int
1239 load_string(byte *string)
1240 {
1241   init_stack();
1242   struct fastbuf fb;
1243   fbbuf_init_read(&fb, string, strlen(string), 0);
1244   byte *msg = parse_fastbuf("memory string", &fb, 0);
1245   return !!msg || done_stack();
1246 }
1247
1248 /* Command-line parser */
1249
1250 static void
1251 load_default(void)
1252 {
1253   if (cf_def_file)
1254     if (cf_load(cf_def_file))
1255       die("Cannot load default config %s", cf_def_file);
1256 }
1257
1258 int
1259 cf_get_opt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
1260 {
1261   static int other_options = 0;
1262   while (1) {
1263     int res = getopt_long (argc, argv, short_opts, long_opts, long_index);
1264     if (res == 'S' || res == 'C')
1265     {
1266       if (other_options)
1267         die("The -S and -C options must precede all other arguments");
1268       if (res == 'S') {
1269         load_default();
1270         if (cf_set(optarg))
1271           die("Cannot set %s", optarg);
1272       } else {
1273         if (cf_load(optarg))
1274           die("Cannot load %s", optarg);
1275       }
1276     } else {
1277       /* unhandled option or end of options */
1278       load_default();
1279       other_options++;
1280       return res;
1281     }
1282   }
1283 }
1284
1285 /* Debug dumping */
1286
1287 static void
1288 spaces(struct fastbuf *fb, uns nr)
1289 {
1290   for (uns i=0; i<nr; i++)
1291     bputs(fb, "  ");
1292 }
1293
1294 static void
1295 dump_basic(struct fastbuf *fb, void *ptr, enum cf_type type)
1296 {
1297   switch (type) {
1298     case CT_INT:        bprintf(fb, "%d ", *(uns*)ptr); break;
1299     case CT_U64:        bprintf(fb, "%llu ", *(u64*)ptr); break;
1300     case CT_DOUBLE:     bprintf(fb, "%lg ", *(double*)ptr); break;
1301     case CT_IP:         bprintf(fb, "%08x ", *(uns*)ptr); break;
1302     case CT_STRING:     bprintf(fb, "'%s' ", *(byte**)ptr); break;
1303   }
1304 }
1305
1306 static void dump_section(struct fastbuf *fb, struct cf_section *sec, int level, void *ptr);
1307
1308 static void
1309 dump_item(struct fastbuf *fb, struct cf_item *item, int level, void *ptr)
1310 {
1311   ptr += (addr_int_t) item->ptr;
1312   enum cf_type type = item->u.type;
1313   int i;
1314   spaces(fb, level);
1315   bprintf(fb, "%s: c%d #%d ", item->name, item->cls, item->number);
1316   if (item->cls == CC_STATIC || item->cls == CC_DYNAMIC)
1317     bprintf(fb, "t%d ", type);
1318   if (item->cls == CC_STATIC) {
1319     for (i=0; i<item->number; i++)
1320       dump_basic(fb, ptr + i * parsers[type].size, type);
1321   } else if (item->cls == CC_DYNAMIC) {
1322     ptr = * (void**) ptr;
1323     if (ptr) {
1324       int real_nr = * (int*) (ptr - parsers[type].size);
1325       bprintf(fb, "##%d ", real_nr);
1326       for (i=0; i<real_nr; i++)
1327         dump_basic(fb, ptr + i * parsers[type].size, type);
1328     } else
1329       bprintf(fb, "NULL ");
1330   }
1331   bputc(fb, '\n');
1332   if (item->cls == CC_SECTION)
1333     dump_section(fb, item->u.sec, level+1, ptr);
1334   else if (item->cls == CC_LIST) {
1335     uns idx = 0;
1336     struct cnode *n;
1337     CLIST_WALK(n, * (clist*) ptr) {
1338       spaces(fb, level+1);
1339       bprintf(fb, "item %d\n", ++idx);
1340       dump_section(fb, item->u.sec, level+2, n);
1341     }
1342   }
1343 }
1344
1345 static void
1346 dump_section(struct fastbuf *fb, struct cf_section *sec, int level, void *ptr)
1347 {
1348   spaces(fb, level);
1349   bprintf(fb, "S%d F%x:\n", sec->size, sec->flags);
1350   for (struct cf_item *item=sec->cfg; item->cls; item++)
1351     dump_item(fb, item, level, ptr);
1352 }
1353
1354 void
1355 cf_dump_sections(struct fastbuf *fb)
1356 {
1357   dump_section(fb, &sections, 0, NULL);
1358 }