2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 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();
84 static bool find_config_file(const char *config_file, char *full_path, int max_path);
86 /* Common Resource definitions */
88 /* Message resource directives
89 * name handler value code flags default_value
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}
115 /* Various message types */
116 static struct s_mtypes msg_types[] = {
121 {"Warning", M_WARNING},
124 {"NotSaved", M_NOTSAVED},
125 {"Skipped", M_SKIPPED},
127 {"Terminate", M_TERM},
128 {"Restored", M_RESTORED},
129 {"Security", M_SECURITY},
131 {"VolMgmt", M_VOLMGMT},
132 {"ErrorTerm", M_ERROR_TERM},
138 * Tape Label types permitted in Pool records
140 * tape label label code = token
142 s_kw tapelabels[] = {
143 {"Bacula", B_BACULA_LABEL},
144 {"ANSI", B_ANSI_LABEL},
145 {"IBM", B_IBM_LABEL},
150 /* Simply print a message */
151 static void prtmsg(void *sock, const char *fmt, ...)
155 va_start(arg_ptr, fmt);
156 vfprintf(stdout, fmt, arg_ptr);
160 const char *res_to_str(int rcode)
162 if (rcode < r_first || rcode > r_last) {
163 return _("***UNKNOWN***");
165 return resources[rcode-r_first].name;
171 * Initialize the static structure to zeros, then
172 * apply all the default values.
174 static void init_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
177 int rindex = type - r_first;
179 memset(config->m_res_all, 0, config->m_res_all_size);
180 res_all.hdr.rcode = type;
181 res_all.hdr.refcnt = 1;
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);
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]);
217 /* Store Messages Destination information */
218 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
225 Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
227 switch (item->code) {
230 case MD_SYSLOG: /* syslog */
233 scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
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;
243 cmd = res_all.res_msgs.mail_cmd;
245 dest = get_pool_memory(PM_MESSAGE);
248 /* Pick up comma separated list of destinations */
250 token = lex_get_token(lc, T_NAME); /* scan destination */
251 dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
253 pm_strcat(dest, " "); /* separate multiple destinations with space */
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 */
263 if (token != T_EQUALS) {
264 scan_err1(lc, _("expected an =, got: %s"), lc->str);
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");
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);
288 scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
289 free_pool_memory(dest);
290 Dmsg0(900, "done with dest codes\n");
294 scan_err1(lc, _("Unknown item code: %d\n"), item->code);
299 set_bit(index, res_all.hdr.item_present);
300 Dmsg0(900, "Done store_msgs\n");
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, ...)
309 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
317 lex_get_token(lc, T_NAME); /* expect at least one type */
319 if (lc->str[0] == '!') {
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;
334 scan_err1(lc, _("message type: %s not found"), str);
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);
343 rem_msg_dest(msg, dest_code, msg_type, where);
345 add_msg_dest(msg, dest_code, msg_type, where, cmd);
350 Dmsg0(900, "call lex_get_token() to eat comma\n");
351 lex_get_token(lc, T_ALL); /* eat comma */
353 Dmsg0(900, "Done scan_types()\n");
358 * This routine is ONLY for resource names
359 * Store a name at specified address.
361 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
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);
369 free_pool_memory(msg);
370 /* Store the name both pass 1 and pass 2 */
371 if (*(item->value)) {
372 scan_err5(lc, _("Attempt to redefine \"%s\" from \"%s\" to \"%s\" referenced on line %d : %s\n"),
373 item->name, *(item->value), lc->str, lc->line_no, lc->line);
376 *(item->value) = bstrdup(lc->str);
378 set_bit(index, res_all.hdr.item_present);
383 * Store a name string at specified address
384 * A name string is limited to MAX_RES_NAME_LENGTH
386 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
388 lex_get_token(lc, T_NAME);
391 if (*(item->value)) {
392 scan_err5(lc, _("Attempt to redefine \"%s\" from \"%s\" to \"%s\" referenced on line %d : %s\n"),
393 item->name, *(item->value), lc->str, lc->line_no, lc->line);
396 *(item->value) = bstrdup(lc->str);
399 set_bit(index, res_all.hdr.item_present);
402 /* Store a string at specified address */
403 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
405 lex_get_token(lc, T_STRING);
407 if (*(item->value)) {
408 scan_err5(lc, _("Attempt to redefine \"%s\" from \"%s\" to \"%s\" referenced on line %d : %s\n"),
409 item->name, *(item->value), lc->str, lc->line_no, lc->line);
412 *(item->value) = bstrdup(lc->str);
415 set_bit(index, res_all.hdr.item_present);
419 * Store a directory name at specified address. Note, we do
420 * shell expansion except if the string begins with a vertical
421 * bar (i.e. it will likely be passed to the shell later).
423 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
425 lex_get_token(lc, T_STRING);
427 if (lc->str[0] != '|') {
428 do_shell_expansion(lc->str, sizeof_pool_memory(lc->str));
430 if (*(item->value)) {
431 scan_err5(lc, _("Attempt to redefine \"%s\" from \"%s\" to \"%s\" referenced on line %d : %s\n"),
432 item->name, *(item->value), lc->str, lc->line_no, lc->line);
435 *(item->value) = bstrdup(lc->str);
438 set_bit(index, res_all.hdr.item_present);
442 /* Store a password specified address in MD5 coding */
443 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
446 struct MD5Context md5c;
447 unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
451 lex_get_token(lc, T_STRING);
454 MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
455 MD5Final(digest, &md5c);
456 for (i = j = 0; i < sizeof(digest); i++) {
457 sprintf(&sig[j], "%02x", digest[i]);
460 if (*(item->value)) {
461 scan_err5(lc, _("Attempt to redefine \"%s\" from \"%s\" to \"%s\" referenced on line %d : %s\n"),
462 item->name, *(item->value), lc->str, lc->line_no, lc->line);
465 *(item->value) = bstrdup(sig);
468 set_bit(index, res_all.hdr.item_present);
472 /* Store a resource at specified address.
473 * If we are in pass 2, do a lookup of the
476 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
480 lex_get_token(lc, T_NAME);
482 res = GetResWithName(item->code, lc->str);
484 scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
485 lc->str, lc->line_no, lc->line);
488 if (*(item->value)) {
489 scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
490 item->name, lc->line_no, lc->line);
493 *(item->value) = (char *)res;
496 set_bit(index, res_all.hdr.item_present);
500 * Store a resource pointer in an alist. default_value indicates how many
501 * times this routine can be called -- i.e. how many alists
503 * If we are in pass 2, do a lookup of the
506 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
509 int count = item->default_value;
514 if (count == 0) { /* always store in item->value */
516 if ((item->value)[i] == NULL) {
517 list = New(alist(10, not_owned_by_alist));
519 list = (alist *)(item->value)[i];
522 /* Find empty place to store this directive */
523 while ((item->value)[i] != NULL && i++ < count) { }
525 scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
526 lc->str, count, lc->line_no, lc->line);
529 list = New(alist(10, not_owned_by_alist));
533 lex_get_token(lc, T_NAME); /* scan next item */
534 res = GetResWithName(item->code, lc->str);
536 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
537 item->name, lc->line_no, lc->line);
540 Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
541 res, list, list->size(), i, item->name);
543 (item->value)[i] = (char *)list;
544 if (lc->ch != ',') { /* if no other item follows */
547 lex_get_token(lc, T_ALL); /* eat comma */
551 set_bit(index, res_all.hdr.item_present);
556 * Store a string in an alist.
558 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
563 if (*(item->value) == NULL) {
564 list = New(alist(10, owned_by_alist));
565 *(item->value) = (char *)list;
567 list = (alist *)(*(item->value));
570 lex_get_token(lc, T_STRING); /* scan next item */
571 Dmsg4(900, "Append %s to alist 0x%p size=%d %s\n",
572 lc->str, list, list->size(), item->name);
573 list->append(bstrdup(lc->str));
574 if (lc->ch != ',') { /* if no other item follows */
577 lex_get_token(lc, T_ALL); /* eat comma */
581 set_bit(index, res_all.hdr.item_present);
587 * Store default values for Resource from xxxDefs
588 * If we are in pass 2, do a lookup of the
589 * resource and store everything not explicitly set
592 * Note, here item points to the main resource (e.g. Job, not
593 * the jobdefs, which we look up).
595 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
599 lex_get_token(lc, T_NAME);
601 Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
602 res = GetResWithName(item->code, lc->str);
604 scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
605 lc->str, lc->line_no, lc->line);
614 /* Store an integer at specified address */
615 void store_int32(LEX *lc, RES_ITEM *item, int index, int pass)
617 lex_get_token(lc, T_INT32);
618 *(uint32_t *)(item->value) = lc->int32_val;
620 set_bit(index, res_all.hdr.item_present);
623 /* Store a positive integer at specified address */
624 void store_pint32(LEX *lc, RES_ITEM *item, int index, int pass)
626 lex_get_token(lc, T_PINT32);
627 *(uint32_t *)(item->value) = lc->pint32_val;
629 set_bit(index, res_all.hdr.item_present);
633 /* Store an 64 bit integer at specified address */
634 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
636 lex_get_token(lc, T_INT64);
637 *(int64_t *)(item->value) = lc->int64_val;
639 set_bit(index, res_all.hdr.item_present);
642 enum store_unit_type {
647 /* Store a size in bytes */
648 static void store_int_unit(LEX *lc, RES_ITEM *item, int index, int pass,
649 bool size32, enum store_unit_type type)
655 Dmsg0(900, "Enter store_unit\n");
656 token = lex_get_token(lc, T_SKIP_EOL);
661 case T_UNQUOTED_STRING:
662 bstrncpy(bsize, lc->str, sizeof(bsize)); /* save first part */
663 /* if terminated by space, scan and get modifier */
664 while (lc->ch == ' ') {
665 token = lex_get_token(lc, T_ALL);
669 case T_UNQUOTED_STRING:
670 bstrncat(bsize, lc->str, sizeof(bsize));
674 if (type == STORE_SIZE) {
675 if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
676 scan_err1(lc, _("expected a size number, got: %s"), lc->str);
680 if (!speed_to_uint64(bsize, strlen(bsize), &uvalue)) {
681 scan_err1(lc, _("expected a speed number, got: %s"), lc->str);
686 *(uint32_t *)(item->value) = (uint32_t)uvalue;
688 *(uint64_t *)(item->value) = uvalue;
692 scan_err2(lc, _("expected a %s, got: %s"),
693 (type == STORE_SIZE)?_("size"):_("speed"), lc->str);
696 if (token != T_EOL) {
699 set_bit(index, res_all.hdr.item_present);
700 Dmsg0(900, "Leave store_unit\n");
703 /* Store a size in bytes */
704 void store_size32(LEX *lc, RES_ITEM *item, int index, int pass)
706 store_int_unit(lc, item, index, pass, true /* 32 bit */, STORE_SIZE);
709 /* Store a size in bytes */
710 void store_size64(LEX *lc, RES_ITEM *item, int index, int pass)
712 store_int_unit(lc, item, index, pass, false /* not 32 bit */, STORE_SIZE);
715 /* Store a speed in bytes/s */
716 void store_speed(LEX *lc, RES_ITEM *item, int index, int pass)
718 store_int_unit(lc, item, index, pass, false /* 64 bit */, STORE_SPEED);
721 /* Store a time period in seconds */
722 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
728 token = lex_get_token(lc, T_SKIP_EOL);
733 case T_UNQUOTED_STRING:
734 bstrncpy(period, lc->str, sizeof(period)); /* get first part */
735 /* if terminated by space, scan and get modifier */
736 while (lc->ch == ' ') {
737 token = lex_get_token(lc, T_ALL);
741 case T_UNQUOTED_STRING:
742 bstrncat(period, lc->str, sizeof(period));
746 if (!duration_to_utime(period, &utime)) {
747 scan_err1(lc, _("expected a time period, got: %s"), period);
750 *(utime_t *)(item->value) = utime;
753 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
756 if (token != T_EOL) {
759 set_bit(index, res_all.hdr.item_present);
763 /* Store a yes/no in a bit field */
764 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
766 lex_get_token(lc, T_NAME);
767 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
768 *(uint32_t *)(item->value) |= item->code;
769 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
770 *(uint32_t *)(item->value) &= ~(item->code);
772 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
776 set_bit(index, res_all.hdr.item_present);
779 /* Store a bool in a bit field */
780 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
782 lex_get_token(lc, T_NAME);
783 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
784 *(bool *)(item->value) = true;
785 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
786 *(bool *)(item->value) = false;
788 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
792 set_bit(index, res_all.hdr.item_present);
797 * Store Tape Label Type (Bacula, ANSI, IBM)
800 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
804 lex_get_token(lc, T_NAME);
805 /* Store the label pass 2 so that type is defined */
806 for (i=0; tapelabels[i].name; i++) {
807 if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
808 *(uint32_t *)(item->value) = tapelabels[i].token;
814 scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
818 set_bit(index, res_all.hdr.item_present);
828 CONFIG *new_config_parser()
831 config = (CONFIG *)malloc(sizeof(CONFIG));
832 memset(config, 0, sizeof(CONFIG));
838 LEX_ERROR_HANDLER *scan_error,
841 int32_t res_all_size,
844 RES_TABLE *resources,
848 m_scan_error = scan_error;
849 m_err_type = err_type;
850 m_res_all = vres_all;
851 m_res_all_size = res_all_size;
854 m_resources = resources;
855 m_res_head = res_head;
858 /*********************************************************************
860 * Parse configuration file
862 * Return 0 if reading failed, 1 otherwise
863 * Note, the default behavior unless you have set an alternate
864 * scan_error handler is to die on an error.
866 bool CONFIG::parse_config()
871 enum parse_state state = p_none;
872 RES_ITEM *items = NULL;
874 static bool first = true;
876 const char *cf = m_cf;
877 LEX_ERROR_HANDLER *scan_error = m_scan_error;
878 int err_type = m_err_type;
880 if (first && (errstat=rwl_init(&res_lock)) != 0) {
882 Jmsg1(NULL, M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
883 be.bstrerror(errstat));
887 char *full_path = (char *)alloca(MAX_PATH + 1);
889 if (!find_config_file(cf, full_path, MAX_PATH +1)) {
890 Jmsg0(NULL, M_ABORT, 0, _("Config filename too long.\n"));
894 /* Make two passes. The first builds the name symbol table,
895 * and the second picks up the items.
897 Dmsg0(900, "Enter parse_config()\n");
898 for (pass=1; pass <= 2; pass++) {
899 Dmsg1(900, "parse_config pass %d\n", pass);
900 if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
902 /* We must create a lex packet to print the error */
903 lc = (LEX *)malloc(sizeof(LEX));
904 memset(lc, 0, sizeof(LEX));
905 lc->str = get_memory(5000);
907 lc->scan_error = scan_error;
909 lex_set_default_error_handler(lc);
911 lex_set_error_handler_error_type(lc, err_type) ;
912 pm_strcpy(lc->str, cf);
914 scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
915 lc->str, be.bstrerror());
916 free_pool_memory(lc->str);
920 lex_set_error_handler_error_type(lc, err_type) ;
921 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
922 Dmsg3(900, "parse state=%d pass=%d got token=%s\n", state, pass,
923 lex_tok_to_str(token));
926 if (token == T_EOL) {
928 } else if (token == T_UTF8_BOM) {
929 /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */
931 } else if (token == T_UTF16_BOM) {
932 scan_err0(lc, _("Currently we cannot handle UTF-16 source files. "
933 "Please convert the conf file to UTF-8\n"));
935 } else if (token != T_IDENTIFIER) {
936 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
939 for (i=0; resources[i].name; i++) {
940 if (strcasecmp(resources[i].name, lc->str) == 0) {
941 items = resources[i].items;
946 res_type = resources[i].rcode;
947 init_resource(this, res_type, items, pass);
951 if (state == p_none) {
952 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
963 scan_err1(lc, _("not in resource definition: %s"), lc->str);
966 for (i=0; items[i].name; i++) {
967 if (strcasecmp(items[i].name, lc->str) == 0) {
968 /* If the ITEM_NO_EQUALS flag is set we do NOT
969 * scan for = after the keyword */
970 if (!(items[i].flags & ITEM_NO_EQUALS)) {
971 token = lex_get_token(lc, T_SKIP_EOL);
972 Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
973 if (token != T_EQUALS) {
974 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
978 Dmsg1(800, "calling handler for %s\n", items[i].name);
979 /* Call item handler */
980 items[i].handler(lc, &items[i], i, pass);
986 Dmsg2(900, "level=%d id=%s\n", level, lc->str);
987 Dmsg1(900, "Keyword = %s\n", lc->str);
988 scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
989 "Perhaps you left the trailing brace off of the previous resource."), lc->str);
997 Dmsg0(900, "T_EOB => define new resource\n");
998 if (res_all.hdr.name == NULL) {
999 scan_err0(lc, _("Name not specified for resource"));
1002 save_resource(res_type, items, pass); /* save resource */
1009 scan_err2(lc, _("unexpected token %d %s in resource definition"),
1010 token, lex_tok_to_str(token));
1015 scan_err1(lc, _("Unknown parser state %d\n"), state);
1019 if (state != p_none) {
1020 scan_err0(lc, _("End of conf file reached with unclosed resource."));
1023 if (debug_level >= 900 && pass == 2) {
1025 for (i=m_r_first; i<=m_r_last; i++) {
1026 dump_resource(i, m_res_head[i-m_r_first], prtmsg, NULL);
1029 lc = lex_close_file(lc);
1031 Dmsg0(900, "Leave parse_config()\n");
1035 lc = lex_close_file(lc);
1040 const char *get_default_configdir()
1046 * Returns false on error
1047 * true on OK, with full_path set to where config file should be
1050 find_config_file(const char *config_file, char *full_path, int max_path)
1052 int file_length = strlen(config_file) + 1;
1054 /* If a full path specified, use it */
1055 if (first_path_separator(config_file) != NULL) {
1056 if (file_length > max_path) {
1059 bstrncpy(full_path, config_file, file_length);
1063 /* config_file is default file name, now find default dir */
1064 const char *config_dir = get_default_configdir();
1065 int dir_length = strlen(config_dir);
1067 if ((dir_length + 1 + file_length) > max_path) {
1071 memcpy(full_path, config_dir, dir_length + 1);
1073 if (!IsPathSeparator(full_path[dir_length - 1])) {
1074 full_path[dir_length++] = '/';
1077 memcpy(&full_path[dir_length], config_file, file_length);
1082 /*********************************************************************
1084 * Free configuration resources
1087 void CONFIG::free_resources()
1089 for (int i=m_r_first; i<=m_r_last; i++) {
1090 free_resource(m_res_head[i-m_r_first], i);
1091 m_res_head[i-m_r_first] = NULL;
1095 RES **CONFIG::save_resources()
1097 int num = m_r_last - m_r_first + 1;
1098 RES **res = (RES **)malloc(num*sizeof(RES *));
1099 for (int i=0; i<num; i++) {
1100 res[i] = m_res_head[i];
1101 m_res_head[i] = NULL;
1106 RES **CONFIG::new_res_head()
1108 int size = (m_r_last - m_r_first + 1) * sizeof(RES *);
1109 RES **res = (RES **)malloc(size);
1110 memset(res, 0, size);
1116 void free_config_resources()
1118 for (int i=r_first; i<=r_last; i++) {
1119 free_resource(res_head[i-r_first], i);
1120 res_head[i-r_first] = NULL;
1124 RES **save_config_resources()
1126 int num = r_last - r_first + 1;
1127 RES **res = (RES **)malloc(num*sizeof(RES *));
1128 for (int i=0; i<num; i++) {
1129 res[i] = res_head[i];
1135 RES **new_res_head()
1137 int size = (r_last - r_first + 1) * sizeof(RES *);
1138 RES **res = (RES **)malloc(size);
1139 memset(res, 0, size);