2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Master Configuration routines.
31 * This file contains the common parts of the Bacula
32 * configuration routines.
34 * Note, the configuration file parser consists of three parts
36 * 1. The generic lexical scanner in lib/lex.c and lib/lex.h
38 * 2. The generic config scanner in lib/parse_conf.c and
40 * These files contain the parser code, some utility
41 * routines, and the common store routines (name, int,
42 * string, time, int64, size, ...).
44 * 3. The daemon specific file, which contains the Resource
45 * definitions as well as any specific store routines
46 * for the resource records.
48 * N.B. This is a two pass parser, so if you malloc() a string
49 * in a "store" routine, you must ensure to do it during
50 * only one of the two passes, or to free it between.
51 * Also, note that the resource record is malloced and
52 * saved in save_resource() during pass 1. Anything that
53 * you want saved after pass two (e.g. resource pointers)
54 * must explicitly be done in save_resource. Take a look
55 * at the Job resource in src/dird/dird_conf.c to see how
58 * Kern Sibbald, January MM
65 #if defined(HAVE_WIN32)
72 * Define the Union of all the common resource structure definitions.
80 // work around visual studio name mangling preventing external linkage since res_all
81 // is declared as a different type when instantiated.
82 extern "C" URES res_all;
87 extern brwlock_t res_lock; /* resource lock */
90 /* Forward referenced subroutines */
91 static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd);
92 static const char *get_default_configdir();
93 static bool find_config_file(const char *config_file, char *full_path, int max_path);
95 /* Common Resource definitions */
97 /* Message resource directives
98 * name handler value code flags default_value
100 RES_ITEM msgs_items[] = {
101 {"name", store_name, ITEM(res_msgs.hdr.name), 0, 0, 0},
102 {"description", store_str, ITEM(res_msgs.hdr.desc), 0, 0, 0},
103 {"mailcommand", store_str, ITEM(res_msgs.mail_cmd), 0, 0, 0},
104 {"operatorcommand", store_str, ITEM(res_msgs.operator_cmd), 0, 0, 0},
105 {"syslog", store_msgs, ITEM(res_msgs), MD_SYSLOG, 0, 0},
106 {"mail", store_msgs, ITEM(res_msgs), MD_MAIL, 0, 0},
107 {"mailonerror", store_msgs, ITEM(res_msgs), MD_MAIL_ON_ERROR, 0, 0},
108 {"mailonsuccess", store_msgs, ITEM(res_msgs), MD_MAIL_ON_SUCCESS, 0, 0},
109 {"file", store_msgs, ITEM(res_msgs), MD_FILE, 0, 0},
110 {"append", store_msgs, ITEM(res_msgs), MD_APPEND, 0, 0},
111 {"stdout", store_msgs, ITEM(res_msgs), MD_STDOUT, 0, 0},
112 {"stderr", store_msgs, ITEM(res_msgs), MD_STDERR, 0, 0},
113 {"director", store_msgs, ITEM(res_msgs), MD_DIRECTOR, 0, 0},
114 {"console", store_msgs, ITEM(res_msgs), MD_CONSOLE, 0, 0},
115 {"operator", store_msgs, ITEM(res_msgs), MD_OPERATOR, 0, 0},
116 {"catalog", store_msgs, ITEM(res_msgs), MD_CATALOG, 0, 0},
117 {NULL, NULL, {0}, 0, 0, 0}
124 /* Various message types */
125 static struct s_mtypes msg_types[] = {
130 {"warning", M_WARNING},
133 {"notsaved", M_NOTSAVED},
134 {"skipped", M_SKIPPED},
136 {"terminate", M_TERM},
137 {"restored", M_RESTORED},
138 {"security", M_SECURITY},
140 {"volmgmt", M_VOLMGMT},
145 /* Used for certain KeyWord tables */
152 * Tape Label types permitted in Pool records
154 * tape label label code = token
156 static s_kw tapelabels[] = {
157 {"bacula", B_BACULA_LABEL},
158 {"ansi", B_ANSI_LABEL},
159 {"ibm", B_IBM_LABEL},
164 /* Simply print a message */
165 static void prtmsg(void *sock, const char *fmt, ...)
169 va_start(arg_ptr, fmt);
170 vfprintf(stdout, fmt, arg_ptr);
174 const char *res_to_str(int rcode)
176 if (rcode < r_first || rcode > r_last) {
177 return _("***UNKNOWN***");
179 return resources[rcode-r_first].name;
185 * Initialize the static structure to zeros, then
186 * apply all the default values.
188 static void init_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
191 int rindex = type - r_first;
193 memset(config->m_res_all, 0, config->m_res_all_size);
194 res_all.hdr.rcode = type;
195 res_all.hdr.refcnt = 1;
197 /* Set defaults in each item */
198 for (i=0; items[i].name; i++) {
199 Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name,
200 (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
201 items[i].default_value);
202 if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) {
203 if (items[i].handler == store_bit) {
204 *(uint32_t *)(items[i].value) |= items[i].code;
205 } else if (items[i].handler == store_bool) {
206 *(bool *)(items[i].value) = items[i].default_value != 0;
207 } else if (items[i].handler == store_pint32 ||
208 items[i].handler == store_int32 ||
209 items[i].handler == store_size32) {
210 *(uint32_t *)(items[i].value) = items[i].default_value;
211 } else if (items[i].handler == store_int64) {
212 *(int64_t *)(items[i].value) = items[i].default_value;
213 } else if (items[i].handler == store_size64) {
214 *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
215 } else if (items[i].handler == store_speed) {
216 *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
217 } else if (items[i].handler == store_time) {
218 *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
219 } else if (pass == 1 && items[i].handler == store_addresses) {
220 init_default_addresses((dlist**)items[i].value, items[i].default_value);
223 /* If this triggers, take a look at lib/parse_conf.h */
224 if (i >= MAX_RES_ITEMS) {
225 Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
231 /* Store Messages Destination information */
232 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
239 Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
241 switch (item->code) {
244 case MD_SYSLOG: /* syslog */
247 scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
249 case MD_OPERATOR: /* send to operator */
250 case MD_DIRECTOR: /* send to Director */
251 case MD_MAIL: /* mail */
252 case MD_MAIL_ON_ERROR: /* mail if Job errors */
253 case MD_MAIL_ON_SUCCESS: /* mail if Job succeeds */
254 if (item->code == MD_OPERATOR) {
255 cmd = res_all.res_msgs.operator_cmd;
257 cmd = res_all.res_msgs.mail_cmd;
259 dest = get_pool_memory(PM_MESSAGE);
262 /* Pick up comma separated list of destinations */
264 token = lex_get_token(lc, T_NAME); /* scan destination */
265 dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
267 pm_strcat(dest, " "); /* separate multiple destinations with space */
270 pm_strcat(dest, lc->str);
271 dest_len += lc->str_len;
272 Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
273 token = lex_get_token(lc, T_SKIP_EOL);
274 if (token == T_COMMA) {
275 continue; /* get another destination */
277 if (token != T_EQUALS) {
278 scan_err1(lc, _("expected an =, got: %s"), lc->str);
283 Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
284 scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
285 free_pool_memory(dest);
286 Dmsg0(900, "done with dest codes\n");
289 case MD_FILE: /* file */
290 case MD_APPEND: /* append */
291 dest = get_pool_memory(PM_MESSAGE);
292 /* Pick up a single destination */
293 token = lex_get_token(lc, T_NAME); /* scan destination */
294 pm_strcpy(dest, lc->str);
295 dest_len = lc->str_len;
296 token = lex_get_token(lc, T_SKIP_EOL);
297 Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
298 if (token != T_EQUALS) {
299 scan_err1(lc, _("expected an =, got: %s"), lc->str);
302 scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
303 free_pool_memory(dest);
304 Dmsg0(900, "done with dest codes\n");
308 scan_err1(lc, _("Unknown item code: %d\n"), item->code);
313 set_bit(index, res_all.hdr.item_present);
314 Dmsg0(900, "Done store_msgs\n");
318 * Scan for message types and add them to the message
319 * destination. The basic job here is to connect message types
320 * (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
321 * destination (MAIL, FILE, OPERATOR, ...)
323 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
331 lex_get_token(lc, T_NAME); /* expect at least one type */
333 if (lc->str[0] == '!') {
340 for (i=0; msg_types[i].name; i++) {
341 if (strcasecmp(str, msg_types[i].name) == 0) {
342 msg_type = msg_types[i].token;
348 scan_err1(lc, _("message type: %s not found"), str);
352 if (msg_type == M_MAX+1) { /* all? */
353 for (i=1; i<=M_MAX; i++) { /* yes set all types */
354 add_msg_dest(msg, dest_code, i, where, cmd);
357 rem_msg_dest(msg, dest_code, msg_type, where);
359 add_msg_dest(msg, dest_code, msg_type, where, cmd);
364 Dmsg0(900, "call lex_get_token() to eat comma\n");
365 lex_get_token(lc, T_ALL); /* eat comma */
367 Dmsg0(900, "Done scan_types()\n");
372 * This routine is ONLY for resource names
373 * Store a name at specified address.
375 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
377 POOLMEM *msg = get_pool_memory(PM_EMSG);
378 lex_get_token(lc, T_NAME);
379 if (!is_name_valid(lc->str, &msg)) {
380 scan_err1(lc, "%s\n", msg);
383 free_pool_memory(msg);
384 /* Store the name both pass 1 and pass 2 */
385 if (*(item->value)) {
386 scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."),
387 *(item->value), lc->str);
390 *(item->value) = bstrdup(lc->str);
392 set_bit(index, res_all.hdr.item_present);
397 * Store a name string at specified address
398 * A name string is limited to MAX_RES_NAME_LENGTH
400 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
402 lex_get_token(lc, T_NAME);
405 *(item->value) = bstrdup(lc->str);
408 set_bit(index, res_all.hdr.item_present);
411 /* Store a string at specified address */
412 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
414 lex_get_token(lc, T_STRING);
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(lc->str));
434 *(item->value) = bstrdup(lc->str);
437 set_bit(index, res_all.hdr.item_present);
441 /* Store a password specified address in MD5 coding */
442 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
445 struct MD5Context md5c;
446 unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
450 lex_get_token(lc, T_STRING);
453 MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
454 MD5Final(digest, &md5c);
455 for (i = j = 0; i < sizeof(digest); i++) {
456 sprintf(&sig[j], "%02x", digest[i]);
459 *(item->value) = bstrdup(sig);
462 set_bit(index, res_all.hdr.item_present);
466 /* Store a resource at specified address.
467 * If we are in pass 2, do a lookup of the
470 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
474 lex_get_token(lc, T_NAME);
476 res = GetResWithName(item->code, lc->str);
478 scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
479 lc->str, lc->line_no, lc->line);
482 if (*(item->value)) {
483 scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
484 item->name, lc->line_no, lc->line);
487 *(item->value) = (char *)res;
490 set_bit(index, res_all.hdr.item_present);
494 * Store a resource pointer in an alist. default_value indicates how many
495 * times this routine can be called -- i.e. how many alists
497 * If we are in pass 2, do a lookup of the
500 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
503 int count = item->default_value;
508 if (count == 0) { /* always store in item->value */
510 if ((item->value)[i] == NULL) {
511 list = New(alist(10, not_owned_by_alist));
513 list = (alist *)(item->value)[i];
516 /* Find empty place to store this directive */
517 while ((item->value)[i] != NULL && i++ < count) { }
519 scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
520 lc->str, count, lc->line_no, lc->line);
523 list = New(alist(10, not_owned_by_alist));
527 lex_get_token(lc, T_NAME); /* scan next item */
528 res = GetResWithName(item->code, lc->str);
530 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
531 item->name, lc->line_no, lc->line);
534 Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
535 res, list, list->size(), i, item->name);
537 (item->value)[i] = (char *)list;
538 if (lc->ch != ',') { /* if no other item follows */
541 lex_get_token(lc, T_ALL); /* eat comma */
545 set_bit(index, res_all.hdr.item_present);
550 * Store a string in an alist.
552 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
557 if (*(item->value) == NULL) {
558 list = New(alist(10, owned_by_alist));
560 list = (alist *)(*(item->value));
563 lex_get_token(lc, T_STRING); /* scan next item */
564 Dmsg4(900, "Append %s to alist %p size=%d %s\n",
565 lc->str, list, list->size(), item->name);
566 list->append(bstrdup(lc->str));
567 *(item->value) = (char *)list;
570 set_bit(index, res_all.hdr.item_present);
576 * Store default values for Resource from xxxDefs
577 * If we are in pass 2, do a lookup of the
578 * resource and store everything not explicitly set
581 * Note, here item points to the main resource (e.g. Job, not
582 * the jobdefs, which we look up).
584 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
588 lex_get_token(lc, T_NAME);
590 Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
591 res = GetResWithName(item->code, lc->str);
593 scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
594 lc->str, lc->line_no, lc->line);
603 /* Store an integer at specified address */
604 void store_int32(LEX *lc, RES_ITEM *item, int index, int pass)
606 lex_get_token(lc, T_INT32);
607 *(uint32_t *)(item->value) = lc->int32_val;
609 set_bit(index, res_all.hdr.item_present);
612 /* Store a positive integer at specified address */
613 void store_pint32(LEX *lc, RES_ITEM *item, int index, int pass)
615 lex_get_token(lc, T_PINT32);
616 *(uint32_t *)(item->value) = lc->pint32_val;
618 set_bit(index, res_all.hdr.item_present);
622 /* Store an 64 bit integer at specified address */
623 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
625 lex_get_token(lc, T_INT64);
626 *(int64_t *)(item->value) = lc->int64_val;
628 set_bit(index, res_all.hdr.item_present);
631 enum store_unit_type {
636 /* Store a size in bytes */
637 static void store_int_unit(LEX *lc, RES_ITEM *item, int index, int pass,
638 bool size32, enum store_unit_type type)
644 Dmsg0(900, "Enter store_unit\n");
645 token = lex_get_token(lc, T_SKIP_EOL);
650 case T_UNQUOTED_STRING:
651 bstrncpy(bsize, lc->str, sizeof(bsize)); /* save first part */
652 /* if terminated by space, scan and get modifier */
653 while (lc->ch == ' ') {
654 token = lex_get_token(lc, T_ALL);
658 case T_UNQUOTED_STRING:
659 bstrncat(bsize, lc->str, sizeof(bsize));
663 if (type == STORE_SIZE) {
664 if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
665 scan_err1(lc, _("expected a size number, got: %s"), lc->str);
669 if (!speed_to_uint64(bsize, strlen(bsize), &uvalue)) {
670 scan_err1(lc, _("expected a speed number, got: %s"), lc->str);
675 *(uint32_t *)(item->value) = (uint32_t)uvalue;
677 *(uint64_t *)(item->value) = uvalue;
681 scan_err2(lc, _("expected a %s, got: %s"),
682 (type == STORE_SIZE)?_("size"):_("speed"), lc->str);
685 if (token != T_EOL) {
688 set_bit(index, res_all.hdr.item_present);
689 Dmsg0(900, "Leave store_unit\n");
692 /* Store a size in bytes */
693 void store_size32(LEX *lc, RES_ITEM *item, int index, int pass)
695 store_int_unit(lc, item, index, pass, true /* 32 bit */, STORE_SIZE);
698 /* Store a size in bytes */
699 void store_size64(LEX *lc, RES_ITEM *item, int index, int pass)
701 store_int_unit(lc, item, index, pass, false /* not 32 bit */, STORE_SIZE);
704 /* Store a speed in bytes/s */
705 void store_speed(LEX *lc, RES_ITEM *item, int index, int pass)
707 store_int_unit(lc, item, index, pass, false /* 64 bit */, STORE_SPEED);
710 /* Store a time period in seconds */
711 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
717 token = lex_get_token(lc, T_SKIP_EOL);
722 case T_UNQUOTED_STRING:
723 bstrncpy(period, lc->str, sizeof(period)); /* get first part */
724 /* if terminated by space, scan and get modifier */
725 while (lc->ch == ' ') {
726 token = lex_get_token(lc, T_ALL);
730 case T_UNQUOTED_STRING:
731 bstrncat(period, lc->str, sizeof(period));
735 if (!duration_to_utime(period, &utime)) {
736 scan_err1(lc, _("expected a time period, got: %s"), period);
739 *(utime_t *)(item->value) = utime;
742 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
745 if (token != T_EOL) {
748 set_bit(index, res_all.hdr.item_present);
752 /* Store a yes/no in a bit field */
753 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
755 lex_get_token(lc, T_NAME);
756 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
757 *(uint32_t *)(item->value) |= item->code;
758 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
759 *(uint32_t *)(item->value) &= ~(item->code);
761 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
765 set_bit(index, res_all.hdr.item_present);
768 /* Store a bool in a bit field */
769 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
771 lex_get_token(lc, T_NAME);
772 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
773 *(bool *)(item->value) = true;
774 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
775 *(bool *)(item->value) = false;
777 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
781 set_bit(index, res_all.hdr.item_present);
786 * Store Tape Label Type (Bacula, ANSI, IBM)
789 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
793 lex_get_token(lc, T_NAME);
794 /* Store the label pass 2 so that type is defined */
795 for (i=0; tapelabels[i].name; i++) {
796 if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
797 *(uint32_t *)(item->value) = tapelabels[i].token;
803 scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
807 set_bit(index, res_all.hdr.item_present);
817 CONFIG *new_config_parser()
820 config = (CONFIG *)malloc(sizeof(CONFIG));
821 memset(config, 0, sizeof(CONFIG));
827 LEX_ERROR_HANDLER *scan_error,
830 int32_t res_all_size,
833 RES_TABLE *resources,
837 m_scan_error = scan_error;
838 m_err_type = err_type;
839 m_res_all = vres_all;
840 m_res_all_size = res_all_size;
843 m_resources = resources;
844 m_res_head = res_head;
847 /*********************************************************************
849 * Parse configuration file
851 * Return 0 if reading failed, 1 otherwise
852 * Note, the default behavior unless you have set an alternate
853 * scan_error handler is to die on an error.
857 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error, int err_type)
860 CONFIG *config = new_config_parser();
861 config->init(cf, scan_error, err_type, (void *)&res_all, res_all_size,
862 r_first, r_last, resources, res_head);
863 ok = config->parse_config();
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));
910 lc->scan_error = scan_error;
912 lex_set_default_error_handler(lc);
914 lex_set_error_handler_error_type(lc, err_type) ;
915 bstrncpy(lc->str, cf, sizeof(lc->str));
917 scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
918 lc->str, be.bstrerror());
922 lex_set_error_handler_error_type(lc, err_type) ;
923 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
924 Dmsg3(900, "parse state=%d pass=%d got token=%s\n", state, pass,
925 lex_tok_to_str(token));
928 if (token == T_EOL) {
930 } else if (token == T_UTF8_BOM) {
931 /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */
933 } else if (token == T_UTF16_BOM) {
934 scan_err0(lc, _("Currently we cannot handle UTF-16 source files. "
935 "Please convert the conf file to UTF-8\n"));
937 } else if (token != T_IDENTIFIER) {
938 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
941 for (i=0; resources[i].name; i++) {
942 if (strcasecmp(resources[i].name, lc->str) == 0) {
943 items = resources[i].items;
948 res_type = resources[i].rcode;
949 init_resource(this, res_type, items, pass);
953 if (state == p_none) {
954 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
965 scan_err1(lc, _("not in resource definition: %s"), lc->str);
968 for (i=0; items[i].name; i++) {
969 if (strcasecmp(items[i].name, lc->str) == 0) {
970 /* If the ITEM_NO_EQUALS flag is set we do NOT
971 * scan for = after the keyword */
972 if (!(items[i].flags & ITEM_NO_EQUALS)) {
973 token = lex_get_token(lc, T_SKIP_EOL);
974 Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
975 if (token != T_EQUALS) {
976 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
980 Dmsg1(800, "calling handler for %s\n", items[i].name);
981 /* Call item handler */
982 items[i].handler(lc, &items[i], i, pass);
988 Dmsg2(900, "level=%d id=%s\n", level, lc->str);
989 Dmsg1(900, "Keyword = %s\n", lc->str);
990 scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
991 "Perhaps you left the trailing brace off of the previous resource."), lc->str);
999 Dmsg0(900, "T_EOB => define new resource\n");
1000 if (res_all.hdr.name == NULL) {
1001 scan_err0(lc, _("Name not specified for resource"));
1004 save_resource(res_type, items, pass); /* save resource */
1011 scan_err2(lc, _("unexpected token %d %s in resource definition"),
1012 token, lex_tok_to_str(token));
1017 scan_err1(lc, _("Unknown parser state %d\n"), state);
1021 if (state != p_none) {
1022 scan_err0(lc, _("End of conf file reached with unclosed resource."));
1025 if (debug_level >= 900 && pass == 2) {
1027 for (i=m_r_first; i<=m_r_last; i++) {
1028 dump_resource(i, m_res_head[i-m_r_first], prtmsg, NULL);
1031 lc = lex_close_file(lc);
1033 Dmsg0(900, "Leave parse_config()\n");
1037 lc = lex_close_file(lc);
1042 const char *get_default_configdir()
1044 #if defined(HAVE_WIN32)
1046 static char szConfigDir[MAX_PATH + 1] = { 0 };
1048 if (!p_SHGetFolderPath) {
1049 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1053 if (szConfigDir[0] == '\0') {
1054 hr = p_SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szConfigDir);
1056 if (SUCCEEDED(hr)) {
1057 bstrncat(szConfigDir, "\\Bacula", sizeof(szConfigDir));
1059 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1069 * Returns false on error
1070 * true on OK, with full_path set to where config file should be
1073 find_config_file(const char *config_file, char *full_path, int max_path)
1075 int file_length = strlen(config_file) + 1;
1077 /* If a full path specified, use it */
1078 if (first_path_separator(config_file) != NULL) {
1079 if (file_length > max_path) {
1082 bstrncpy(full_path, config_file, file_length);
1086 /* config_file is default file name, now find default dir */
1087 const char *config_dir = get_default_configdir();
1088 int dir_length = strlen(config_dir);
1090 if ((dir_length + 1 + file_length) > max_path) {
1094 memcpy(full_path, config_dir, dir_length + 1);
1096 if (!IsPathSeparator(full_path[dir_length - 1])) {
1097 full_path[dir_length++] = '/';
1100 memcpy(&full_path[dir_length], config_file, file_length);
1105 /*********************************************************************
1107 * Free configuration resources
1110 void CONFIG::free_resources()
1112 for (int i=m_r_first; i<=m_r_last; i++) {
1113 free_resource(m_res_head[i-m_r_first], i);
1114 m_res_head[i-m_r_first] = NULL;
1118 RES **CONFIG::save_resources()
1120 int num = m_r_last - m_r_first + 1;
1121 RES **res = (RES **)malloc(num*sizeof(RES *));
1122 for (int i=0; i<num; i++) {
1123 res[i] = m_res_head[i];
1124 m_res_head[i] = NULL;
1129 RES **CONFIG::new_res_head()
1131 int size = (m_r_last - m_r_first + 1) * sizeof(RES *);
1132 RES **res = (RES **)malloc(size);
1133 memset(res, 0, size);
1139 void free_config_resources()
1141 for (int i=r_first; i<=r_last; i++) {
1142 free_resource(res_head[i-r_first], i);
1143 res_head[i-r_first] = NULL;
1147 RES **save_config_resources()
1149 int num = r_last - r_first + 1;
1150 RES **res = (RES **)malloc(num*sizeof(RES *));
1151 for (int i=0; i<num; i++) {
1152 res[i] = res_head[i];
1158 RES **new_res_head()
1160 int size = (r_last - r_first + 1) * sizeof(RES *);
1161 RES **res = (RES **)malloc(size);
1162 memset(res, 0, size);