2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 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 two of the GNU 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 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 John Walker.
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 *(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_size) {
214 *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
215 } else if (items[i].handler == store_time) {
216 *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
217 } else if (pass == 1 && items[i].handler == store_addresses) {
218 init_default_addresses((dlist**)items[i].value, items[i].default_value);
221 /* If this triggers, take a look at lib/parse_conf.h */
222 if (i >= MAX_RES_ITEMS) {
223 Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
229 /* Store Messages Destination information */
230 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
237 Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
239 switch (item->code) {
242 case MD_SYSLOG: /* syslog */
245 scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
247 case MD_OPERATOR: /* send to operator */
248 case MD_DIRECTOR: /* send to Director */
249 case MD_MAIL: /* mail */
250 case MD_MAIL_ON_ERROR: /* mail if Job errors */
251 case MD_MAIL_ON_SUCCESS: /* mail if Job succeeds */
252 if (item->code == MD_OPERATOR) {
253 cmd = res_all.res_msgs.operator_cmd;
255 cmd = res_all.res_msgs.mail_cmd;
257 dest = get_pool_memory(PM_MESSAGE);
260 /* Pick up comma separated list of destinations */
262 token = lex_get_token(lc, T_NAME); /* scan destination */
263 dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
265 pm_strcat(dest, " "); /* separate multiple destinations with space */
268 pm_strcat(dest, lc->str);
269 dest_len += lc->str_len;
270 Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
271 token = lex_get_token(lc, T_SKIP_EOL);
272 if (token == T_COMMA) {
273 continue; /* get another destination */
275 if (token != T_EQUALS) {
276 scan_err1(lc, _("expected an =, got: %s"), lc->str);
280 Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
281 scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
282 free_pool_memory(dest);
283 Dmsg0(900, "done with dest codes\n");
286 case MD_FILE: /* file */
287 case MD_APPEND: /* append */
288 dest = get_pool_memory(PM_MESSAGE);
289 /* Pick up a single destination */
290 token = lex_get_token(lc, T_NAME); /* scan destination */
291 pm_strcpy(dest, lc->str);
292 dest_len = lc->str_len;
293 token = lex_get_token(lc, T_SKIP_EOL);
294 Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
295 if (token != T_EQUALS) {
296 scan_err1(lc, _("expected an =, got: %s"), lc->str);
298 scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
299 free_pool_memory(dest);
300 Dmsg0(900, "done with dest codes\n");
304 scan_err1(lc, _("Unknown item code: %d\n"), item->code);
309 set_bit(index, res_all.hdr.item_present);
310 Dmsg0(900, "Done store_msgs\n");
314 * Scan for message types and add them to the message
315 * destination. The basic job here is to connect message types
316 * (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
317 * destination (MAIL, FILE, OPERATOR, ...)
319 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
327 lex_get_token(lc, T_NAME); /* expect at least one type */
329 if (lc->str[0] == '!') {
336 for (i=0; msg_types[i].name; i++) {
337 if (strcasecmp(str, msg_types[i].name) == 0) {
338 msg_type = msg_types[i].token;
344 scan_err1(lc, _("message type: %s not found"), str);
348 if (msg_type == M_MAX+1) { /* all? */
349 for (i=1; i<=M_MAX; i++) { /* yes set all types */
350 add_msg_dest(msg, dest_code, i, where, cmd);
353 rem_msg_dest(msg, dest_code, msg_type, where);
355 add_msg_dest(msg, dest_code, msg_type, where, cmd);
360 Dmsg0(900, "call lex_get_token() to eat comma\n");
361 lex_get_token(lc, T_ALL); /* eat comma */
363 Dmsg0(900, "Done scan_types()\n");
368 * This routine is ONLY for resource names
369 * Store a name at specified address.
371 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
373 POOLMEM *msg = get_pool_memory(PM_EMSG);
374 lex_get_token(lc, T_NAME);
375 if (!is_name_valid(lc->str, &msg)) {
376 scan_err1(lc, "%s\n", msg);
378 free_pool_memory(msg);
379 /* Store the name both pass 1 and pass 2 */
380 if (*(item->value)) {
381 scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."),
382 *(item->value), lc->str);
384 *(item->value) = bstrdup(lc->str);
386 set_bit(index, res_all.hdr.item_present);
391 * Store a name string at specified address
392 * A name string is limited to MAX_RES_NAME_LENGTH
394 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
396 lex_get_token(lc, T_NAME);
399 *(item->value) = bstrdup(lc->str);
402 set_bit(index, res_all.hdr.item_present);
405 /* Store a string at specified address */
406 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
408 lex_get_token(lc, T_STRING);
410 *(item->value) = bstrdup(lc->str);
413 set_bit(index, res_all.hdr.item_present);
417 * Store a directory name at specified address. Note, we do
418 * shell expansion except if the string begins with a vertical
419 * bar (i.e. it will likely be passed to the shell later).
421 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
423 lex_get_token(lc, T_STRING);
425 if (lc->str[0] != '|') {
426 do_shell_expansion(lc->str, sizeof(lc->str));
428 *(item->value) = bstrdup(lc->str);
431 set_bit(index, res_all.hdr.item_present);
435 /* Store a password specified address in MD5 coding */
436 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
439 struct MD5Context md5c;
440 unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
444 lex_get_token(lc, T_STRING);
447 MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
448 MD5Final(digest, &md5c);
449 for (i = j = 0; i < sizeof(digest); i++) {
450 sprintf(&sig[j], "%02x", digest[i]);
453 *(item->value) = bstrdup(sig);
456 set_bit(index, res_all.hdr.item_present);
460 /* Store a resource at specified address.
461 * If we are in pass 2, do a lookup of the
464 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
468 lex_get_token(lc, T_NAME);
470 res = GetResWithName(item->code, lc->str);
472 scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
473 lc->str, lc->line_no, lc->line);
475 if (*(item->value)) {
476 scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
477 item->name, lc->line_no, lc->line);
479 *(item->value) = (char *)res;
482 set_bit(index, res_all.hdr.item_present);
486 * Store a resource pointer in an alist. default_value indicates how many
487 * times this routine can be called -- i.e. how many alists
489 * If we are in pass 2, do a lookup of the
492 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
495 int count = item->default_value;
500 if (count == 0) { /* always store in item->value */
502 if ((item->value)[i] == NULL) {
503 list = New(alist(10, not_owned_by_alist));
505 list = (alist *)(item->value)[i];
508 /* Find empty place to store this directive */
509 while ((item->value)[i] != NULL && i++ < count) { }
511 scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
512 lc->str, count, lc->line_no, lc->line);
514 list = New(alist(10, not_owned_by_alist));
518 lex_get_token(lc, T_NAME); /* scan next item */
519 res = GetResWithName(item->code, lc->str);
521 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
522 item->name, lc->line_no, lc->line);
524 Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
525 res, list, list->size(), i, item->name);
527 (item->value)[i] = (char *)list;
528 if (lc->ch != ',') { /* if no other item follows */
531 lex_get_token(lc, T_ALL); /* eat comma */
535 set_bit(index, res_all.hdr.item_present);
540 * Store a string in an alist.
542 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
547 if (*(item->value) == NULL) {
548 list = New(alist(10, owned_by_alist));
550 list = (alist *)(*(item->value));
553 lex_get_token(lc, T_STRING); /* scan next item */
554 Dmsg4(900, "Append %s to alist %p size=%d %s\n",
555 lc->str, list, list->size(), item->name);
556 list->append(bstrdup(lc->str));
557 *(item->value) = (char *)list;
560 set_bit(index, res_all.hdr.item_present);
566 * Store default values for Resource from xxxDefs
567 * If we are in pass 2, do a lookup of the
568 * resource and store everything not explicitly set
571 * Note, here item points to the main resource (e.g. Job, not
572 * the jobdefs, which we look up).
574 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
578 lex_get_token(lc, T_NAME);
580 Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
581 res = GetResWithName(item->code, lc->str);
583 scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
584 lc->str, lc->line_no, lc->line);
592 /* Store an integer at specified address */
593 void store_int32(LEX *lc, RES_ITEM *item, int index, int pass)
595 lex_get_token(lc, T_INT32);
596 *(uint32_t *)(item->value) = lc->int32_val;
598 set_bit(index, res_all.hdr.item_present);
601 /* Store a positive integer at specified address */
602 void store_pint32(LEX *lc, RES_ITEM *item, int index, int pass)
604 lex_get_token(lc, T_PINT32);
605 *(uint32_t *)(item->value) = lc->pint32_val;
607 set_bit(index, res_all.hdr.item_present);
611 /* Store an 64 bit integer at specified address */
612 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
614 lex_get_token(lc, T_INT64);
615 *(int64_t *)(item->value) = lc->int64_val;
617 set_bit(index, res_all.hdr.item_present);
620 /* Store a size in bytes */
621 void store_size(LEX *lc, RES_ITEM *item, int index, int pass)
627 Dmsg0(900, "Enter store_size\n");
628 token = lex_get_token(lc, T_SKIP_EOL);
633 case T_UNQUOTED_STRING:
634 bstrncpy(bsize, lc->str, sizeof(bsize)); /* save first part */
635 /* if terminated by space, scan and get modifier */
636 while (lc->ch == ' ') {
637 token = lex_get_token(lc, T_ALL);
641 case T_UNQUOTED_STRING:
642 bstrncat(bsize, lc->str, sizeof(bsize));
646 if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
647 scan_err1(lc, _("expected a size number, got: %s"), lc->str);
649 *(uint64_t *)(item->value) = uvalue;
652 scan_err1(lc, _("expected a size, got: %s"), lc->str);
655 if (token != T_EOL) {
658 set_bit(index, res_all.hdr.item_present);
659 Dmsg0(900, "Leave store_size\n");
663 /* Store a time period in seconds */
664 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
670 token = lex_get_token(lc, T_SKIP_EOL);
675 case T_UNQUOTED_STRING:
676 bstrncpy(period, lc->str, sizeof(period)); /* get first part */
677 /* if terminated by space, scan and get modifier */
678 while (lc->ch == ' ') {
679 token = lex_get_token(lc, T_ALL);
683 case T_UNQUOTED_STRING:
684 bstrncat(period, lc->str, sizeof(period));
688 if (!duration_to_utime(period, &utime)) {
689 scan_err1(lc, _("expected a time period, got: %s"), period);
691 *(utime_t *)(item->value) = utime;
694 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
697 if (token != T_EOL) {
700 set_bit(index, res_all.hdr.item_present);
704 /* Store a yes/no in a bit field */
705 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
707 lex_get_token(lc, T_NAME);
708 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
709 *(uint32_t *)(item->value) |= item->code;
710 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
711 *(uint32_t *)(item->value) &= ~(item->code);
713 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
716 set_bit(index, res_all.hdr.item_present);
719 /* Store a bool in a bit field */
720 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
722 lex_get_token(lc, T_NAME);
723 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
724 *(bool *)(item->value) = true;
725 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
726 *(bool *)(item->value) = false;
728 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
731 set_bit(index, res_all.hdr.item_present);
736 * Store Tape Label Type (Bacula, ANSI, IBM)
739 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
743 token = lex_get_token(lc, T_NAME);
744 /* Store the label pass 2 so that type is defined */
745 for (i=0; tapelabels[i].name; i++) {
746 if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
747 *(uint32_t *)(item->value) = tapelabels[i].token;
753 scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
756 set_bit(index, res_all.hdr.item_present);
766 CONFIG *new_config_parser()
769 config = (CONFIG *)malloc(sizeof(CONFIG));
770 memset(config, 0, sizeof(CONFIG));
776 LEX_ERROR_HANDLER *scan_error,
782 RES_TABLE *resources,
786 m_scan_error = scan_error;
787 m_err_type = err_type;
788 m_res_all = vres_all;
789 m_res_all_size = res_all_size;
792 m_resources = resources;
793 m_res_head = res_head;
796 /*********************************************************************
798 * Parse configuration file
800 * Return 0 if reading failed, 1 otherwise
801 * Note, the default behavior unless you have set an alternate
802 * scan_error handler is to die on an error.
806 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error, int err_type)
809 CONFIG *config = new_config_parser();
810 config->init(cf, scan_error, err_type, (void *)&res_all, res_all_size,
811 r_first, r_last, resources, res_head);
812 ok = config->parse_config();
819 bool CONFIG::parse_config()
824 enum parse_state state = p_none;
825 RES_ITEM *items = NULL;
827 static bool first = true;
829 const char *cf = m_cf;
830 LEX_ERROR_HANDLER *scan_error = m_scan_error;
831 int err_type = m_err_type;
833 if (first && (errstat=rwl_init(&res_lock)) != 0) {
835 Emsg1(M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
836 be.bstrerror(errstat));
840 char *full_path = (char *)alloca(MAX_PATH + 1);
842 if (find_config_file(cf, full_path, MAX_PATH +1)) {
846 /* Make two passes. The first builds the name symbol table,
847 * and the second picks up the items.
849 Dmsg0(900, "Enter parse_config()\n");
850 for (pass=1; pass <= 2; pass++) {
851 Dmsg1(900, "parse_config pass %d\n", pass);
852 if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
854 /* We must create a lex packet to print the error */
855 lc = (LEX *)malloc(sizeof(LEX));
856 memset(lc, 0, sizeof(LEX));
858 lc->scan_error = scan_error;
860 lex_set_default_error_handler(lc);
862 lex_set_error_handler_error_type(lc, err_type) ;
863 bstrncpy(lc->str, cf, sizeof(lc->str));
865 scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
866 lc->str, be.bstrerror());
870 lex_set_error_handler_error_type(lc, err_type) ;
871 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
872 Dmsg3(900, "parse state=%d pass=%d got token=%s\n", state, pass,
873 lex_tok_to_str(token));
876 if (token == T_EOL) {
878 } else if (token == T_UTF8_BOM) {
879 /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */
881 } else if (token == T_UTF16_BOM) {
882 scan_err0(lc, _("Currently we cannot handle UTF-16 source files. "
883 "Please convert the conf file to UTF-8\n"));
885 } else if (token != T_IDENTIFIER) {
886 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
889 for (i=0; resources[i].name; i++) {
890 if (strcasecmp(resources[i].name, lc->str) == 0) {
891 items = resources[i].items;
896 res_type = resources[i].rcode;
897 init_resource(this, res_type, items, pass);
901 if (state == p_none) {
902 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
913 scan_err1(lc, _("not in resource definition: %s"), lc->str);
916 for (i=0; items[i].name; i++) {
917 if (strcasecmp(items[i].name, lc->str) == 0) {
918 /* If the ITEM_NO_EQUALS flag is set we do NOT
919 * scan for = after the keyword */
920 if (!(items[i].flags & ITEM_NO_EQUALS)) {
921 token = lex_get_token(lc, T_SKIP_EOL);
922 Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
923 if (token != T_EQUALS) {
924 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
928 Dmsg1(800, "calling handler for %s\n", items[i].name);
929 /* Call item handler */
930 items[i].handler(lc, &items[i], i, pass);
936 Dmsg2(900, "level=%d id=%s\n", level, lc->str);
937 Dmsg1(900, "Keyword = %s\n", lc->str);
938 scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
939 "Perhaps you left the trailing brace off of the previous resource."), lc->str);
947 Dmsg0(900, "T_EOB => define new resource\n");
948 if (res_all.hdr.name == NULL) {
949 scan_err0(lc, _("Name not specified for resource"));
951 save_resource(res_type, items, pass); /* save resource */
958 scan_err2(lc, _("unexpected token %d %s in resource definition"),
959 token, lex_tok_to_str(token));
964 scan_err1(lc, _("Unknown parser state %d\n"), state);
968 if (state != p_none) {
969 scan_err0(lc, _("End of conf file reached with unclosed resource."));
972 if (debug_level >= 900 && pass == 2) {
974 for (i=m_r_first; i<=m_r_last; i++) {
975 dump_resource(i, m_res_head[i-m_r_first], prtmsg, NULL);
978 lc = lex_close_file(lc);
980 Dmsg0(900, "Leave parse_config()\n");
984 const char *get_default_configdir()
986 #if defined(HAVE_WIN32)
988 static char szConfigDir[MAX_PATH + 1] = { 0 };
990 if (!p_SHGetFolderPath) {
991 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
995 if (szConfigDir[0] == '\0') {
996 hr = p_SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szConfigDir);
999 bstrncat(szConfigDir, "\\Bacula", sizeof(szConfigDir));
1001 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1011 find_config_file(const char *config_file, char *full_path, int max_path)
1013 if (first_path_separator(config_file) != NULL) {
1019 if (stat(config_file, &st) == 0) {
1023 const char *config_dir = get_default_configdir();
1024 int dir_length = strlen(config_dir);
1025 int file_length = strlen(config_file);
1027 if ((dir_length + 1 + file_length + 1) > max_path) {
1031 memcpy(full_path, config_dir, dir_length + 1);
1033 if (!IsPathSeparator(full_path[dir_length - 1])) {
1034 full_path[dir_length++] = '/';
1037 memcpy(&full_path[dir_length], config_file, file_length + 1);
1042 /*********************************************************************
1044 * Free configuration resources
1047 void CONFIG::free_resources()
1049 for (int i=m_r_first; i<=m_r_last; i++) {
1050 free_resource(m_res_head[i-m_r_first], i);
1051 m_res_head[i-m_r_first] = NULL;
1055 RES **CONFIG::save_resources()
1057 int num = m_r_last - m_r_first + 1;
1058 RES **res = (RES **)malloc(num*sizeof(RES *));
1059 for (int i=0; i<num; i++) {
1060 res[i] = m_res_head[i];
1061 m_res_head[i] = NULL;
1066 RES **CONFIG::new_res_head()
1068 int size = (m_r_last - m_r_first + 1) * sizeof(RES *);
1069 RES **res = (RES **)malloc(size);
1070 memset(res, 0, size);
1076 void free_config_resources()
1078 for (int i=r_first; i<=r_last; i++) {
1079 free_resource(res_head[i-r_first], i);
1080 res_head[i-r_first] = NULL;
1084 RES **save_config_resources()
1086 int num = r_last - r_first + 1;
1087 RES **res = (RES **)malloc(num*sizeof(RES *));
1088 for (int i=0; i<num; i++) {
1089 res[i] = res_head[i];
1095 RES **new_res_head()
1097 int size = (r_last - r_first + 1) * sizeof(RES *);
1098 RES **res = (RES **)malloc(size);
1099 memset(res, 0, size);