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