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)
72 /* Each daemon has a slightly different set of
73 * resources, so it will define the following
78 extern RES_TABLE resources[];
79 extern RES **res_head;
82 * Define the Union of all the common resource structure definitions.
90 // work around visual studio name mangling preventing external linkage since res_all
91 // is declared as a different type when instantiated.
92 extern "C" URES res_all;
96 extern int res_all_size;
98 extern brwlock_t res_lock; /* resource lock */
101 /* Forward referenced subroutines */
102 static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd);
103 static const char *get_default_configdir();
104 static bool find_config_file(const char *config_file, char *full_path, int max_path);
106 /* Common Resource definitions */
108 /* Message resource directives
109 * name handler value code flags default_value
111 RES_ITEM msgs_items[] = {
112 {"name", store_name, ITEM(res_msgs.hdr.name), 0, 0, 0},
113 {"description", store_str, ITEM(res_msgs.hdr.desc), 0, 0, 0},
114 {"mailcommand", store_str, ITEM(res_msgs.mail_cmd), 0, 0, 0},
115 {"operatorcommand", store_str, ITEM(res_msgs.operator_cmd), 0, 0, 0},
116 {"syslog", store_msgs, ITEM(res_msgs), MD_SYSLOG, 0, 0},
117 {"mail", store_msgs, ITEM(res_msgs), MD_MAIL, 0, 0},
118 {"mailonerror", store_msgs, ITEM(res_msgs), MD_MAIL_ON_ERROR, 0, 0},
119 {"mailonsuccess", store_msgs, ITEM(res_msgs), MD_MAIL_ON_SUCCESS, 0, 0},
120 {"file", store_msgs, ITEM(res_msgs), MD_FILE, 0, 0},
121 {"append", store_msgs, ITEM(res_msgs), MD_APPEND, 0, 0},
122 {"stdout", store_msgs, ITEM(res_msgs), MD_STDOUT, 0, 0},
123 {"stderr", store_msgs, ITEM(res_msgs), MD_STDERR, 0, 0},
124 {"director", store_msgs, ITEM(res_msgs), MD_DIRECTOR, 0, 0},
125 {"console", store_msgs, ITEM(res_msgs), MD_CONSOLE, 0, 0},
126 {"operator", store_msgs, ITEM(res_msgs), MD_OPERATOR, 0, 0},
127 {"catalog", store_msgs, ITEM(res_msgs), MD_CATALOG, 0, 0},
128 {NULL, NULL, {0}, 0, 0, 0}
135 /* Various message types */
136 static struct s_mtypes msg_types[] = {
141 {"warning", M_WARNING},
144 {"notsaved", M_NOTSAVED},
145 {"skipped", M_SKIPPED},
147 {"terminate", M_TERM},
148 {"restored", M_RESTORED},
149 {"security", M_SECURITY},
151 {"volmgmt", M_VOLMGMT},
156 /* Used for certain KeyWord tables */
163 * Tape Label types permitted in Pool records
165 * tape label label code = token
167 static s_kw tapelabels[] = {
168 {"bacula", B_BACULA_LABEL},
169 {"ansi", B_ANSI_LABEL},
170 {"ibm", B_IBM_LABEL},
175 /* Simply print a message */
176 static void prtmsg(void *sock, const char *fmt, ...)
180 va_start(arg_ptr, fmt);
181 vfprintf(stdout, fmt, arg_ptr);
185 const char *res_to_str(int rcode)
187 if (rcode < r_first || rcode > r_last) {
188 return _("***UNKNOWN***");
190 return resources[rcode-r_first].name;
196 * Initialize the static structure to zeros, then
197 * apply all the default values.
199 static void init_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
202 int rindex = type - r_first;
204 memset(config->m_res_all, 0, config->m_res_all_size);
205 res_all.hdr.rcode = type;
206 res_all.hdr.refcnt = 1;
208 /* Set defaults in each item */
209 for (i=0; items[i].name; i++) {
210 Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name,
211 (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
212 items[i].default_value);
213 if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) {
214 if (items[i].handler == store_bit) {
215 *(int *)(items[i].value) |= items[i].code;
216 } else if (items[i].handler == store_bool) {
217 *(bool *)(items[i].value) = items[i].default_value != 0;
218 } else if (items[i].handler == store_pint ||
219 items[i].handler == store_int) {
220 *(int *)(items[i].value) = items[i].default_value;
221 } else if (items[i].handler == store_int64) {
222 *(int64_t *)(items[i].value) = items[i].default_value;
223 } else if (items[i].handler == store_size) {
224 *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
225 } else if (items[i].handler == store_time) {
226 *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
227 } else if (pass == 1 && items[i].handler == store_addresses) {
228 init_default_addresses((dlist**)items[i].value, items[i].default_value);
231 /* If this triggers, take a look at lib/parse_conf.h */
232 if (i >= MAX_RES_ITEMS) {
233 Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
239 /* Store Messages Destination information */
240 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
247 Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
249 switch (item->code) {
252 case MD_SYSLOG: /* syslog */
255 scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
257 case MD_OPERATOR: /* send to operator */
258 case MD_DIRECTOR: /* send to Director */
259 case MD_MAIL: /* mail */
260 case MD_MAIL_ON_ERROR: /* mail if Job errors */
261 case MD_MAIL_ON_SUCCESS: /* mail if Job succeeds */
262 if (item->code == MD_OPERATOR) {
263 cmd = res_all.res_msgs.operator_cmd;
265 cmd = res_all.res_msgs.mail_cmd;
267 dest = get_pool_memory(PM_MESSAGE);
270 /* Pick up comma separated list of destinations */
272 token = lex_get_token(lc, T_NAME); /* scan destination */
273 dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
275 pm_strcat(dest, " "); /* separate multiple destinations with space */
278 pm_strcat(dest, lc->str);
279 dest_len += lc->str_len;
280 Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
281 token = lex_get_token(lc, T_SKIP_EOL);
282 if (token == T_COMMA) {
283 continue; /* get another destination */
285 if (token != T_EQUALS) {
286 scan_err1(lc, _("expected an =, got: %s"), lc->str);
290 Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
291 scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
292 free_pool_memory(dest);
293 Dmsg0(900, "done with dest codes\n");
296 case MD_FILE: /* file */
297 case MD_APPEND: /* append */
298 dest = get_pool_memory(PM_MESSAGE);
299 /* Pick up a single destination */
300 token = lex_get_token(lc, T_NAME); /* scan destination */
301 pm_strcpy(dest, lc->str);
302 dest_len = lc->str_len;
303 token = lex_get_token(lc, T_SKIP_EOL);
304 Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
305 if (token != T_EQUALS) {
306 scan_err1(lc, _("expected an =, got: %s"), lc->str);
308 scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
309 free_pool_memory(dest);
310 Dmsg0(900, "done with dest codes\n");
314 scan_err1(lc, _("Unknown item code: %d\n"), item->code);
319 set_bit(index, res_all.hdr.item_present);
320 Dmsg0(900, "Done store_msgs\n");
324 * Scan for message types and add them to the message
325 * destination. The basic job here is to connect message types
326 * (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
327 * destination (MAIL, FILE, OPERATOR, ...)
329 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
337 lex_get_token(lc, T_NAME); /* expect at least one type */
339 if (lc->str[0] == '!') {
346 for (i=0; msg_types[i].name; i++) {
347 if (strcasecmp(str, msg_types[i].name) == 0) {
348 msg_type = msg_types[i].token;
354 scan_err1(lc, _("message type: %s not found"), str);
358 if (msg_type == M_MAX+1) { /* all? */
359 for (i=1; i<=M_MAX; i++) { /* yes set all types */
360 add_msg_dest(msg, dest_code, i, where, cmd);
363 rem_msg_dest(msg, dest_code, msg_type, where);
365 add_msg_dest(msg, dest_code, msg_type, where, cmd);
370 Dmsg0(900, "call lex_get_token() to eat comma\n");
371 lex_get_token(lc, T_ALL); /* eat comma */
373 Dmsg0(900, "Done scan_types()\n");
378 * This routine is ONLY for resource names
379 * Store a name at specified address.
381 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
383 POOLMEM *msg = get_pool_memory(PM_EMSG);
384 lex_get_token(lc, T_NAME);
385 if (!is_name_valid(lc->str, &msg)) {
386 scan_err1(lc, "%s\n", msg);
388 free_pool_memory(msg);
389 /* Store the name both pass 1 and pass 2 */
390 if (*(item->value)) {
391 scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."),
392 *(item->value), lc->str);
394 *(item->value) = bstrdup(lc->str);
396 set_bit(index, res_all.hdr.item_present);
401 * Store a name string at specified address
402 * A name string is limited to MAX_RES_NAME_LENGTH
404 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
406 lex_get_token(lc, T_NAME);
409 *(item->value) = bstrdup(lc->str);
412 set_bit(index, res_all.hdr.item_present);
415 /* Store a string at specified address */
416 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
418 lex_get_token(lc, T_STRING);
420 *(item->value) = bstrdup(lc->str);
423 set_bit(index, res_all.hdr.item_present);
427 * Store a directory name at specified address. Note, we do
428 * shell expansion except if the string begins with a vertical
429 * bar (i.e. it will likely be passed to the shell later).
431 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
433 lex_get_token(lc, T_STRING);
435 if (lc->str[0] != '|') {
436 do_shell_expansion(lc->str, sizeof(lc->str));
438 *(item->value) = bstrdup(lc->str);
441 set_bit(index, res_all.hdr.item_present);
445 /* Store a password specified address in MD5 coding */
446 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
449 struct MD5Context md5c;
450 unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
454 lex_get_token(lc, T_STRING);
457 MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
458 MD5Final(digest, &md5c);
459 for (i = j = 0; i < sizeof(digest); i++) {
460 sprintf(&sig[j], "%02x", digest[i]);
463 *(item->value) = bstrdup(sig);
466 set_bit(index, res_all.hdr.item_present);
470 /* Store a resource at specified address.
471 * If we are in pass 2, do a lookup of the
474 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
478 lex_get_token(lc, T_NAME);
480 res = GetResWithName(item->code, lc->str);
482 scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
483 lc->str, lc->line_no, lc->line);
485 if (*(item->value)) {
486 scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
487 item->name, lc->line_no, lc->line);
489 *(item->value) = (char *)res;
492 set_bit(index, res_all.hdr.item_present);
496 * Store a resource pointer in an alist. default_value indicates how many
497 * times this routine can be called -- i.e. how many alists
499 * If we are in pass 2, do a lookup of the
502 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
505 int count = item->default_value;
510 if (count == 0) { /* always store in item->value */
512 if ((item->value)[i] == NULL) {
513 list = New(alist(10, not_owned_by_alist));
515 list = (alist *)(item->value)[i];
518 /* Find empty place to store this directive */
519 while ((item->value)[i] != NULL && i++ < count) { }
521 scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
522 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);
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);
602 /* Store an integer at specified address */
603 void store_int(LEX *lc, RES_ITEM *item, int index, int pass)
605 lex_get_token(lc, T_INT32);
606 *(int *)(item->value) = lc->int32_val;
608 set_bit(index, res_all.hdr.item_present);
611 /* Store a positive integer at specified address */
612 void store_pint(LEX *lc, RES_ITEM *item, int index, int pass)
614 lex_get_token(lc, T_PINT32);
615 *(int *)(item->value) = lc->pint32_val;
617 set_bit(index, res_all.hdr.item_present);
621 /* Store an 64 bit integer at specified address */
622 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
624 lex_get_token(lc, T_INT64);
625 *(int64_t *)(item->value) = lc->int64_val;
627 set_bit(index, res_all.hdr.item_present);
630 /* Store a size in bytes */
631 void store_size(LEX *lc, RES_ITEM *item, int index, int pass)
637 Dmsg0(900, "Enter store_size\n");
638 token = lex_get_token(lc, T_SKIP_EOL);
643 case T_UNQUOTED_STRING:
644 bstrncpy(bsize, lc->str, sizeof(bsize)); /* save first part */
645 /* if terminated by space, scan and get modifier */
646 while (lc->ch == ' ') {
647 token = lex_get_token(lc, T_ALL);
651 case T_UNQUOTED_STRING:
652 bstrncat(bsize, lc->str, sizeof(bsize));
656 if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
657 scan_err1(lc, _("expected a size number, got: %s"), lc->str);
659 *(uint64_t *)(item->value) = uvalue;
662 scan_err1(lc, _("expected a size, got: %s"), lc->str);
665 if (token != T_EOL) {
668 set_bit(index, res_all.hdr.item_present);
669 Dmsg0(900, "Leave store_size\n");
673 /* Store a time period in seconds */
674 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
680 token = lex_get_token(lc, T_SKIP_EOL);
685 case T_UNQUOTED_STRING:
686 bstrncpy(period, lc->str, sizeof(period)); /* get first part */
687 /* if terminated by space, scan and get modifier */
688 while (lc->ch == ' ') {
689 token = lex_get_token(lc, T_ALL);
693 case T_UNQUOTED_STRING:
694 bstrncat(period, lc->str, sizeof(period));
698 if (!duration_to_utime(period, &utime)) {
699 scan_err1(lc, _("expected a time period, got: %s"), period);
701 *(utime_t *)(item->value) = utime;
704 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
707 if (token != T_EOL) {
710 set_bit(index, res_all.hdr.item_present);
714 /* Store a yes/no in a bit field */
715 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
717 lex_get_token(lc, T_NAME);
718 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
719 *(int *)(item->value) |= item->code;
720 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
721 *(int *)(item->value) &= ~(item->code);
723 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
726 set_bit(index, res_all.hdr.item_present);
729 /* Store a bool in a bit field */
730 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
732 lex_get_token(lc, T_NAME);
733 if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
734 *(bool *)(item->value) = true;
735 } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
736 *(bool *)(item->value) = false;
738 scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
741 set_bit(index, res_all.hdr.item_present);
746 * Store Tape Label Type (Bacula, ANSI, IBM)
749 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
753 token = lex_get_token(lc, T_NAME);
754 /* Store the label pass 2 so that type is defined */
755 for (i=0; tapelabels[i].name; i++) {
756 if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
757 *(int *)(item->value) = tapelabels[i].token;
763 scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
766 set_bit(index, res_all.hdr.item_present);
776 CONFIG *new_config_parser()
779 config = (CONFIG *)malloc(sizeof(CONFIG));
780 memset(config, 0, sizeof(CONFIG));
786 LEX_ERROR_HANDLER *scan_error,
792 RES_TABLE *resources,
796 m_scan_error = scan_error;
797 m_err_type = err_type;
798 m_res_all = vres_all;
799 m_res_all_size = res_all_size;
802 m_resources = resources;
803 m_res_head = res_head;
806 /*********************************************************************
808 * Parse configuration file
810 * Return 0 if reading failed, 1 otherwise
811 * Note, the default behavior unless you have set an alternate
812 * scan_error handler is to die on an error.
815 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error, int err_type)
818 CONFIG *config = new_config_parser();
819 config->init(cf, scan_error, err_type, (void *)&res_all, res_all_size,
820 r_first, r_last, resources, res_head);
821 ok = config->parse_config();
827 bool CONFIG::parse_config()
832 enum parse_state state = p_none;
833 RES_ITEM *items = NULL;
835 static bool first = true;
837 const char *cf = m_cf;
838 LEX_ERROR_HANDLER *scan_error = m_scan_error;
839 int err_type = m_err_type;
841 if (first && (errstat=rwl_init(&res_lock)) != 0) {
843 Emsg1(M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
844 be.bstrerror(errstat));
848 char *full_path = (char *)alloca(MAX_PATH + 1);
850 if (find_config_file(cf, full_path, MAX_PATH +1)) {
854 /* Make two passes. The first builds the name symbol table,
855 * and the second picks up the items.
857 Dmsg0(900, "Enter parse_config()\n");
858 for (pass=1; pass <= 2; pass++) {
859 Dmsg1(900, "parse_config pass %d\n", pass);
860 if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
862 /* We must create a lex packet to print the error */
863 lc = (LEX *)malloc(sizeof(LEX));
864 memset(lc, 0, sizeof(LEX));
866 lc->scan_error = scan_error;
868 lex_set_default_error_handler(lc);
870 lex_set_error_handler_error_type(lc, err_type) ;
871 bstrncpy(lc->str, cf, sizeof(lc->str));
873 scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
874 lc->str, be.bstrerror());
878 lex_set_error_handler_error_type(lc, err_type) ;
879 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
880 Dmsg3(900, "parse state=%d pass=%d got token=%s\n", state, pass,
881 lex_tok_to_str(token));
884 if (token == T_EOL) {
886 } else if (token == T_UTF8_BOM) {
887 /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */
889 } else if (token == T_UTF16_BOM) {
890 scan_err0(lc, _("Currently we cannot handle UTF-16 source files. "
891 "Please convert the conf file to UTF-8\n"));
893 } else if (token != T_IDENTIFIER) {
894 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
897 for (i=0; resources[i].name; i++) {
898 if (strcasecmp(resources[i].name, lc->str) == 0) {
899 items = resources[i].items;
904 res_type = resources[i].rcode;
905 init_resource(this, res_type, items, pass);
909 if (state == p_none) {
910 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
921 scan_err1(lc, _("not in resource definition: %s"), lc->str);
924 for (i=0; items[i].name; i++) {
925 if (strcasecmp(items[i].name, lc->str) == 0) {
926 /* If the ITEM_NO_EQUALS flag is set we do NOT
927 * scan for = after the keyword */
928 if (!(items[i].flags & ITEM_NO_EQUALS)) {
929 token = lex_get_token(lc, T_SKIP_EOL);
930 Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
931 if (token != T_EQUALS) {
932 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
936 Dmsg1(800, "calling handler for %s\n", items[i].name);
937 /* Call item handler */
938 items[i].handler(lc, &items[i], i, pass);
944 Dmsg2(900, "level=%d id=%s\n", level, lc->str);
945 Dmsg1(900, "Keyword = %s\n", lc->str);
946 scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
947 "Perhaps you left the trailing brace off of the previous resource."), lc->str);
955 Dmsg0(900, "T_EOB => define new resource\n");
956 if (res_all.hdr.name == NULL) {
957 scan_err0(lc, _("Name not specified for resource"));
959 save_resource(res_type, items, pass); /* save resource */
966 scan_err2(lc, _("unexpected token %d %s in resource definition"),
967 token, lex_tok_to_str(token));
972 scan_err1(lc, _("Unknown parser state %d\n"), state);
976 if (state != p_none) {
977 scan_err0(lc, _("End of conf file reached with unclosed resource."));
980 if (debug_level >= 900 && pass == 2) {
982 for (i=r_first; i<=r_last; i++) {
983 dump_resource(i, res_head[i-r_first], prtmsg, NULL);
986 lc = lex_close_file(lc);
988 Dmsg0(900, "Leave parse_config()\n");
992 const char *get_default_configdir()
994 #if defined(HAVE_WIN32)
996 static char szConfigDir[MAX_PATH + 1] = { 0 };
998 if (!p_SHGetFolderPath) {
999 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1003 if (szConfigDir[0] == '\0') {
1004 hr = p_SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szConfigDir);
1006 if (SUCCEEDED(hr)) {
1007 bstrncat(szConfigDir, "\\Bacula", sizeof(szConfigDir));
1009 bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1019 find_config_file(const char *config_file, char *full_path, int max_path)
1021 if (first_path_separator(config_file) != NULL) {
1027 if (stat(config_file, &st) == 0) {
1031 const char *config_dir = get_default_configdir();
1032 int dir_length = strlen(config_dir);
1033 int file_length = strlen(config_file);
1035 if ((dir_length + 1 + file_length + 1) > max_path) {
1039 memcpy(full_path, config_dir, dir_length + 1);
1041 if (!IsPathSeparator(full_path[dir_length - 1])) {
1042 full_path[dir_length++] = '/';
1045 memcpy(&full_path[dir_length], config_file, file_length + 1);
1050 /*********************************************************************
1052 * Free configuration resources
1055 void CONFIG::free_resources()
1057 for (int i=m_r_first; i<=m_r_last; i++) {
1058 free_resource(m_res_head[i-m_r_first], i);
1059 m_res_head[i-m_r_first] = NULL;
1063 RES **CONFIG::save_resources()
1065 int num = m_r_last - m_r_first + 1;
1066 RES **res = (RES **)malloc(num*sizeof(RES *));
1067 for (int i=0; i<num; i++) {
1068 res[i] = m_res_head[i];
1069 m_res_head[i] = NULL;
1074 RES **CONFIG::new_res_head()
1076 int size = (m_r_last - m_r_first + 1) * sizeof(RES *);
1077 RES **res = (RES **)malloc(size);
1078 memset(res, 0, size);
1082 void free_config_resources()
1084 for (int i=r_first; i<=r_last; i++) {
1085 free_resource(res_head[i-r_first], i);
1086 res_head[i-r_first] = NULL;
1091 RES **save_config_resources()
1093 int num = r_last - r_first + 1;
1094 RES **res = (RES **)malloc(num*sizeof(RES *));
1095 for (int i=0; i<num; i++) {
1096 res[i] = res_head[i];
1102 RES **new_res_head()
1104 int size = (r_last - r_first + 1) * sizeof(RES *);
1105 RES **res = (RES **)malloc(size);
1106 memset(res, 0, size);