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