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, ITEM_ALLOW_DUPS, 0},
95 {"OperatorCommand", store_str, ITEM(res_msgs.operator_cmd), 0, ITEM_ALLOW_DUPS, 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 directives in \"%s\" resource\n"), resources[rindex].name);
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) && (item->flags & ITEM_ALLOW_DUPS)) {
408 free(*(item->value));
409 *(item->value) = NULL;
411 if (*(item->value)) {
412 scan_err5(lc, _("Attempt to redefine \"%s\" from \"%s\" to \"%s\" referenced on line %d : %s\n"),
413 item->name, *(item->value), lc->str, lc->line_no, lc->line);
416 *(item->value) = bstrdup(lc->str);
419 set_bit(index, res_all.hdr.item_present);
423 * Store a directory name at specified address. Note, we do
424 * shell expansion except if the string begins with a vertical
425 * bar (i.e. it will likely be passed to the shell later).
427 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
429 lex_get_token(lc, T_STRING);
431 if (lc->str[0] != '|') {
432 do_shell_expansion(lc->str, sizeof_pool_memory(lc->str));
434 if (*(item->value)) {
435 scan_err5(lc, _("Attempt to redefine \"%s\" from \"%s\" to \"%s\" referenced on line %d : %s\n"),
436 item->name, *(item->value), lc->str, lc->line_no, lc->line);
439 *(item->value) = bstrdup(lc->str);
442 set_bit(index, res_all.hdr.item_present);
446 /* Store a password specified address in MD5 coding */
447 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
450 struct MD5Context md5c;
451 unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
455 lex_get_token(lc, T_STRING);
458 MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
459 MD5Final(digest, &md5c);
460 for (i = j = 0; i < sizeof(digest); i++) {
461 sprintf(&sig[j], "%02x", digest[i]);
464 if (*(item->value)) {
465 scan_err5(lc, _("Attempt to redefine \"%s\" from \"%s\" to \"%s\" referenced on line %d : %s\n"),
466 item->name, *(item->value), lc->str, lc->line_no, lc->line);
469 *(item->value) = bstrdup(sig);
472 set_bit(index, res_all.hdr.item_present);
476 /* Store a resource at specified address.
477 * If we are in pass 2, do a lookup of the
480 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
484 lex_get_token(lc, T_NAME);
486 res = GetResWithName(item->code, lc->str);
488 scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
489 lc->str, lc->line_no, lc->line);
492 if (*(item->value)) {
493 scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
494 item->name, lc->line_no, lc->line);
497 *(item->value) = (char *)res;
500 set_bit(index, res_all.hdr.item_present);
504 * Store a resource pointer in an alist. default_value indicates how many
505 * times this routine can be called -- i.e. how many alists
507 * If we are in pass 2, do a lookup of the
510 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
513 int count = item->default_value;
518 if (count == 0) { /* always store in item->value */
520 if ((item->value)[i] == NULL) {
521 list = New(alist(10, not_owned_by_alist));
523 list = (alist *)(item->value)[i];
526 /* Find empty place to store this directive */
527 while ((item->value)[i] != NULL && i++ < count) { }
529 scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
530 lc->str, count, lc->line_no, lc->line);
533 list = New(alist(10, not_owned_by_alist));
537 lex_get_token(lc, T_NAME); /* scan next item */
538 res = GetResWithName(item->code, lc->str);
540 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
541 item->name, lc->line_no, lc->line);
544 Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
545 res, list, list->size(), i, item->name);
547 (item->value)[i] = (char *)list;
548 if (lc->ch != ',') { /* if no other item follows */
551 lex_get_token(lc, T_ALL); /* eat comma */
555 set_bit(index, res_all.hdr.item_present);
560 * Store a string in an alist.
562 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
567 if (*(item->value) == NULL) {
568 list = New(alist(10, owned_by_alist));
569 *(item->value) = (char *)list;
571 list = (alist *)(*(item->value));
574 lex_get_token(lc, T_STRING); /* scan next item */
575 Dmsg4(900, "Append %s to alist 0x%p size=%d %s\n",
576 lc->str, list, list->size(), item->name);
577 list->append(bstrdup(lc->str));
578 if (lc->ch != ',') { /* if no other item follows */
581 lex_get_token(lc, T_ALL); /* eat comma */
585 set_bit(index, res_all.hdr.item_present);
591 * Store default values for Resource from xxxDefs
592 * If we are in pass 2, do a lookup of the
593 * resource and store everything not explicitly set
596 * Note, here item points to the main resource (e.g. Job, not
597 * the jobdefs, which we look up).
599 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
603 lex_get_token(lc, T_NAME);
605 Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
606 res = GetResWithName(item->code, lc->str);
608 scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
609 lc->str, lc->line_no, lc->line);
618 /* Store an integer at specified address */
619 void store_int32(LEX *lc, RES_ITEM *item, int index, int pass)
621 lex_get_token(lc, T_INT32);
622 *(uint32_t *)(item->value) = lc->int32_val;
624 set_bit(index, res_all.hdr.item_present);
627 /* Store a positive integer at specified address */
628 void store_pint32(LEX *lc, RES_ITEM *item, int index, int pass)
630 lex_get_token(lc, T_PINT32);
631 *(uint32_t *)(item->value) = lc->pint32_val;
633 set_bit(index, res_all.hdr.item_present);
637 /* Store an 64 bit integer at specified address */
638 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
640 lex_get_token(lc, T_INT64);
641 *(int64_t *)(item->value) = lc->int64_val;
643 set_bit(index, res_all.hdr.item_present);
646 enum store_unit_type {
651 /* Store a size in bytes */
652 static void store_int_unit(LEX *lc, RES_ITEM *item, int index, int pass,
653 bool size32, enum store_unit_type type)
659 Dmsg0(900, "Enter store_unit\n");
660 token = lex_get_token(lc, T_SKIP_EOL);
665 case T_UNQUOTED_STRING:
666 bstrncpy(bsize, lc->str, sizeof(bsize)); /* save first part */
667 /* if terminated by space, scan and get modifier */
668 while (lc->ch == ' ') {
669 token = lex_get_token(lc, T_ALL);
673 case T_UNQUOTED_STRING:
674 bstrncat(bsize, lc->str, sizeof(bsize));
678 if (type == STORE_SIZE) {
679 if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
680 scan_err1(lc, _("expected a size number, got: %s"), lc->str);
684 if (!speed_to_uint64(bsize, strlen(bsize), &uvalue)) {
685 scan_err1(lc, _("expected a speed number, got: %s"), lc->str);
690 *(uint32_t *)(item->value) = (uint32_t)uvalue;
692 *(uint64_t *)(item->value) = uvalue;
696 scan_err2(lc, _("expected a %s, got: %s"),
697 (type == STORE_SIZE)?_("size"):_("speed"), lc->str);
700 if (token != T_EOL) {
703 set_bit(index, res_all.hdr.item_present);
704 Dmsg0(900, "Leave store_unit\n");
707 /* Store a size in bytes */
708 void store_size32(LEX *lc, RES_ITEM *item, int index, int pass)
710 store_int_unit(lc, item, index, pass, true /* 32 bit */, STORE_SIZE);
713 /* Store a size in bytes */
714 void store_size64(LEX *lc, RES_ITEM *item, int index, int pass)
716 store_int_unit(lc, item, index, pass, false /* not 32 bit */, STORE_SIZE);
719 /* Store a speed in bytes/s */
720 void store_speed(LEX *lc, RES_ITEM *item, int index, int pass)
722 store_int_unit(lc, item, index, pass, false /* 64 bit */, STORE_SPEED);
725 /* Store a time period in seconds */
726 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
732 token = lex_get_token(lc, T_SKIP_EOL);
737 case T_UNQUOTED_STRING:
738 bstrncpy(period, lc->str, sizeof(period)); /* get first part */
739 /* if terminated by space, scan and get modifier */
740 while (lc->ch == ' ') {
741 token = lex_get_token(lc, T_ALL);
745 case T_UNQUOTED_STRING:
746 bstrncat(period, lc->str, sizeof(period));
750 if (!duration_to_utime(period, &utime)) {
751 scan_err1(lc, _("expected a time period, got: %s"), period);
754 *(utime_t *)(item->value) = utime;
757 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
760 if (token != T_EOL) {
763 set_bit(index, res_all.hdr.item_present);
767 /* Store a yes/no in a bit field */
768 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
770 lex_get_token(lc, T_NAME);
771 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
772 *(uint32_t *)(item->value) |= item->code;
773 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
774 *(uint32_t *)(item->value) &= ~(item->code);
776 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
780 set_bit(index, res_all.hdr.item_present);
783 /* Store a bool in a bit field */
784 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
786 lex_get_token(lc, T_NAME);
787 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
788 *(bool *)(item->value) = true;
789 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
790 *(bool *)(item->value) = false;
792 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
796 set_bit(index, res_all.hdr.item_present);
801 * Store Tape Label Type (Bacula, ANSI, IBM)
804 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
808 lex_get_token(lc, T_NAME);
809 /* Store the label pass 2 so that type is defined */
810 for (i=0; tapelabels[i].name; i++) {
811 if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
812 *(uint32_t *)(item->value) = tapelabels[i].token;
818 scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
822 set_bit(index, res_all.hdr.item_present);
832 CONFIG *new_config_parser()
835 config = (CONFIG *)malloc(sizeof(CONFIG));
836 memset(config, 0, sizeof(CONFIG));
842 LEX_ERROR_HANDLER *scan_error,
845 int32_t res_all_size,
848 RES_TABLE *resources,
852 m_scan_error = scan_error;
853 m_err_type = err_type;
854 m_res_all = vres_all;
855 m_res_all_size = res_all_size;
858 m_resources = resources;
859 m_res_head = res_head;
862 /*********************************************************************
864 * Parse configuration file
866 * Return 0 if reading failed, 1 otherwise
867 * Note, the default behavior unless you have set an alternate
868 * scan_error handler is to die on an error.
870 bool CONFIG::parse_config()
875 enum parse_state state = p_none;
876 RES_ITEM *items = NULL;
878 static bool first = true;
880 const char *cf = m_cf;
881 LEX_ERROR_HANDLER *scan_error = m_scan_error;
882 int err_type = m_err_type;
884 if (first && (errstat=rwl_init(&res_lock)) != 0) {
886 Jmsg1(NULL, M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
887 be.bstrerror(errstat));
891 char *full_path = (char *)alloca(MAX_PATH + 1);
893 if (!find_config_file(cf, full_path, MAX_PATH +1)) {
894 Jmsg0(NULL, M_ABORT, 0, _("Config filename too long.\n"));
898 /* Make two passes. The first builds the name symbol table,
899 * and the second picks up the items.
901 Dmsg0(900, "Enter parse_config()\n");
902 for (pass=1; pass <= 2; pass++) {
903 Dmsg1(900, "parse_config pass %d\n", pass);
904 if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
906 /* We must create a lex packet to print the error */
907 lc = (LEX *)malloc(sizeof(LEX));
908 memset(lc, 0, sizeof(LEX));
909 lc->str = get_memory(5000);
911 lc->scan_error = scan_error;
913 lex_set_default_error_handler(lc);
915 lex_set_error_handler_error_type(lc, err_type) ;
916 pm_strcpy(lc->str, cf);
918 scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
919 lc->str, be.bstrerror());
920 free_pool_memory(lc->str);
924 lex_set_error_handler_error_type(lc, err_type) ;
925 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
926 Dmsg3(900, "parse state=%d pass=%d got token=%s\n", state, pass,
927 lex_tok_to_str(token));
930 if (token == T_EOL) {
932 } else if (token == T_UTF8_BOM) {
933 /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */
935 } else if (token == T_UTF16_BOM) {
936 scan_err0(lc, _("Currently we cannot handle UTF-16 source files. "
937 "Please convert the conf file to UTF-8\n"));
939 } else if (token != T_IDENTIFIER) {
940 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
943 for (i=0; resources[i].name; i++) {
944 if (strcasecmp(resources[i].name, lc->str) == 0) {
945 items = resources[i].items;
950 res_type = resources[i].rcode;
951 init_resource(this, res_type, items, pass);
955 if (state == p_none) {
956 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
967 scan_err1(lc, _("not in resource definition: %s"), lc->str);
970 for (i=0; items[i].name; i++) {
971 if (strcasecmp(items[i].name, lc->str) == 0) {
972 /* If the ITEM_NO_EQUALS flag is set we do NOT
973 * scan for = after the keyword */
974 if (!(items[i].flags & ITEM_NO_EQUALS)) {
975 token = lex_get_token(lc, T_SKIP_EOL);
976 Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
977 if (token != T_EQUALS) {
978 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
982 Dmsg1(800, "calling handler for %s\n", items[i].name);
983 /* Call item handler */
984 items[i].handler(lc, &items[i], i, pass);
990 Dmsg2(900, "level=%d id=%s\n", level, lc->str);
991 Dmsg1(900, "Keyword = %s\n", lc->str);
992 scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
993 "Perhaps you left the trailing brace off of the previous resource."), lc->str);
1001 Dmsg0(900, "T_EOB => define new resource\n");
1002 if (res_all.hdr.name == NULL) {
1003 scan_err0(lc, _("Name not specified for resource"));
1006 save_resource(res_type, items, pass); /* save resource */
1013 scan_err2(lc, _("unexpected token %d %s in resource definition"),
1014 token, lex_tok_to_str(token));
1019 scan_err1(lc, _("Unknown parser state %d\n"), state);
1023 if (state != p_none) {
1024 scan_err0(lc, _("End of conf file reached with unclosed resource."));
1027 if (debug_level >= 900 && pass == 2) {
1029 for (i=m_r_first; i<=m_r_last; i++) {
1030 dump_resource(i, m_res_head[i-m_r_first], prtmsg, NULL);
1033 lc = lex_close_file(lc);
1035 Dmsg0(900, "Leave parse_config()\n");
1039 lc = lex_close_file(lc);
1044 const char *get_default_configdir()
1050 * Returns false on error
1051 * true on OK, with full_path set to where config file should be
1054 find_config_file(const char *config_file, char *full_path, int max_path)
1056 int file_length = strlen(config_file) + 1;
1058 /* If a full path specified, use it */
1059 if (first_path_separator(config_file) != NULL) {
1060 if (file_length > max_path) {
1063 bstrncpy(full_path, config_file, file_length);
1067 /* config_file is default file name, now find default dir */
1068 const char *config_dir = get_default_configdir();
1069 int dir_length = strlen(config_dir);
1071 if ((dir_length + 1 + file_length) > max_path) {
1075 memcpy(full_path, config_dir, dir_length + 1);
1077 if (!IsPathSeparator(full_path[dir_length - 1])) {
1078 full_path[dir_length++] = '/';
1081 memcpy(&full_path[dir_length], config_file, file_length);
1086 /*********************************************************************
1088 * Free configuration resources
1091 void CONFIG::free_resources()
1093 for (int i=m_r_first; i<=m_r_last; i++) {
1094 free_resource(m_res_head[i-m_r_first], i);
1095 m_res_head[i-m_r_first] = NULL;
1099 RES **CONFIG::save_resources()
1101 int num = m_r_last - m_r_first + 1;
1102 RES **res = (RES **)malloc(num*sizeof(RES *));
1103 for (int i=0; i<num; i++) {
1104 res[i] = m_res_head[i];
1105 m_res_head[i] = NULL;
1110 RES **CONFIG::new_res_head()
1112 int size = (m_r_last - m_r_first + 1) * sizeof(RES *);
1113 RES **res = (RES **)malloc(size);
1114 memset(res, 0, size);
1120 void free_config_resources()
1122 for (int i=r_first; i<=r_last; i++) {
1123 free_resource(res_head[i-r_first], i);
1124 res_head[i-r_first] = NULL;
1128 RES **save_config_resources()
1130 int num = r_last - r_first + 1;
1131 RES **res = (RES **)malloc(num*sizeof(RES *));
1132 for (int i=0; i<num; i++) {
1133 res[i] = res_head[i];
1139 RES **new_res_head()
1141 int size = (r_last - r_first + 1) * sizeof(RES *);
1142 RES **res = (RES **)malloc(size);
1143 memset(res, 0, size);