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