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