2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Master Configuration routines.
22 * This file contains the common parts of the Bacula
23 * configuration routines.
25 * Note, the configuration file parser consists of three parts
27 * 1. The generic lexical scanner in lib/lex.c and lib/lex.h
29 * 2. The generic config scanner in lib/parse_conf.c and
31 * These files contain the parser code, some utility
32 * routines, and the common store routines (name, int,
33 * string, time, int64, size, ...).
35 * 3. The daemon specific file, which contains the Resource
36 * definitions as well as any specific store routines
37 * for the resource records.
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
49 * Kern Sibbald, January MM
56 #if defined(HAVE_WIN32)
63 * Define the Union of all the common resource structure definitions.
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;
78 extern brwlock_t res_lock; /* resource lock */
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();
85 /* Common Resource definitions */
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.
94 * name handler value code flags default_value
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}
117 /* Various message types */
119 {"Debug", M_DEBUG}, /* Keep 1st place */
120 {"Saved", M_SAVED}, /* Keep 2nd place */
124 {"Warning", M_WARNING},
126 {"NotSaved", M_NOTSAVED},
127 {"Skipped", M_SKIPPED},
129 {"Terminate", M_TERM},
130 {"Restored", M_RESTORED},
131 {"Security", M_SECURITY},
133 {"VolMgmt", M_VOLMGMT},
134 {"ErrorTerm", M_ERROR_TERM},
141 * Tape Label types permitted in Pool records
143 * tape label label code = token
145 s_kw tapelabels[] = {
146 {"Bacula", B_BACULA_LABEL},
147 {"ANSI", B_ANSI_LABEL},
148 {"IBM", B_IBM_LABEL},
153 /* Simply print a message */
154 static void prtmsg(void *sock, const char *fmt, ...)
158 va_start(arg_ptr, fmt);
159 vfprintf(stdout, fmt, arg_ptr);
163 const char *res_to_str(int rcode)
165 if (rcode < r_first || rcode > r_last) {
166 return _("***UNKNOWN***");
168 return resources[rcode-r_first].name;
173 * Create a new res_head pointer to a list of res_heads
175 void CONFIG::init_res_head(RES_HEAD ***rhead, int32_t rfirst, int32_t rlast)
177 int num = rlast - rfirst + 1;
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));
190 * Insert the resource in res_all into the
193 bool CONFIG::insert_res(int rindex, int size)
196 rblist *list = m_res_head[rindex]->res_list;
197 res = (RES *)malloc(size);
198 memcpy(res, m_res_all, size);
200 list->insert(res, res_compare);
201 m_res_head[rindex]->first = res;
202 m_res_head[rindex]->last = res;
205 prev = m_res_head[rindex]->last;
206 item = (RES *)list->insert(res, res_compare);
208 Mmsg(m_errmsg, _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
209 resources[rindex].name, ((URES *)res)->hdr.name);
212 prev->res_next = res;
213 m_res_head[rindex]->last = res;
215 Dmsg2(900, _("Inserted res: %s index=%d\n"), ((URES *)res)->hdr.name, rindex);
220 * Initialize the static structure to zeros, then
221 * apply all the default values.
223 static void init_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
226 int rindex = type - r_first;
228 memset(config->m_res_all, 0, config->m_res_all_size);
229 res_all.hdr.rcode = type;
230 res_all.hdr.refcnt = 1;
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);
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);
265 /* Initialize a resouce with default values */
266 bool init_resource(CONFIG *config, uint32_t type, void *res)
269 for (int i=0; resources[i].name; i++) {
270 if (resources[i].rcode == type) {
271 items = resources[i].items;
275 init_resource(config, type, items, 1);
276 memcpy(res, config->m_res_all, config->m_res_all_size);
284 * Dump each resource of type
286 void dump_each_resource(int type, void sendit(void *sock, const char *fmt, ...), void *sock)
290 if (type < 0) { /* no recursion */
293 foreach_res(res, type) {
294 dump_resource(-type, res, sendit, sock);
299 /* Store Messages Destination information */
300 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
307 Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
309 switch (item->code) {
312 case MD_SYSLOG: /* syslog */
315 scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
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;
325 cmd = res_all.res_msgs.mail_cmd;
327 dest = get_pool_memory(PM_MESSAGE);
330 /* Pick up comma separated list of destinations */
332 token = lex_get_token(lc, T_NAME); /* scan destination */
333 dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
335 pm_strcat(dest, " "); /* separate multiple destinations with space */
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 */
345 if (token != T_EQUALS) {
346 scan_err1(lc, _("expected an =, got: %s"), lc->str);
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");
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);
370 scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
371 free_pool_memory(dest);
372 Dmsg0(900, "done with dest codes\n");
376 scan_err1(lc, _("Unknown item code: %d\n"), item->code);
381 set_bit(index, res_all.hdr.item_present);
382 Dmsg0(900, "Done store_msgs\n");
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, ...)
391 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
399 lex_get_token(lc, T_NAME); /* expect at least one type */
401 if (lc->str[0] == '!') {
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;
416 scan_err1(lc, _("message type: %s not found"), str);
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);
425 rem_msg_dest(msg, dest_code, msg_type, where);
427 add_msg_dest(msg, dest_code, msg_type, where, cmd);
432 Dmsg0(900, "call lex_get_token() to eat comma\n");
433 lex_get_token(lc, T_ALL); /* eat comma */
435 Dmsg0(900, "Done scan_types()\n");
440 * This routine is ONLY for resource names
441 * Store a name at specified address.
443 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
445 POOLMEM *msg = get_pool_memory(PM_EMSG);
447 lex_get_token(lc, T_NAME);
448 if (!is_name_valid(lc->str, &msg)) {
449 scan_err1(lc, "%s\n", msg);
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);
459 *(item->value) = bstrdup(lc->str);
461 set_bit(index, res_all.hdr.item_present);
466 * Store a name string at specified address
467 * A name string is limited to MAX_RES_NAME_LENGTH
469 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
471 lex_get_token(lc, T_NAME);
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);
479 *(item->value) = bstrdup(lc->str);
482 set_bit(index, res_all.hdr.item_present);
485 /* Store a string at specified address */
486 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
488 lex_get_token(lc, T_STRING);
490 if (*(item->value) && (item->flags & ITEM_ALLOW_DUPS)) {
491 free(*(item->value));
492 *(item->value) = NULL;
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);
499 *(item->value) = bstrdup(lc->str);
502 set_bit(index, res_all.hdr.item_present);
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).
510 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
512 lex_get_token(lc, T_STRING);
514 if (lc->str[0] != '|') {
515 do_shell_expansion(lc->str, sizeof_pool_memory(lc->str));
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])) {
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);
530 *(item->value) = bstrdup(lc->str);
533 set_bit(index, res_all.hdr.item_present);
537 /* Store a password specified address in MD5 coding */
538 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
541 struct MD5Context md5c;
542 unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
545 if (lc->options & LOPT_NO_MD5) {
546 store_str(lc, item, index, pass);
549 lex_get_token(lc, T_STRING);
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]);
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);
563 *(item->value) = bstrdup(sig);
566 set_bit(index, res_all.hdr.item_present);
571 /* Store a resource at specified address.
572 * If we are in pass 2, do a lookup of the
575 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
579 lex_get_token(lc, T_NAME);
581 res = GetResWithName(item->code, lc->str);
583 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
584 lc->str, lc->line_no, lc->line);
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);
592 *(item->value) = (char *)res;
595 set_bit(index, res_all.hdr.item_present);
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
602 * If we are in pass 2, do a lookup of the
605 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
608 int count = item->default_value;
613 if (count == 0) { /* always store in item->value */
615 if ((item->value)[i] == NULL) {
616 list = New(alist(10, not_owned_by_alist));
618 list = (alist *)(item->value)[i];
621 /* Find empty place to store this directive */
622 while ((item->value)[i] != NULL && 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);
628 list = New(alist(10, not_owned_by_alist));
632 lex_get_token(lc, T_NAME); /* scan next item */
633 res = GetResWithName(item->code, lc->str);
635 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
636 lc->str, lc->line_no, lc->line);
639 Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
640 res, list, list->size(), i, item->name);
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);
651 lex_get_token(lc, T_ALL); /* eat comma */
655 set_bit(index, res_all.hdr.item_present);
660 * Store a string in an alist.
662 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
667 if (*(item->value) == NULL) {
668 list = New(alist(10, owned_by_alist));
669 *(item->value) = (char *)list;
671 list = (alist *)(*(item->value));
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);
686 lex_get_token(lc, T_ALL); /* eat comma */
690 set_bit(index, res_all.hdr.item_present);
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
701 * Note, here item points to the main resource (e.g. Job, not
702 * the jobdefs, which we look up).
704 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
708 lex_get_token(lc, T_NAME);
710 Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
711 res = GetResWithName(item->code, lc->str);
713 scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
714 lc->str, lc->line_no, lc->line);
723 /* Store an integer at specified address */
724 void store_int32(LEX *lc, RES_ITEM *item, int index, int pass)
726 lex_get_token(lc, T_INT32);
727 *(uint32_t *)(item->value) = lc->int32_val;
729 set_bit(index, res_all.hdr.item_present);
732 /* Store a positive integer at specified address */
733 void store_pint32(LEX *lc, RES_ITEM *item, int index, int pass)
735 lex_get_token(lc, T_PINT32);
736 *(uint32_t *)(item->value) = lc->pint32_val;
738 set_bit(index, res_all.hdr.item_present);
742 /* Store an 64 bit integer at specified address */
743 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
745 lex_get_token(lc, T_INT64);
746 *(int64_t *)(item->value) = lc->int64_val;
748 set_bit(index, res_all.hdr.item_present);
751 enum store_unit_type {
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).
760 static void store_int_unit(LEX *lc, RES_ITEM *item, int index, int pass,
761 bool size32, enum store_unit_type type)
767 Dmsg0(900, "Enter store_unit\n");
768 token = lex_get_token(lc, T_SKIP_EOL);
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);
781 case T_UNQUOTED_STRING:
782 bstrncat(bsize, lc->str, sizeof(bsize));
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);
792 if (!speed_to_uint64(bsize, strlen(bsize), &uvalue)) {
793 scan_err1(lc, _("expected a speed number, got: %s"), lc->str);
798 *(uint32_t *)(item->value) = (uint32_t)uvalue;
800 *(uint64_t *)(item->value) = uvalue;
804 scan_err2(lc, _("expected a %s, got: %s"),
805 (type == STORE_SIZE)?_("size"):_("speed"), lc->str);
808 if (token != T_EOL) {
811 set_bit(index, res_all.hdr.item_present);
812 Dmsg0(900, "Leave store_unit\n");
815 /* Store a size in bytes */
816 void store_size32(LEX *lc, RES_ITEM *item, int index, int pass)
818 store_int_unit(lc, item, index, pass, true /* 32 bit */, STORE_SIZE);
821 /* Store a size in bytes */
822 void store_size64(LEX *lc, RES_ITEM *item, int index, int pass)
824 store_int_unit(lc, item, index, pass, false /* not 32 bit */, STORE_SIZE);
827 /* Store a speed in bytes/s */
828 void store_speed(LEX *lc, RES_ITEM *item, int index, int pass)
830 store_int_unit(lc, item, index, pass, false /* 64 bit */, STORE_SPEED);
833 /* Store a time period in seconds */
834 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
840 token = lex_get_token(lc, T_SKIP_EOL);
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);
853 case T_UNQUOTED_STRING:
854 bstrncat(period, lc->str, sizeof(period));
858 if (!duration_to_utime(period, &utime)) {
859 scan_err1(lc, _("expected a time period, got: %s"), period);
862 *(utime_t *)(item->value) = utime;
865 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
868 if (token != T_EOL) {
871 set_bit(index, res_all.hdr.item_present);
875 /* Store a yes/no in a bit field */
876 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
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);
884 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
888 set_bit(index, res_all.hdr.item_present);
891 /* Store a bool in a bit field */
892 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
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;
900 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
904 set_bit(index, res_all.hdr.item_present);
909 * Store Tape Label Type (Bacula, ANSI, IBM)
912 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
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;
926 scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
930 set_bit(index, res_all.hdr.item_present);
942 LEX_ERROR_HANDLER *scan_error,
945 int32_t res_all_size,
948 RES_TABLE *resources,
949 RES_HEAD ***res_head)
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;
958 m_resources = resources;
959 init_res_head(res_head, r_first, r_last);
960 m_res_head = *res_head;
963 /*********************************************************************
965 * Parse configuration file
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.
971 bool CONFIG::parse_config()
976 enum parse_state state = p_none;
977 RES_ITEM *items = NULL;
979 static bool first = true;
981 const char *cf = m_cf;
982 LEX_ERROR_HANDLER *scan_error = m_scan_error;
983 int err_type = m_err_type;
986 if (first && (errstat=rwl_init(&res_lock)) != 0) {
988 Jmsg1(NULL, M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
989 be.bstrerror(errstat));
993 char *full_path = (char *)alloca(MAX_PATH + 1);
995 if (!find_config_file(cf, full_path, MAX_PATH +1)) {
996 Jmsg0(NULL, M_ABORT, 0, _("Config filename too long.\n"));
1000 /* Make two passes. The first builds the name symbol table,
1001 * and the second picks up the items.
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) {
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);
1013 lc->scan_error = scan_error;
1015 lex_set_default_error_handler(lc);
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);
1026 if (!m_encode_pass) {
1027 lex_store_clear_passwords(lc);
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));
1035 if (token == T_EOL) {
1037 } else if (token == T_UTF8_BOM) {
1038 /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */
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"));
1044 } else if (token != T_IDENTIFIER) {
1045 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
1048 for (i=0; resources[i].name; i++) {
1049 if (strcasecmp(resources[i].name, lc->str) == 0) {
1050 items = resources[i].items;
1055 res_type = resources[i].rcode;
1056 init_resource(this, res_type, items, pass);
1060 if (state == p_none) {
1061 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
1072 scan_err1(lc, _("not in resource definition: %s"), lc->str);
1075 for (i=0; items[i].name; i++) {
1077 //hpkt.ritem = &items[i];
1078 //hpkt.edbuf = NULL;
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);
1093 Dmsg1(800, "calling handler for %s\n", items[i].name);
1094 /* Call item handler */
1095 items[i].handler(lc, &items[i], i, pass);
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);
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"));
1117 if (!save_resource(this, res_type, items, pass)) { /* save resource */
1118 scan_err1(lc, "%s", m_errmsg);
1127 scan_err2(lc, _("unexpected token %d %s in resource definition"),
1128 token, lex_tok_to_str(token));
1133 scan_err1(lc, _("Unknown parser state %d\n"), state);
1137 if (state != p_none) {
1138 scan_err0(lc, _("End of conf file reached with unclosed resource."));
1141 if (chk_dbglvl(900) && pass == 2) {
1143 for (i=m_r_first; i<=m_r_last; i++) {
1144 dump_each_resource(i, prtmsg, NULL);
1147 lc = lex_close_file(lc);
1149 Dmsg0(900, "Leave parse_config()\n");
1153 lc = lex_close_file(lc);
1158 const char *get_default_configdir()
1165 static char szConfigDir[MAX_PATH + 1] = { 0 };
1166 if (!p_SHGetFolderPath) {
1167 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
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));
1175 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1183 * Returns false on error
1184 * true on OK, with full_path set to where config file should be
1187 find_config_file(const char *config_file, char *full_path, int max_path)
1189 int file_length = strlen(config_file) + 1;
1191 /* If a full path specified, use it */
1192 if (first_path_separator(config_file) != NULL) {
1193 if (file_length > max_path) {
1196 bstrncpy(full_path, config_file, file_length);
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);
1204 if ((dir_length + 1 + file_length) > max_path) {
1208 memcpy(full_path, config_dir, dir_length + 1);
1210 if (!IsPathSeparator(full_path[dir_length - 1])) {
1211 full_path[dir_length++] = '/';
1214 memcpy(&full_path[dir_length], config_file, file_length);
1219 /*********************************************************************
1221 * Free configuration resources
1224 void CONFIG::free_all_resources()
1227 if (m_res_head == NULL) {
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 */
1238 next = res->res_next;
1239 free_resource(res, i);
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;
1254 m_encode_pass(true),
1260 m_errmsg = get_pool_memory(PM_EMSG);
1265 free_all_resources();
1266 free_pool_memory(m_errmsg);
1269 void CONFIG::encode_password(bool a)