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