2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2009 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
66 #if defined(HAVE_WIN32)
73 * Define the Union of all the common resource structure definitions.
81 // work around visual studio name mangling preventing external linkage since res_all
82 // is declared as a different type when instantiated.
83 extern "C" URES res_all;
88 extern brwlock_t res_lock; /* resource lock */
91 /* Forward referenced subroutines */
92 static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd);
93 static const char *get_default_configdir();
94 static bool find_config_file(const char *config_file, char *full_path, int max_path);
96 /* Common Resource definitions */
98 /* Message resource directives
99 * name handler value code flags default_value
101 RES_ITEM msgs_items[] = {
102 {"name", store_name, ITEM(res_msgs.hdr.name), 0, 0, 0},
103 {"description", store_str, ITEM(res_msgs.hdr.desc), 0, 0, 0},
104 {"mailcommand", store_str, ITEM(res_msgs.mail_cmd), 0, 0, 0},
105 {"operatorcommand", store_str, ITEM(res_msgs.operator_cmd), 0, 0, 0},
106 {"syslog", store_msgs, ITEM(res_msgs), MD_SYSLOG, 0, 0},
107 {"mail", store_msgs, ITEM(res_msgs), MD_MAIL, 0, 0},
108 {"mailonerror", store_msgs, ITEM(res_msgs), MD_MAIL_ON_ERROR, 0, 0},
109 {"mailonsuccess", store_msgs, ITEM(res_msgs), MD_MAIL_ON_SUCCESS, 0, 0},
110 {"file", store_msgs, ITEM(res_msgs), MD_FILE, 0, 0},
111 {"append", store_msgs, ITEM(res_msgs), MD_APPEND, 0, 0},
112 {"stdout", store_msgs, ITEM(res_msgs), MD_STDOUT, 0, 0},
113 {"stderr", store_msgs, ITEM(res_msgs), MD_STDERR, 0, 0},
114 {"director", store_msgs, ITEM(res_msgs), MD_DIRECTOR, 0, 0},
115 {"console", store_msgs, ITEM(res_msgs), MD_CONSOLE, 0, 0},
116 {"operator", store_msgs, ITEM(res_msgs), MD_OPERATOR, 0, 0},
117 {"catalog", store_msgs, ITEM(res_msgs), MD_CATALOG, 0, 0},
118 {NULL, NULL, {0}, 0, 0, 0}
125 /* Various message types */
126 static struct s_mtypes msg_types[] = {
131 {"warning", M_WARNING},
134 {"notsaved", M_NOTSAVED},
135 {"skipped", M_SKIPPED},
137 {"terminate", M_TERM},
138 {"restored", M_RESTORED},
139 {"security", M_SECURITY},
141 {"volmgmt", M_VOLMGMT},
146 /* Used for certain KeyWord tables */
153 * Tape Label types permitted in Pool records
155 * tape label label code = token
157 static s_kw tapelabels[] = {
158 {"bacula", B_BACULA_LABEL},
159 {"ansi", B_ANSI_LABEL},
160 {"ibm", B_IBM_LABEL},
165 /* Simply print a message */
166 static void prtmsg(void *sock, const char *fmt, ...)
170 va_start(arg_ptr, fmt);
171 vfprintf(stdout, fmt, arg_ptr);
175 const char *res_to_str(int rcode)
177 if (rcode < r_first || rcode > r_last) {
178 return _("***UNKNOWN***");
180 return resources[rcode-r_first].name;
186 * Initialize the static structure to zeros, then
187 * apply all the default values.
189 static void init_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
192 int rindex = type - r_first;
194 memset(config->m_res_all, 0, config->m_res_all_size);
195 res_all.hdr.rcode = type;
196 res_all.hdr.refcnt = 1;
198 /* Set defaults in each item */
199 for (i=0; items[i].name; i++) {
200 Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name,
201 (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
202 items[i].default_value);
203 if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) {
204 if (items[i].handler == store_bit) {
205 *(uint32_t *)(items[i].value) |= items[i].code;
206 } else if (items[i].handler == store_bool) {
207 *(bool *)(items[i].value) = items[i].default_value != 0;
208 } else if (items[i].handler == store_pint32 ||
209 items[i].handler == store_int32 ||
210 items[i].handler == store_size32) {
211 *(uint32_t *)(items[i].value) = items[i].default_value;
212 } else if (items[i].handler == store_int64) {
213 *(int64_t *)(items[i].value) = items[i].default_value;
214 } else if (items[i].handler == store_size64) {
215 *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
216 } else if (items[i].handler == store_speed) {
217 *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
218 } else if (items[i].handler == store_time) {
219 *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
220 } else if (pass == 1 && items[i].handler == store_addresses) {
221 init_default_addresses((dlist**)items[i].value, items[i].default_value);
224 /* If this triggers, take a look at lib/parse_conf.h */
225 if (i >= MAX_RES_ITEMS) {
226 Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
232 /* Store Messages Destination information */
233 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
240 Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
242 switch (item->code) {
245 case MD_SYSLOG: /* syslog */
248 scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
250 case MD_OPERATOR: /* send to operator */
251 case MD_DIRECTOR: /* send to Director */
252 case MD_MAIL: /* mail */
253 case MD_MAIL_ON_ERROR: /* mail if Job errors */
254 case MD_MAIL_ON_SUCCESS: /* mail if Job succeeds */
255 if (item->code == MD_OPERATOR) {
256 cmd = res_all.res_msgs.operator_cmd;
258 cmd = res_all.res_msgs.mail_cmd;
260 dest = get_pool_memory(PM_MESSAGE);
263 /* Pick up comma separated list of destinations */
265 token = lex_get_token(lc, T_NAME); /* scan destination */
266 dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
268 pm_strcat(dest, " "); /* separate multiple destinations with space */
271 pm_strcat(dest, lc->str);
272 dest_len += lc->str_len;
273 Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
274 token = lex_get_token(lc, T_SKIP_EOL);
275 if (token == T_COMMA) {
276 continue; /* get another destination */
278 if (token != T_EQUALS) {
279 scan_err1(lc, _("expected an =, got: %s"), lc->str);
284 Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
285 scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
286 free_pool_memory(dest);
287 Dmsg0(900, "done with dest codes\n");
290 case MD_FILE: /* file */
291 case MD_APPEND: /* append */
292 dest = get_pool_memory(PM_MESSAGE);
293 /* Pick up a single destination */
294 token = lex_get_token(lc, T_NAME); /* scan destination */
295 pm_strcpy(dest, lc->str);
296 dest_len = lc->str_len;
297 token = lex_get_token(lc, T_SKIP_EOL);
298 Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
299 if (token != T_EQUALS) {
300 scan_err1(lc, _("expected an =, got: %s"), lc->str);
303 scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
304 free_pool_memory(dest);
305 Dmsg0(900, "done with dest codes\n");
309 scan_err1(lc, _("Unknown item code: %d\n"), item->code);
314 set_bit(index, res_all.hdr.item_present);
315 Dmsg0(900, "Done store_msgs\n");
319 * Scan for message types and add them to the message
320 * destination. The basic job here is to connect message types
321 * (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
322 * destination (MAIL, FILE, OPERATOR, ...)
324 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
332 lex_get_token(lc, T_NAME); /* expect at least one type */
334 if (lc->str[0] == '!') {
341 for (i=0; msg_types[i].name; i++) {
342 if (strcasecmp(str, msg_types[i].name) == 0) {
343 msg_type = msg_types[i].token;
349 scan_err1(lc, _("message type: %s not found"), str);
353 if (msg_type == M_MAX+1) { /* all? */
354 for (i=1; i<=M_MAX; i++) { /* yes set all types */
355 add_msg_dest(msg, dest_code, i, where, cmd);
358 rem_msg_dest(msg, dest_code, msg_type, where);
360 add_msg_dest(msg, dest_code, msg_type, where, cmd);
365 Dmsg0(900, "call lex_get_token() to eat comma\n");
366 lex_get_token(lc, T_ALL); /* eat comma */
368 Dmsg0(900, "Done scan_types()\n");
373 * This routine is ONLY for resource names
374 * Store a name at specified address.
376 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
378 POOLMEM *msg = get_pool_memory(PM_EMSG);
379 lex_get_token(lc, T_NAME);
380 if (!is_name_valid(lc->str, &msg)) {
381 scan_err1(lc, "%s\n", msg);
384 free_pool_memory(msg);
385 /* Store the name both pass 1 and pass 2 */
386 if (*(item->value)) {
387 scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."),
388 *(item->value), lc->str);
391 *(item->value) = bstrdup(lc->str);
393 set_bit(index, res_all.hdr.item_present);
398 * Store a name string at specified address
399 * A name string is limited to MAX_RES_NAME_LENGTH
401 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
403 lex_get_token(lc, T_NAME);
406 *(item->value) = bstrdup(lc->str);
409 set_bit(index, res_all.hdr.item_present);
412 /* Store a string at specified address */
413 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
415 lex_get_token(lc, T_STRING);
417 *(item->value) = bstrdup(lc->str);
420 set_bit(index, res_all.hdr.item_present);
424 * Store a directory name at specified address. Note, we do
425 * shell expansion except if the string begins with a vertical
426 * bar (i.e. it will likely be passed to the shell later).
428 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
430 lex_get_token(lc, T_STRING);
432 if (lc->str[0] != '|') {
433 do_shell_expansion(lc->str, sizeof(lc->str));
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 *(item->value) = bstrdup(sig);
463 set_bit(index, res_all.hdr.item_present);
467 /* Store a resource at specified address.
468 * If we are in pass 2, do a lookup of the
471 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
475 lex_get_token(lc, T_NAME);
477 res = GetResWithName(item->code, lc->str);
479 scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
480 lc->str, lc->line_no, lc->line);
483 if (*(item->value)) {
484 scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
485 item->name, lc->line_no, lc->line);
488 *(item->value) = (char *)res;
491 set_bit(index, res_all.hdr.item_present);
495 * Store a resource pointer in an alist. default_value indicates how many
496 * times this routine can be called -- i.e. how many alists
498 * If we are in pass 2, do a lookup of the
501 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
504 int count = item->default_value;
509 if (count == 0) { /* always store in item->value */
511 if ((item->value)[i] == NULL) {
512 list = New(alist(10, not_owned_by_alist));
514 list = (alist *)(item->value)[i];
517 /* Find empty place to store this directive */
518 while ((item->value)[i] != NULL && i++ < count) { }
520 scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
521 lc->str, count, lc->line_no, lc->line);
524 list = New(alist(10, not_owned_by_alist));
528 lex_get_token(lc, T_NAME); /* scan next item */
529 res = GetResWithName(item->code, lc->str);
531 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
532 item->name, lc->line_no, lc->line);
535 Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
536 res, list, list->size(), i, item->name);
538 (item->value)[i] = (char *)list;
539 if (lc->ch != ',') { /* if no other item follows */
542 lex_get_token(lc, T_ALL); /* eat comma */
546 set_bit(index, res_all.hdr.item_present);
551 * Store a string in an alist.
553 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
558 if (*(item->value) == NULL) {
559 list = New(alist(10, owned_by_alist));
561 list = (alist *)(*(item->value));
564 lex_get_token(lc, T_STRING); /* scan next item */
565 Dmsg4(900, "Append %s to alist %p size=%d %s\n",
566 lc->str, list, list->size(), item->name);
567 list->append(bstrdup(lc->str));
568 *(item->value) = (char *)list;
571 set_bit(index, res_all.hdr.item_present);
577 * Store default values for Resource from xxxDefs
578 * If we are in pass 2, do a lookup of the
579 * resource and store everything not explicitly set
582 * Note, here item points to the main resource (e.g. Job, not
583 * the jobdefs, which we look up).
585 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
589 lex_get_token(lc, T_NAME);
591 Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
592 res = GetResWithName(item->code, lc->str);
594 scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
595 lc->str, lc->line_no, lc->line);
604 /* Store an integer at specified address */
605 void store_int32(LEX *lc, RES_ITEM *item, int index, int pass)
607 lex_get_token(lc, T_INT32);
608 *(uint32_t *)(item->value) = lc->int32_val;
610 set_bit(index, res_all.hdr.item_present);
613 /* Store a positive integer at specified address */
614 void store_pint32(LEX *lc, RES_ITEM *item, int index, int pass)
616 lex_get_token(lc, T_PINT32);
617 *(uint32_t *)(item->value) = lc->pint32_val;
619 set_bit(index, res_all.hdr.item_present);
623 /* Store an 64 bit integer at specified address */
624 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
626 lex_get_token(lc, T_INT64);
627 *(int64_t *)(item->value) = lc->int64_val;
629 set_bit(index, res_all.hdr.item_present);
632 enum store_unit_type {
637 /* Store a size in bytes */
638 static void store_int_unit(LEX *lc, RES_ITEM *item, int index, int pass,
639 bool size32, enum store_unit_type type)
645 Dmsg0(900, "Enter store_unit\n");
646 token = lex_get_token(lc, T_SKIP_EOL);
651 case T_UNQUOTED_STRING:
652 bstrncpy(bsize, lc->str, sizeof(bsize)); /* save first part */
653 /* if terminated by space, scan and get modifier */
654 while (lc->ch == ' ') {
655 token = lex_get_token(lc, T_ALL);
659 case T_UNQUOTED_STRING:
660 bstrncat(bsize, lc->str, sizeof(bsize));
664 if (type == STORE_SIZE) {
665 if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
666 scan_err1(lc, _("expected a size number, got: %s"), lc->str);
670 if (!speed_to_uint64(bsize, strlen(bsize), &uvalue)) {
671 scan_err1(lc, _("expected a speed number, got: %s"), lc->str);
676 *(uint32_t *)(item->value) = (uint32_t)uvalue;
678 *(uint64_t *)(item->value) = uvalue;
682 scan_err2(lc, _("expected a %s, got: %s"),
683 (type == STORE_SIZE)?_("size"):_("speed"), lc->str);
686 if (token != T_EOL) {
689 set_bit(index, res_all.hdr.item_present);
690 Dmsg0(900, "Leave store_unit\n");
693 /* Store a size in bytes */
694 void store_size32(LEX *lc, RES_ITEM *item, int index, int pass)
696 store_int_unit(lc, item, index, pass, true /* 32 bit */, STORE_SIZE);
699 /* Store a size in bytes */
700 void store_size64(LEX *lc, RES_ITEM *item, int index, int pass)
702 store_int_unit(lc, item, index, pass, false /* not 32 bit */, STORE_SIZE);
705 /* Store a speed in bytes/s */
706 void store_speed(LEX *lc, RES_ITEM *item, int index, int pass)
708 store_int_unit(lc, item, index, pass, false /* 64 bit */, STORE_SPEED);
711 /* Store a time period in seconds */
712 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
718 token = lex_get_token(lc, T_SKIP_EOL);
723 case T_UNQUOTED_STRING:
724 bstrncpy(period, lc->str, sizeof(period)); /* get first part */
725 /* if terminated by space, scan and get modifier */
726 while (lc->ch == ' ') {
727 token = lex_get_token(lc, T_ALL);
731 case T_UNQUOTED_STRING:
732 bstrncat(period, lc->str, sizeof(period));
736 if (!duration_to_utime(period, &utime)) {
737 scan_err1(lc, _("expected a time period, got: %s"), period);
740 *(utime_t *)(item->value) = utime;
743 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
746 if (token != T_EOL) {
749 set_bit(index, res_all.hdr.item_present);
753 /* Store a yes/no in a bit field */
754 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
756 lex_get_token(lc, T_NAME);
757 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
758 *(uint32_t *)(item->value) |= item->code;
759 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
760 *(uint32_t *)(item->value) &= ~(item->code);
762 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
766 set_bit(index, res_all.hdr.item_present);
769 /* Store a bool in a bit field */
770 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
772 lex_get_token(lc, T_NAME);
773 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
774 *(bool *)(item->value) = true;
775 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
776 *(bool *)(item->value) = false;
778 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
782 set_bit(index, res_all.hdr.item_present);
787 * Store Tape Label Type (Bacula, ANSI, IBM)
790 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
794 token = lex_get_token(lc, T_NAME);
795 /* Store the label pass 2 so that type is defined */
796 for (i=0; tapelabels[i].name; i++) {
797 if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
798 *(uint32_t *)(item->value) = tapelabels[i].token;
804 scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
808 set_bit(index, res_all.hdr.item_present);
818 CONFIG *new_config_parser()
821 config = (CONFIG *)malloc(sizeof(CONFIG));
822 memset(config, 0, sizeof(CONFIG));
828 LEX_ERROR_HANDLER *scan_error,
831 int32_t res_all_size,
834 RES_TABLE *resources,
838 m_scan_error = scan_error;
839 m_err_type = err_type;
840 m_res_all = vres_all;
841 m_res_all_size = res_all_size;
844 m_resources = resources;
845 m_res_head = res_head;
848 /*********************************************************************
850 * Parse configuration file
852 * Return 0 if reading failed, 1 otherwise
853 * Note, the default behavior unless you have set an alternate
854 * scan_error handler is to die on an error.
858 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error, int err_type)
861 CONFIG *config = new_config_parser();
862 config->init(cf, scan_error, err_type, (void *)&res_all, res_all_size,
863 r_first, r_last, resources, res_head);
864 ok = config->parse_config();
871 bool CONFIG::parse_config()
876 enum parse_state state = p_none;
877 RES_ITEM *items = NULL;
879 static bool first = true;
881 const char *cf = m_cf;
882 LEX_ERROR_HANDLER *scan_error = m_scan_error;
883 int err_type = m_err_type;
885 if (first && (errstat=rwl_init(&res_lock)) != 0) {
887 Jmsg1(NULL, M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
888 be.bstrerror(errstat));
892 char *full_path = (char *)alloca(MAX_PATH + 1);
894 if (!find_config_file(cf, full_path, MAX_PATH +1)) {
895 Jmsg0(NULL, M_ABORT, 0, _("Config filename too long.\n"));
899 /* Make two passes. The first builds the name symbol table,
900 * and the second picks up the items.
902 Dmsg0(900, "Enter parse_config()\n");
903 for (pass=1; pass <= 2; pass++) {
904 Dmsg1(900, "parse_config pass %d\n", pass);
905 if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
907 /* We must create a lex packet to print the error */
908 lc = (LEX *)malloc(sizeof(LEX));
909 memset(lc, 0, sizeof(LEX));
911 lc->scan_error = scan_error;
913 lex_set_default_error_handler(lc);
915 lex_set_error_handler_error_type(lc, err_type) ;
916 bstrncpy(lc->str, cf, sizeof(lc->str));
918 scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
919 lc->str, be.bstrerror());
923 lex_set_error_handler_error_type(lc, err_type) ;
924 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
925 Dmsg3(900, "parse state=%d pass=%d got token=%s\n", state, pass,
926 lex_tok_to_str(token));
929 if (token == T_EOL) {
931 } else if (token == T_UTF8_BOM) {
932 /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */
934 } else if (token == T_UTF16_BOM) {
935 scan_err0(lc, _("Currently we cannot handle UTF-16 source files. "
936 "Please convert the conf file to UTF-8\n"));
938 } else if (token != T_IDENTIFIER) {
939 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
942 for (i=0; resources[i].name; i++) {
943 if (strcasecmp(resources[i].name, lc->str) == 0) {
944 items = resources[i].items;
949 res_type = resources[i].rcode;
950 init_resource(this, res_type, items, pass);
954 if (state == p_none) {
955 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
966 scan_err1(lc, _("not in resource definition: %s"), lc->str);
969 for (i=0; items[i].name; i++) {
970 if (strcasecmp(items[i].name, lc->str) == 0) {
971 /* If the ITEM_NO_EQUALS flag is set we do NOT
972 * scan for = after the keyword */
973 if (!(items[i].flags & ITEM_NO_EQUALS)) {
974 token = lex_get_token(lc, T_SKIP_EOL);
975 Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
976 if (token != T_EQUALS) {
977 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
981 Dmsg1(800, "calling handler for %s\n", items[i].name);
982 /* Call item handler */
983 items[i].handler(lc, &items[i], i, pass);
989 Dmsg2(900, "level=%d id=%s\n", level, lc->str);
990 Dmsg1(900, "Keyword = %s\n", lc->str);
991 scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
992 "Perhaps you left the trailing brace off of the previous resource."), lc->str);
1000 Dmsg0(900, "T_EOB => define new resource\n");
1001 if (res_all.hdr.name == NULL) {
1002 scan_err0(lc, _("Name not specified for resource"));
1005 save_resource(res_type, items, pass); /* save resource */
1012 scan_err2(lc, _("unexpected token %d %s in resource definition"),
1013 token, lex_tok_to_str(token));
1018 scan_err1(lc, _("Unknown parser state %d\n"), state);
1022 if (state != p_none) {
1023 scan_err0(lc, _("End of conf file reached with unclosed resource."));
1026 if (debug_level >= 900 && pass == 2) {
1028 for (i=m_r_first; i<=m_r_last; i++) {
1029 dump_resource(i, m_res_head[i-m_r_first], prtmsg, NULL);
1032 lc = lex_close_file(lc);
1034 Dmsg0(900, "Leave parse_config()\n");
1038 lc = lex_close_file(lc);
1043 const char *get_default_configdir()
1045 #if defined(HAVE_WIN32)
1047 static char szConfigDir[MAX_PATH + 1] = { 0 };
1049 if (!p_SHGetFolderPath) {
1050 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1054 if (szConfigDir[0] == '\0') {
1055 hr = p_SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szConfigDir);
1057 if (SUCCEEDED(hr)) {
1058 bstrncat(szConfigDir, "\\Bacula", sizeof(szConfigDir));
1060 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1070 * Returns false on error
1071 * true on OK, with full_path set to where config file should be
1074 find_config_file(const char *config_file, char *full_path, int max_path)
1076 int file_length = strlen(config_file) + 1;
1078 /* If a full path specified, use it */
1079 if (first_path_separator(config_file) != NULL) {
1080 if (file_length > max_path) {
1083 bstrncpy(full_path, config_file, file_length);
1087 /* config_file is default file name, now find default dir */
1088 const char *config_dir = get_default_configdir();
1089 int dir_length = strlen(config_dir);
1091 if ((dir_length + 1 + file_length) > max_path) {
1095 memcpy(full_path, config_dir, dir_length + 1);
1097 if (!IsPathSeparator(full_path[dir_length - 1])) {
1098 full_path[dir_length++] = '/';
1101 memcpy(&full_path[dir_length], config_file, file_length);
1106 /*********************************************************************
1108 * Free configuration resources
1111 void CONFIG::free_resources()
1113 for (int i=m_r_first; i<=m_r_last; i++) {
1114 free_resource(m_res_head[i-m_r_first], i);
1115 m_res_head[i-m_r_first] = NULL;
1119 RES **CONFIG::save_resources()
1121 int num = m_r_last - m_r_first + 1;
1122 RES **res = (RES **)malloc(num*sizeof(RES *));
1123 for (int i=0; i<num; i++) {
1124 res[i] = m_res_head[i];
1125 m_res_head[i] = NULL;
1130 RES **CONFIG::new_res_head()
1132 int size = (m_r_last - m_r_first + 1) * sizeof(RES *);
1133 RES **res = (RES **)malloc(size);
1134 memset(res, 0, size);
1140 void free_config_resources()
1142 for (int i=r_first; i<=r_last; i++) {
1143 free_resource(res_head[i-r_first], i);
1144 res_head[i-r_first] = NULL;
1148 RES **save_config_resources()
1150 int num = r_last - r_first + 1;
1151 RES **res = (RES **)malloc(num*sizeof(RES *));
1152 for (int i=0; i<num; i++) {
1153 res[i] = res_head[i];
1159 RES **new_res_head()
1161 int size = (r_last - r_first + 1) * sizeof(RES *);
1162 RES **res = (RES **)malloc(size);
1163 memset(res, 0, size);