]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/parse_conf.c
04Jul05
[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-2005 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 ammended 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 struct 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_yesno) {
195             *(int *)(items[i].value) |= items[i].code;
196          } else if (items[i].handler == store_pint ||
197                     items[i].handler == store_int) {
198             *(int *)(items[i].value) = items[i].default_value;
199          } else if (items[i].handler == store_int64) {
200             *(int64_t *)(items[i].value) = items[i].default_value;
201          } else if (items[i].handler == store_size) {
202             *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
203          } else if (items[i].handler == store_time) {
204             *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
205          } else if (pass == 1 && items[i].handler == store_addresses) {
206             init_default_addresses((dlist**)items[i].value, items[i].default_value);
207          }
208       }
209       /* If this triggers, take a look at lib/parse_conf.h */
210       if (i >= MAX_RES_ITEMS) {
211          Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
212       }
213    }
214 }
215
216
217 /* Store Messages Destination information */
218 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
219 {
220    int token;
221    char *cmd;
222    POOLMEM *dest;
223    int dest_len;
224
225    Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
226    if (pass == 1) {
227       switch (item->code) {
228       case MD_STDOUT:
229       case MD_STDERR:
230       case MD_SYSLOG:              /* syslog */
231       case MD_CONSOLE:
232          scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
233          break;
234       case MD_OPERATOR:            /* send to operator */
235       case MD_DIRECTOR:            /* send to Director */
236       case MD_MAIL:                /* mail */
237       case MD_MAIL_ON_ERROR:       /* mail if Job errors */
238          if (item->code == MD_OPERATOR) {
239             cmd = res_all.res_msgs.operator_cmd;
240          } else {
241             cmd = res_all.res_msgs.mail_cmd;
242          }
243          dest = get_pool_memory(PM_MESSAGE);
244          dest[0] = 0;
245          dest_len = 0;
246          /* Pick up comma separated list of destinations */
247          for ( ;; ) {
248             token = lex_get_token(lc, T_NAME);   /* scan destination */
249             dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
250             if (dest[0] != 0) {
251                pm_strcat(dest, " ");  /* separate multiple destinations with space */
252                dest_len++;
253             }
254             pm_strcat(dest, lc->str);
255             dest_len += lc->str_len;
256             Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
257             token = lex_get_token(lc, T_SKIP_EOL);
258             if (token == T_COMMA) {
259                continue;           /* get another destination */
260             }
261             if (token != T_EQUALS) {
262                scan_err1(lc, _("expected an =, got: %s"), lc->str);
263             }
264             break;
265          }
266          Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
267          scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
268          free_pool_memory(dest);
269          Dmsg0(900, "done with dest codes\n");
270          break;
271       case MD_FILE:                /* file */
272       case MD_APPEND:              /* append */
273          dest = get_pool_memory(PM_MESSAGE);
274          /* Pick up a single destination */
275          token = lex_get_token(lc, T_NAME);   /* scan destination */
276          pm_strcpy(dest, lc->str);
277          dest_len = lc->str_len;
278          token = lex_get_token(lc, T_SKIP_EOL);
279          Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
280          if (token != T_EQUALS) {
281             scan_err1(lc, _("expected an =, got: %s"), lc->str);
282          }
283          scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
284          free_pool_memory(dest);
285          Dmsg0(900, "done with dest codes\n");
286          break;
287
288       default:
289          scan_err1(lc, _("Unknown item code: %d\n"), item->code);
290          break;
291       }
292    }
293    scan_to_eol(lc);
294    set_bit(index, res_all.hdr.item_present);
295    Dmsg0(900, "Done store_msgs\n");
296 }
297
298 /*
299  * Scan for message types and add them to the message
300  * destination. The basic job here is to connect message types
301  *  (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
302  *  destination (MAIL, FILE, OPERATOR, ...)
303  */
304 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
305 {
306    int i, found, quit, is_not;
307    int msg_type = 0;
308    char *str;
309
310    for (quit=0; !quit;) {
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 {
337          if (is_not) {
338             rem_msg_dest(msg, dest_code, msg_type, where);
339          } else {
340             add_msg_dest(msg, dest_code, msg_type, where, cmd);
341          }
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 signature[16];
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(signature, &md5c);
435       for (i = j = 0; i < sizeof(signature); i++) {
436          sprintf(&sig[j], "%02x", signature[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       if (lc->ch == ' ') {
623          token = lex_get_token(lc, T_ALL);
624          switch (token) {
625          case T_IDENTIFIER:
626          case T_UNQUOTED_STRING:
627             bstrncat(bsize, lc->str, sizeof(bsize));
628             break;
629          }
630       }
631       if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
632          scan_err1(lc, _("expected a size number, got: %s"), lc->str);
633       }
634       *(uint64_t *)(item->value) = uvalue;
635       break;
636    default:
637       scan_err1(lc, _("expected a size, got: %s"), lc->str);
638       break;
639    }
640    if (token != T_EOL) {
641       scan_to_eol(lc);
642    }
643    set_bit(index, res_all.hdr.item_present);
644    Dmsg0(900, "Leave store_size\n");
645 }
646
647
648 /* Store a time period in seconds */
649 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
650 {
651    int token;
652    utime_t utime;
653    char period[500];
654
655    token = lex_get_token(lc, T_SKIP_EOL);
656    errno = 0;
657    switch (token) {
658    case T_NUMBER:
659    case T_IDENTIFIER:
660    case T_UNQUOTED_STRING:
661       bstrncpy(period, lc->str, sizeof(period));  /* get first part */
662       /* if terminated by space, scan and get modifier */
663       if (lc->ch == ' ') {
664          token = lex_get_token(lc, T_ALL);
665          switch (token) {
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_yesno(LEX *lc, RES_ITEM *item, int index, int pass)
690 {
691    lex_get_token(lc, T_NAME);
692    if (strcasecmp(lc->str, "yes") == 0) {
693       *(int *)(item->value) |= item->code;
694    } else if (strcasecmp(lc->str, "no") == 0) {
695       *(int *)(item->value) &= ~(item->code);
696    } else {
697       scan_err1(lc, _("Expect a YES or NO, got: %s"), lc->str);
698    }
699    scan_to_eol(lc);
700    set_bit(index, res_all.hdr.item_present);
701 }
702
703 /*
704  * Store Tape Label Type (Bacula, ANSI, IBM)
705  *
706  */
707 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
708 {
709    int token, i;
710
711    token = lex_get_token(lc, T_NAME);
712    /* Store the label pass 2 so that type is defined */
713    for (i=0; tapelabels[i].name; i++) {
714       if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
715          *(int *)(item->value) = tapelabels[i].token;
716          i = 0;
717          break;
718       }
719    }
720    if (i != 0) {
721       scan_err1(lc, "Expected a Tape Label keyword, got: %s", lc->str);
722    }
723    scan_to_eol(lc);
724    set_bit(index, res_all.hdr.item_present);
725 }
726
727
728 /* Parser state */
729 enum parse_state {
730    p_none,
731    p_resource
732 };
733
734 /*********************************************************************
735  *
736  * Parse configuration file
737  *
738  * Return 0 if reading failed, 1 otherwise
739  *  Note, the default behavior unless you have set an alternate
740  *  scan_error handler is to die on an error.
741  */
742 int
743 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error)
744 {
745    LEX *lc = NULL;
746    int token, i, pass;
747    int res_type = 0;
748    enum parse_state state = p_none;
749    RES_ITEM *items = NULL;
750    int level = 0;
751
752    /* Make two passes. The first builds the name symbol table,
753     * and the second picks up the items.
754     */
755    Dmsg0(900, "Enter parse_config()\n");
756    for (pass=1; pass <= 2; pass++) {
757       Dmsg1(900, "parse_config pass %d\n", pass);
758       if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
759          berrno be;
760          /* We must create a lex packet to print the error */
761          lc = (LEX *)malloc(sizeof(LEX));
762          memset(lc, 0, sizeof(LEX));
763          if (scan_error) {
764             lc->scan_error = scan_error;
765          } else {
766             lex_set_default_error_handler(lc);
767          }
768          bstrncpy(lc->str, cf, sizeof(lc->str));
769          lc->fname = lc->str;
770          scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
771             lc->str, be.strerror());
772          free(lc);
773          return 0;
774       }
775       while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
776          Dmsg1(900, "parse got token=%s\n", lex_tok_to_str(token));
777          switch (state) {
778          case p_none:
779             if (token == T_EOL) {
780                break;
781             }
782             if (token != T_IDENTIFIER) {
783                scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
784                return 0;
785             }
786             for (i=0; resources[i].name; i++)
787                if (strcasecmp(resources[i].name, lc->str) == 0) {
788                   state = p_resource;
789                   items = resources[i].items;
790                   res_type = resources[i].rcode;
791                   init_resource(res_type, items, pass);
792                   break;
793                }
794             if (state == p_none) {
795                scan_err1(lc, _("expected resource name, got: %s"), lc->str);
796           return 0;
797             }
798             break;
799          case p_resource:
800             switch (token) {
801             case T_BOB:
802                level++;
803                break;
804             case T_IDENTIFIER:
805                if (level != 1) {
806                   scan_err1(lc, _("not in resource definition: %s"), lc->str);
807                   return 0;
808                }
809                for (i=0; items[i].name; i++) {
810                   if (strcasecmp(items[i].name, lc->str) == 0) {
811                      /* If the ITEM_NO_EQUALS flag is set we do NOT
812                       *   scan for = after the keyword  */
813                      if (!(items[i].flags & ITEM_NO_EQUALS)) {
814                         token = lex_get_token(lc, T_SKIP_EOL);
815                         Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
816                         if (token != T_EQUALS) {
817                            scan_err1(lc, _("expected an equals, got: %s"), lc->str);
818                            return 0;
819                         }
820                      }
821                      Dmsg1(800, "calling handler for %s\n", items[i].name);
822                      /* Call item handler */
823                      items[i].handler(lc, &items[i], i, pass);
824                      i = -1;
825                      break;
826                   }
827                }
828                if (i >= 0) {
829                   Dmsg2(900, "level=%d id=%s\n", level, lc->str);
830                   Dmsg1(900, "Keyword = %s\n", lc->str);
831                   scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
832                      "Perhaps you left the trailing brace off of the previous resource."), lc->str);
833                   return 0;
834                }
835                break;
836
837             case T_EOB:
838                level--;
839                state = p_none;
840                Dmsg0(900, "T_EOB => define new resource\n");
841                save_resource(res_type, items, pass);  /* save resource */
842                break;
843
844             case T_EOL:
845                break;
846
847             default:
848                scan_err2(lc, _("unexpected token %d %s in resource definition"),
849                   token, lex_tok_to_str(token));
850                return 0;
851             }
852             break;
853          default:
854             scan_err1(lc, _("Unknown parser state %d\n"), state);
855             return 0;
856          }
857       }
858       if (state != p_none) {
859          scan_err0(lc, _("End of conf file reached with unclosed resource."));
860          return 0;
861       }
862       if (debug_level >= 900 && pass == 2) {
863          int i;
864          for (i=r_first; i<=r_last; i++) {
865             dump_resource(i, res_head[i-r_first], prtmsg, NULL);
866          }
867       }
868       lc = lex_close_file(lc);
869    }
870    Dmsg0(900, "Leave parse_config()\n");
871    return 1;
872 }
873
874 /*********************************************************************
875  *
876  *      Free configuration resources
877  *
878  */
879 void free_config_resources()
880 {
881    for (int i=r_first; i<=r_last; i++) {
882       free_resource(res_head[i-r_first], i);
883       res_head[i-r_first] = NULL;
884    }
885 }
886
887 RES **save_config_resources()
888 {
889    int num = r_last - r_first + 1;
890    RES **res = (RES **)malloc(num*sizeof(RES *));
891    for (int i=0; i<num; i++) {
892       res[i] = res_head[i];
893       res_head[i] = NULL;
894    }
895    return res;
896 }
897
898 RES **new_res_head()
899 {
900    int size = (r_last - r_first + 1) * sizeof(RES *);
901    RES **res = (RES **)malloc(size);
902    memset(res, 0, size);
903    return res;
904 }