]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/parse_conf.c
Fix header file includes.
[bacula/bacula] / bacula / src / lib / parse_conf.c
1 /*
2  *   Master Configuration routines.
3  *
4  *   This file contains the common parts of the Bacula
5  *   configuration routines.
6  *
7  *   Note, the configuration file parser consists of three parts
8  *
9  *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
10  *
11  *   2. The generic config  scanner in lib/parse_conf.c and
12  *      lib/parse_conf.h.
13  *      These files contain the parser code, some utility
14  *      routines, and the common store routines (name, int,
15  *      string, time, int64, size, ...).
16  *
17  *   3. The daemon specific file, which contains the Resource
18  *      definitions as well as any specific store routines
19  *      for the resource records.
20  *
21  *    N.B. This is a two pass parser, so if you malloc() a string
22  *         in a "store" routine, you must ensure to do it during
23  *         only one of the two passes, or to free it between.
24  *         Also, note that the resource record is malloced and
25  *         saved in save_resource() during pass 1.  Anything that
26  *         you want saved after pass two (e.g. resource pointers)
27  *         must explicitly be done in save_resource. Take a look
28  *         at the Job resource in src/dird/dird_conf.c to see how
29  *         it is done.
30  *
31  *     Kern Sibbald, January MM
32  *
33  *   Version $Id$
34  */
35 /*
36    Copyright (C) 2000-2006 Kern Sibbald
37
38    This program is free software; you can redistribute it and/or
39    modify it under the terms of the GNU General Public License
40    version 2 as amended with additional clauses defined in the
41    file LICENSE in the main source directory.
42
43    This program is distributed in the hope that it will be useful,
44    but WITHOUT ANY WARRANTY; without even the implied warranty of
45    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
46    the file LICENSE for additional details.
47
48  */
49
50
51 #include "bacula.h"
52
53 /* Each daemon has a slightly different set of
54  * resources, so it will define the following
55  * global values.
56  */
57 extern int r_first;
58 extern int r_last;
59 extern RES_TABLE resources[];
60 extern RES **res_head;
61
62 #if defined(_MSC_VER)
63 // work around visual studio name manling preventing external linkage since res_all
64 // is declared as a different type when instantiated.
65 extern "C" CURES res_all;
66 #else
67 extern  CURES res_all;
68 #endif
69 extern int res_all_size;
70
71 extern brwlock_t res_lock;            /* resource lock */
72
73
74 /* Forward referenced subroutines */
75 static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd);
76
77
78 /* Common Resource definitions */
79
80 /* Message resource directives
81  *  name         handler      value       code   flags  default_value
82  */
83 RES_ITEM msgs_items[] = {
84    {"name",        store_name,    ITEM(res_msgs.hdr.name),  0, 0, 0},
85    {"description", store_str,     ITEM(res_msgs.hdr.desc),  0, 0, 0},
86    {"mailcommand", store_str,     ITEM(res_msgs.mail_cmd),  0, 0, 0},
87    {"operatorcommand", store_str, ITEM(res_msgs.operator_cmd), 0, 0, 0},
88    {"syslog",      store_msgs, ITEM(res_msgs), MD_SYSLOG,   0, 0},
89    {"mail",        store_msgs, ITEM(res_msgs), MD_MAIL,     0, 0},
90    {"mailonerror", store_msgs, ITEM(res_msgs), MD_MAIL_ON_ERROR, 0, 0},
91    {"file",        store_msgs, ITEM(res_msgs), MD_FILE,     0, 0},
92    {"append",      store_msgs, ITEM(res_msgs), MD_APPEND,   0, 0},
93    {"stdout",      store_msgs, ITEM(res_msgs), MD_STDOUT,   0, 0},
94    {"stderr",      store_msgs, ITEM(res_msgs), MD_STDERR,   0, 0},
95    {"director",    store_msgs, ITEM(res_msgs), MD_DIRECTOR, 0, 0},
96    {"console",     store_msgs, ITEM(res_msgs), MD_CONSOLE,  0, 0},
97    {"operator",    store_msgs, ITEM(res_msgs), MD_OPERATOR, 0, 0},
98    {NULL,          NULL,       {0},       0, 0, 0}
99 };
100
101 struct s_mtypes {
102    const char *name;
103    int token;
104 };
105 /* Various message types */
106 static struct s_mtypes msg_types[] = {
107    {"debug",         M_DEBUG},
108    {"abort",         M_ABORT},
109    {"fatal",         M_FATAL},
110    {"error",         M_ERROR},
111    {"warning",       M_WARNING},
112    {"info",          M_INFO},
113    {"saved",         M_SAVED},
114    {"notsaved",      M_NOTSAVED},
115    {"skipped",       M_SKIPPED},
116    {"mount",         M_MOUNT},
117    {"terminate",     M_TERM},
118    {"restored",      M_RESTORED},
119    {"security",      M_SECURITY},
120    {"alert",         M_ALERT},
121    {"all",           M_MAX+1},
122    {NULL,            0}
123 };
124
125 /* Used for certain KeyWord tables */
126 struct s_kw {
127    const char *name;
128    int token;
129 };
130
131 /*
132  * Tape Label types permitted in Pool records 
133  *
134  *   tape label      label code = token
135  */
136 static s_kw tapelabels[] = {
137    {"bacula",        B_BACULA_LABEL},
138    {"ansi",          B_ANSI_LABEL},
139    {"ibm",           B_IBM_LABEL},
140    {NULL,            0}
141 };
142
143
144 /* Simply print a message */
145 static void prtmsg(void *sock, const char *fmt, ...)
146 {
147    va_list arg_ptr;
148
149    va_start(arg_ptr, fmt);
150    vfprintf(stdout, fmt, arg_ptr);
151    va_end(arg_ptr);
152 }
153
154 const char *res_to_str(int rcode)
155 {
156    if (rcode < r_first || rcode > r_last) {
157       return _("***UNKNOWN***");
158    } else {
159       return resources[rcode-r_first].name;
160    }
161 }
162
163
164 /*
165  * Initialize the static structure to zeros, then
166  *  apply all the default values.
167  */
168 void init_resource(int type, RES_ITEM *items, int pass)
169 {
170    int i;
171    int rindex = type - r_first;
172    static bool first = true;
173    int errstat;
174
175    if (first && (errstat=rwl_init(&res_lock)) != 0) {
176       Emsg1(M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
177             strerror(errstat));
178    }
179    first = false;
180
181    memset(&res_all, 0, res_all_size);
182    res_all.hdr.rcode = type;
183    res_all.hdr.refcnt = 1;
184
185    /* Set defaults in each item */
186    for (i=0; items[i].name; i++) {
187       Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name,
188             (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
189             items[i].default_value);
190       if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) {
191          if (items[i].handler == store_bit) {
192             *(int *)(items[i].value) |= items[i].code;
193          } else if (items[i].handler == store_bool) {
194             *(bool *)(items[i].value) = items[i].default_value;
195          } else if (items[i].handler == store_pint ||
196                     items[i].handler == store_int) {
197             *(int *)(items[i].value) = items[i].default_value;
198          } else if (items[i].handler == store_int64) {
199             *(int64_t *)(items[i].value) = items[i].default_value;
200          } else if (items[i].handler == store_size) {
201             *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
202          } else if (items[i].handler == store_time) {
203             *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
204          } else if (pass == 1 && items[i].handler == store_addresses) {
205             init_default_addresses((dlist**)items[i].value, items[i].default_value);
206          }
207       }
208       /* If this triggers, take a look at lib/parse_conf.h */
209       if (i >= MAX_RES_ITEMS) {
210          Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
211       }
212    }
213 }
214
215
216 /* Store Messages Destination information */
217 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
218 {
219    int token;
220    char *cmd;
221    POOLMEM *dest;
222    int dest_len;
223
224    Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
225    if (pass == 1) {
226       switch (item->code) {
227       case MD_STDOUT:
228       case MD_STDERR:
229       case MD_SYSLOG:              /* syslog */
230       case MD_CONSOLE:
231          scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
232          break;
233       case MD_OPERATOR:            /* send to operator */
234       case MD_DIRECTOR:            /* send to Director */
235       case MD_MAIL:                /* mail */
236       case MD_MAIL_ON_ERROR:       /* mail if Job errors */
237          if (item->code == MD_OPERATOR) {
238             cmd = res_all.res_msgs.operator_cmd;
239          } else {
240             cmd = res_all.res_msgs.mail_cmd;
241          }
242          dest = get_pool_memory(PM_MESSAGE);
243          dest[0] = 0;
244          dest_len = 0;
245          /* Pick up comma separated list of destinations */
246          for ( ;; ) {
247             token = lex_get_token(lc, T_NAME);   /* scan destination */
248             dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
249             if (dest[0] != 0) {
250                pm_strcat(dest, " ");  /* separate multiple destinations with space */
251                dest_len++;
252             }
253             pm_strcat(dest, lc->str);
254             dest_len += lc->str_len;
255             Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
256             token = lex_get_token(lc, T_SKIP_EOL);
257             if (token == T_COMMA) {
258                continue;           /* get another destination */
259             }
260             if (token != T_EQUALS) {
261                scan_err1(lc, _("expected an =, got: %s"), lc->str);
262             }
263             break;
264          }
265          Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
266          scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
267          free_pool_memory(dest);
268          Dmsg0(900, "done with dest codes\n");
269          break;
270       case MD_FILE:                /* file */
271       case MD_APPEND:              /* append */
272          dest = get_pool_memory(PM_MESSAGE);
273          /* Pick up a single destination */
274          token = lex_get_token(lc, T_NAME);   /* scan destination */
275          pm_strcpy(dest, lc->str);
276          dest_len = lc->str_len;
277          token = lex_get_token(lc, T_SKIP_EOL);
278          Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
279          if (token != T_EQUALS) {
280             scan_err1(lc, _("expected an =, got: %s"), lc->str);
281          }
282          scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
283          free_pool_memory(dest);
284          Dmsg0(900, "done with dest codes\n");
285          break;
286
287       default:
288          scan_err1(lc, _("Unknown item code: %d\n"), item->code);
289          break;
290       }
291    }
292    scan_to_eol(lc);
293    set_bit(index, res_all.hdr.item_present);
294    Dmsg0(900, "Done store_msgs\n");
295 }
296
297 /*
298  * Scan for message types and add them to the message
299  * destination. The basic job here is to connect message types
300  *  (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
301  *  destination (MAIL, FILE, OPERATOR, ...)
302  */
303 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
304 {
305    int i; 
306    bool found, is_not;
307    int msg_type = 0;
308    char *str;
309
310    for ( ;; ) {
311       lex_get_token(lc, T_NAME);            /* expect at least one type */
312       found = false;
313       if (lc->str[0] == '!') {
314          is_not = true;
315          str = &lc->str[1];
316       } else {
317          is_not = false;
318          str = &lc->str[0];
319       }
320       for (i=0; msg_types[i].name; i++) {
321          if (strcasecmp(str, msg_types[i].name) == 0) {
322             msg_type = msg_types[i].token;
323             found = true;
324             break;
325          }
326       }
327       if (!found) {
328          scan_err1(lc, _("message type: %s not found"), str);
329          /* NOT REACHED */
330       }
331
332       if (msg_type == M_MAX+1) {         /* all? */
333          for (i=1; i<=M_MAX; i++) {      /* yes set all types */
334             add_msg_dest(msg, dest_code, i, where, cmd);
335          }
336       } else if (is_not) {
337          rem_msg_dest(msg, dest_code, msg_type, where);
338       } else {
339          add_msg_dest(msg, dest_code, msg_type, where, cmd);
340       }
341       if (lc->ch != ',') {
342          break;
343       }
344       Dmsg0(900, "call lex_get_token() to eat comma\n");
345       lex_get_token(lc, T_ALL);          /* eat comma */
346    }
347    Dmsg0(900, "Done scan_types()\n");
348 }
349
350
351 /*
352  * This routine is ONLY for resource names
353  *  Store a name at specified address.
354  */
355 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
356 {
357    POOLMEM *msg = get_pool_memory(PM_EMSG);
358    lex_get_token(lc, T_NAME);
359    if (!is_name_valid(lc->str, &msg)) {
360       scan_err1(lc, "%s\n", msg);
361    }
362    free_pool_memory(msg);
363    /* Store the name both pass 1 and pass 2 */
364    if (*(item->value)) {
365       scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."),
366          *(item->value), lc->str);
367    }
368    *(item->value) = bstrdup(lc->str);
369    scan_to_eol(lc);
370    set_bit(index, res_all.hdr.item_present);
371 }
372
373
374 /*
375  * Store a name string at specified address
376  * A name string is limited to MAX_RES_NAME_LENGTH
377  */
378 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
379 {
380    lex_get_token(lc, T_NAME);
381    /* Store the name */
382    if (pass == 1) {
383       *(item->value) = bstrdup(lc->str);
384    }
385    scan_to_eol(lc);
386    set_bit(index, res_all.hdr.item_present);
387 }
388
389 /* Store a string at specified address */
390 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
391 {
392    lex_get_token(lc, T_STRING);
393    if (pass == 1) {
394       *(item->value) = bstrdup(lc->str);
395    }
396    scan_to_eol(lc);
397    set_bit(index, res_all.hdr.item_present);
398 }
399
400 /*
401  * Store a directory name at specified address. Note, we do
402  *   shell expansion except if the string begins with a vertical
403  *   bar (i.e. it will likely be passed to the shell later).
404  */
405 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
406 {
407    lex_get_token(lc, T_STRING);
408    if (pass == 1) {
409       if (lc->str[0] != '|') {
410          do_shell_expansion(lc->str, sizeof(lc->str));
411       }
412       *(item->value) = bstrdup(lc->str);
413    }
414    scan_to_eol(lc);
415    set_bit(index, res_all.hdr.item_present);
416 }
417
418
419 /* Store a password specified address in MD5 coding */
420 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
421 {
422    unsigned int i, j;
423    struct MD5Context md5c;
424    unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
425    char sig[100];
426
427
428    lex_get_token(lc, T_STRING);
429    if (pass == 1) {
430       MD5Init(&md5c);
431       MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
432       MD5Final(digest, &md5c);
433       for (i = j = 0; i < sizeof(digest); i++) {
434          sprintf(&sig[j], "%02x", digest[i]);
435          j += 2;
436       }
437       *(item->value) = bstrdup(sig);
438    }
439    scan_to_eol(lc);
440    set_bit(index, res_all.hdr.item_present);
441 }
442
443
444 /* Store a resource at specified address.
445  * If we are in pass 2, do a lookup of the
446  * resource.
447  */
448 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
449 {
450    RES *res;
451
452    lex_get_token(lc, T_NAME);
453    if (pass == 2) {
454       res = GetResWithName(item->code, lc->str);
455       if (res == NULL) {
456          scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
457             lc->str, lc->line_no, lc->line);
458       }
459       if (*(item->value)) {
460          scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
461             item->name, lc->line_no, lc->line);
462       }
463       *(item->value) = (char *)res;
464    }
465    scan_to_eol(lc);
466    set_bit(index, res_all.hdr.item_present);
467 }
468
469 /*
470  * Store a resource pointer in an alist. default_value indicates how many
471  *   times this routine can be called -- i.e. how many alists
472  *   there are.
473  * If we are in pass 2, do a lookup of the
474  *   resource.
475  */
476 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
477 {
478    RES *res;
479    int count = item->default_value;
480    int i = 0;
481    alist *list;
482
483    if (pass == 2) {
484       if (count == 0) {               /* always store in item->value */
485          i = 0;
486          if ((item->value)[i] == NULL) {
487             list = New(alist(10, not_owned_by_alist));
488          } else {
489             list = (alist *)(item->value)[i];
490          }
491       } else {
492          /* Find empty place to store this directive */
493          while ((item->value)[i] != NULL && i++ < count) { }
494          if (i >= count) {
495             scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
496                lc->str, count, lc->line_no, lc->line);
497          }
498          list = New(alist(10, not_owned_by_alist));
499       }
500
501       for (;;) {
502          lex_get_token(lc, T_NAME);   /* scan next item */
503          res = GetResWithName(item->code, lc->str);
504          if (res == NULL) {
505             scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
506                item->name, lc->line_no, lc->line);
507          }
508          Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n", 
509                res, list, list->size(), i, item->name);
510          list->append(res);
511          (item->value)[i] = (char *)list;
512          if (lc->ch != ',') {         /* if no other item follows */
513             break;                    /* get out */
514          }
515          lex_get_token(lc, T_ALL);    /* eat comma */
516       }
517    }
518    scan_to_eol(lc);
519    set_bit(index, res_all.hdr.item_present);
520 }
521
522
523 /*
524  * Store a string in an alist.
525  */
526 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
527 {
528    alist *list;
529
530    if (pass == 2) {
531       if (*(item->value) == NULL) {
532          list = New(alist(10, owned_by_alist));
533       } else {
534          list = (alist *)(*(item->value));    
535       }
536
537       lex_get_token(lc, T_STRING);   /* scan next item */
538       Dmsg4(900, "Append %s to alist %p size=%d %s\n", 
539          lc->str, list, list->size(), item->name);
540       list->append(bstrdup(lc->str));
541       *(item->value) = (char *)list;
542    }
543    scan_to_eol(lc);
544    set_bit(index, res_all.hdr.item_present);
545 }
546
547
548
549 /*
550  * Store default values for Resource from xxxDefs
551  * If we are in pass 2, do a lookup of the
552  * resource and store everything not explicitly set
553  * in main resource.
554  *
555  * Note, here item points to the main resource (e.g. Job, not
556  *  the jobdefs, which we look up).
557  */
558 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
559 {
560    RES *res;
561
562    lex_get_token(lc, T_NAME);
563    if (pass == 2) {
564      Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
565      res = GetResWithName(item->code, lc->str);
566      if (res == NULL) {
567         scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
568            lc->str, lc->line_no, lc->line);
569      }
570    }
571    scan_to_eol(lc);
572 }
573
574
575
576 /* Store an integer at specified address */
577 void store_int(LEX *lc, RES_ITEM *item, int index, int pass)
578 {
579    lex_get_token(lc, T_INT32);
580    *(int *)(item->value) = lc->int32_val;
581    scan_to_eol(lc);
582    set_bit(index, res_all.hdr.item_present);
583 }
584
585 /* Store a positive integer at specified address */
586 void store_pint(LEX *lc, RES_ITEM *item, int index, int pass)
587 {
588    lex_get_token(lc, T_PINT32);
589    *(int *)(item->value) = lc->pint32_val;
590    scan_to_eol(lc);
591    set_bit(index, res_all.hdr.item_present);
592 }
593
594
595 /* Store an 64 bit integer at specified address */
596 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
597 {
598    lex_get_token(lc, T_INT64);
599    *(int64_t *)(item->value) = lc->int64_val;
600    scan_to_eol(lc);
601    set_bit(index, res_all.hdr.item_present);
602 }
603
604 /* Store a size in bytes */
605 void store_size(LEX *lc, RES_ITEM *item, int index, int pass)
606 {
607    int token;
608    uint64_t uvalue;
609    char bsize[500];
610
611    Dmsg0(900, "Enter store_size\n");
612    token = lex_get_token(lc, T_SKIP_EOL);
613    errno = 0;
614    switch (token) {
615    case T_NUMBER:
616    case T_IDENTIFIER:
617    case T_UNQUOTED_STRING:
618       bstrncpy(bsize, lc->str, sizeof(bsize));  /* save first part */
619       /* if terminated by space, scan and get modifier */
620       while (lc->ch == ' ') {
621          token = lex_get_token(lc, T_ALL);
622          switch (token) {
623          case T_NUMBER:
624          case T_IDENTIFIER:
625          case T_UNQUOTED_STRING:
626             bstrncat(bsize, lc->str, sizeof(bsize));
627             break;
628          }
629       }
630       if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
631          scan_err1(lc, _("expected a size number, got: %s"), lc->str);
632       }
633       *(uint64_t *)(item->value) = uvalue;
634       break;
635    default:
636       scan_err1(lc, _("expected a size, got: %s"), lc->str);
637       break;
638    }
639    if (token != T_EOL) {
640       scan_to_eol(lc);
641    }
642    set_bit(index, res_all.hdr.item_present);
643    Dmsg0(900, "Leave store_size\n");
644 }
645
646
647 /* Store a time period in seconds */
648 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
649 {
650    int token;
651    utime_t utime;
652    char period[500];
653
654    token = lex_get_token(lc, T_SKIP_EOL);
655    errno = 0;
656    switch (token) {
657    case T_NUMBER:
658    case T_IDENTIFIER:
659    case T_UNQUOTED_STRING:
660       bstrncpy(period, lc->str, sizeof(period));  /* get first part */
661       /* if terminated by space, scan and get modifier */
662       while (lc->ch == ' ') {
663          token = lex_get_token(lc, T_ALL);
664          switch (token) {
665          case T_NUMBER:
666          case T_IDENTIFIER:
667          case T_UNQUOTED_STRING:
668             bstrncat(period, lc->str, sizeof(period));
669             break;
670          }
671       }
672       if (!duration_to_utime(period, &utime)) {
673          scan_err1(lc, _("expected a time period, got: %s"), period);
674       }
675       *(utime_t *)(item->value) = utime;
676       break;
677    default:
678       scan_err1(lc, _("expected a time period, got: %s"), lc->str);
679       break;
680    }
681    if (token != T_EOL) {
682       scan_to_eol(lc);
683    }
684    set_bit(index, res_all.hdr.item_present);
685 }
686
687
688 /* Store a yes/no in a bit field */
689 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
690 {
691    lex_get_token(lc, T_NAME);
692    if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
693       *(int *)(item->value) |= item->code;
694    } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
695       *(int *)(item->value) &= ~(item->code);
696    } else {
697       scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
698    }
699    scan_to_eol(lc);
700    set_bit(index, res_all.hdr.item_present);
701 }
702
703 /* Store a bool in a bit field */
704 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
705 {
706    lex_get_token(lc, T_NAME);
707    if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
708       *(bool *)(item->value) = true;
709    } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
710       *(bool *)(item->value) = false;
711    } else {
712       scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
713    }
714    scan_to_eol(lc);
715    set_bit(index, res_all.hdr.item_present);
716 }
717
718
719 /*
720  * Store Tape Label Type (Bacula, ANSI, IBM)
721  *
722  */
723 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
724 {
725    int token, i;
726
727    token = lex_get_token(lc, T_NAME);
728    /* Store the label pass 2 so that type is defined */
729    for (i=0; tapelabels[i].name; i++) {
730       if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
731          *(int *)(item->value) = tapelabels[i].token;
732          i = 0;
733          break;
734       }
735    }
736    if (i != 0) {
737       scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
738    }
739    scan_to_eol(lc);
740    set_bit(index, res_all.hdr.item_present);
741 }
742
743
744 /* Parser state */
745 enum parse_state {
746    p_none,
747    p_resource
748 };
749
750 /*********************************************************************
751  *
752  * Parse configuration file
753  *
754  * Return 0 if reading failed, 1 otherwise
755  *  Note, the default behavior unless you have set an alternate
756  *  scan_error handler is to die on an error.
757  */
758 int
759 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error, int err_type)
760 {
761    LEX *lc = NULL;
762    int token, i, pass;
763    int res_type = 0;
764    enum parse_state state = p_none;
765    RES_ITEM *items = NULL;
766    int level = 0;
767
768    /* Make two passes. The first builds the name symbol table,
769     * and the second picks up the items.
770     */
771    Dmsg0(900, "Enter parse_config()\n");
772    for (pass=1; pass <= 2; pass++) {
773       Dmsg1(900, "parse_config pass %d\n", pass);
774       if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
775          berrno be;
776          /* We must create a lex packet to print the error */
777          lc = (LEX *)malloc(sizeof(LEX));
778          memset(lc, 0, sizeof(LEX));
779          if (scan_error) {
780             lc->scan_error = scan_error;
781          } else {
782             lex_set_default_error_handler(lc);
783          }
784          lex_set_error_handler_error_type(lc, err_type) ;
785          bstrncpy(lc->str, cf, sizeof(lc->str));
786          lc->fname = lc->str;
787          scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
788             lc->str, be.strerror());
789          free(lc);
790          return 0;
791       }
792       lex_set_error_handler_error_type(lc, err_type) ;
793       while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
794          Dmsg1(900, "parse got token=%s\n", lex_tok_to_str(token));
795          switch (state) {
796          case p_none:
797             if (token == T_EOL) {
798                break;
799             }
800             if (token != T_IDENTIFIER) {
801                scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
802                return 0;
803             }
804             for (i=0; resources[i].name; i++)
805                if (strcasecmp(resources[i].name, lc->str) == 0) {
806                   state = p_resource;
807                   items = resources[i].items;
808                   res_type = resources[i].rcode;
809                   init_resource(res_type, items, pass);
810                   break;
811                }
812             if (state == p_none) {
813                scan_err1(lc, _("expected resource name, got: %s"), lc->str);
814           return 0;
815             }
816             break;
817          case p_resource:
818             switch (token) {
819             case T_BOB:
820                level++;
821                break;
822             case T_IDENTIFIER:
823                if (level != 1) {
824                   scan_err1(lc, _("not in resource definition: %s"), lc->str);
825                   return 0;
826                }
827                for (i=0; items[i].name; i++) {
828                   if (strcasecmp(items[i].name, lc->str) == 0) {
829                      /* If the ITEM_NO_EQUALS flag is set we do NOT
830                       *   scan for = after the keyword  */
831                      if (!(items[i].flags & ITEM_NO_EQUALS)) {
832                         token = lex_get_token(lc, T_SKIP_EOL);
833                         Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
834                         if (token != T_EQUALS) {
835                            scan_err1(lc, _("expected an equals, got: %s"), lc->str);
836                            return 0;
837                         }
838                      }
839                      Dmsg1(800, "calling handler for %s\n", items[i].name);
840                      /* Call item handler */
841                      items[i].handler(lc, &items[i], i, pass);
842                      i = -1;
843                      break;
844                   }
845                }
846                if (i >= 0) {
847                   Dmsg2(900, "level=%d id=%s\n", level, lc->str);
848                   Dmsg1(900, "Keyword = %s\n", lc->str);
849                   scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
850                      "Perhaps you left the trailing brace off of the previous resource."), lc->str);
851                   return 0;
852                }
853                break;
854
855             case T_EOB:
856                level--;
857                state = p_none;
858                Dmsg0(900, "T_EOB => define new resource\n");
859                if (res_all.hdr.name == NULL) {
860                   scan_err0(lc, _("Name not specified for resource"));
861                }
862                save_resource(res_type, items, pass);  /* save resource */
863                break;
864
865             case T_EOL:
866                break;
867
868             default:
869                scan_err2(lc, _("unexpected token %d %s in resource definition"),
870                   token, lex_tok_to_str(token));
871                return 0;
872             }
873             break;
874          default:
875             scan_err1(lc, _("Unknown parser state %d\n"), state);
876             return 0;
877          }
878       }
879       if (state != p_none) {
880          scan_err0(lc, _("End of conf file reached with unclosed resource."));
881          return 0;
882       }
883       if (debug_level >= 900 && pass == 2) {
884          int i;
885          for (i=r_first; i<=r_last; i++) {
886             dump_resource(i, res_head[i-r_first], prtmsg, NULL);
887          }
888       }
889       lc = lex_close_file(lc);
890    }
891    Dmsg0(900, "Leave parse_config()\n");
892    return 1;
893 }
894
895 /*********************************************************************
896  *
897  *      Free configuration resources
898  *
899  */
900 void free_config_resources()
901 {
902    for (int i=r_first; i<=r_last; i++) {
903       free_resource(res_head[i-r_first], i);
904       res_head[i-r_first] = NULL;
905    }
906 }
907
908 RES **save_config_resources()
909 {
910    int num = r_last - r_first + 1;
911    RES **res = (RES **)malloc(num*sizeof(RES *));
912    for (int i=0; i<num; i++) {
913       res[i] = res_head[i];
914       res_head[i] = NULL;
915    }
916    return res;
917 }
918
919 RES **new_res_head()
920 {
921    int size = (r_last - r_first + 1) * sizeof(RES *);
922    RES **res = (RES **)malloc(size);
923    memset(res, 0, size);
924    return res;
925 }