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