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