2 * Master Configuration routines.
4 * This file contains the common parts of the Bacula
5 * configuration routines.
7 * Note, the configuration file parser consists of three parts
9 * 1. The generic lexical scanner in lib/lex.c and lib/lex.h
11 * 2. The generic config scanner in lib/parse_conf.c and
13 * These files contain the parser code, some utility
14 * routines, and the common store routines (name, int,
15 * string, time, int64, size, ...).
17 * 3. The daemon specific file, which contains the Resource
18 * definitions as well as any specific store routines
19 * for the resource records.
21 * N.B. This is a two pass parser, so if you malloc() a string
22 * in a "store" routine, you must ensure to do it during
23 * only one of the two passes, or to free it between.
24 * Also, note that the resource record is malloced and
25 * saved in save_resource() during pass 1. Anything that
26 * you want saved after pass two (e.g. resource pointers)
27 * must explicitly be done in save_resource. Take a look
28 * at the Job resource in src/dird/dird_conf.c to see how
31 * Kern Sibbald, January MM
36 Copyright (C) 2000-2005 Kern Sibbald
38 This program is free software; you can redistribute it and/or
39 modify it under the terms of the GNU General Public License
40 version 2 as ammended with additional clauses defined in the
41 file LICENSE in the main source directory.
43 This program is distributed in the hope that it will be useful,
44 but WITHOUT ANY WARRANTY; without even the implied warranty of
45 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46 the file LICENSE for additional details.
53 extern int debug_level;
55 /* Each daemon has a slightly different set of
56 * resources, so it will define the following
61 extern RES_TABLE resources[];
62 extern RES **res_head;
65 // work around visual studio name manling preventing external linkage since res_all
66 // is declared as a different type when instantiated.
67 extern "C" CURES res_all;
68 extern "C" int res_all_size;
71 extern int res_all_size;
74 extern brwlock_t res_lock; /* resource lock */
77 /* Forward referenced subroutines */
78 static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd);
81 /* Common Resource definitions */
83 /* Message resource directives
84 * name handler value code flags default_value
86 RES_ITEM msgs_items[] = {
87 {"name", store_name, ITEM(res_msgs.hdr.name), 0, 0, 0},
88 {"description", store_str, ITEM(res_msgs.hdr.desc), 0, 0, 0},
89 {"mailcommand", store_str, ITEM(res_msgs.mail_cmd), 0, 0, 0},
90 {"operatorcommand", store_str, ITEM(res_msgs.operator_cmd), 0, 0, 0},
91 {"syslog", store_msgs, ITEM(res_msgs), MD_SYSLOG, 0, 0},
92 {"mail", store_msgs, ITEM(res_msgs), MD_MAIL, 0, 0},
93 {"mailonerror", store_msgs, ITEM(res_msgs), MD_MAIL_ON_ERROR, 0, 0},
94 {"file", store_msgs, ITEM(res_msgs), MD_FILE, 0, 0},
95 {"append", store_msgs, ITEM(res_msgs), MD_APPEND, 0, 0},
96 {"stdout", store_msgs, ITEM(res_msgs), MD_STDOUT, 0, 0},
97 {"stderr", store_msgs, ITEM(res_msgs), MD_STDERR, 0, 0},
98 {"director", store_msgs, ITEM(res_msgs), MD_DIRECTOR, 0, 0},
99 {"console", store_msgs, ITEM(res_msgs), MD_CONSOLE, 0, 0},
100 {"operator", store_msgs, ITEM(res_msgs), MD_OPERATOR, 0, 0},
101 {NULL, NULL, NULL, 0, 0}
108 /* Various message types */
109 static struct s_mtypes msg_types[] = {
114 {"warning", M_WARNING},
117 {"notsaved", M_NOTSAVED},
118 {"skipped", M_SKIPPED},
120 {"terminate", M_TERM},
121 {"restored", M_RESTORED},
122 {"security", M_SECURITY},
128 /* Used for certain KeyWord tables */
135 * Tape Label types permitted in Pool records
137 * tape label label code = token
139 struct s_kw tapelabels[] = {
140 {"bacula", B_BACULA_LABEL},
141 {"ansi", B_ANSI_LABEL},
142 {"ibm", B_IBM_LABEL},
147 /* Simply print a message */
148 static void prtmsg(void *sock, const char *fmt, ...)
152 va_start(arg_ptr, fmt);
153 vfprintf(stdout, fmt, arg_ptr);
157 const char *res_to_str(int rcode)
159 if (rcode < r_first || rcode > r_last) {
160 return _("***UNKNOWN***");
162 return resources[rcode-r_first].name;
168 * Initialize the static structure to zeros, then
169 * apply all the default values.
171 void init_resource(int type, RES_ITEM *items, int pass)
174 int rindex = type - r_first;
175 static bool first = true;
178 if (first && (errstat=rwl_init(&res_lock)) != 0) {
179 Emsg1(M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
184 memset(&res_all, 0, res_all_size);
185 res_all.hdr.rcode = type;
186 res_all.hdr.refcnt = 1;
188 for (i=0; items[i].name; i++) {
189 Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name,
190 (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
191 items[i].default_value);
192 if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) {
193 if (items[i].handler == store_yesno) {
194 *(int *)(items[i].value) |= items[i].code;
195 } else if (items[i].handler == store_pint ||
196 items[i].handler == store_int) {
197 *(int *)(items[i].value) = items[i].default_value;
198 } else if (items[i].handler == store_int64) {
199 *(int64_t *)(items[i].value) = items[i].default_value;
200 } else if (items[i].handler == store_size) {
201 *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
202 } else if (items[i].handler == store_time) {
203 *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
204 } else if (pass == 1 && items[i].handler == store_addresses) {
205 init_default_addresses((dlist**)items[i].value, items[i].default_value);
208 /* If this triggers, take a look at lib/parse_conf.h */
209 if (i >= MAX_RES_ITEMS) {
210 Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
216 /* Store Messages Destination information */
217 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
224 Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
226 switch (item->code) {
229 case MD_SYSLOG: /* syslog */
231 scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
233 case MD_OPERATOR: /* send to operator */
234 case MD_DIRECTOR: /* send to Director */
235 case MD_MAIL: /* mail */
236 case MD_MAIL_ON_ERROR: /* mail if Job errors */
237 if (item->code == MD_OPERATOR) {
238 cmd = res_all.res_msgs.operator_cmd;
240 cmd = res_all.res_msgs.mail_cmd;
242 dest = get_pool_memory(PM_MESSAGE);
245 /* Pick up comma separated list of destinations */
247 token = lex_get_token(lc, T_NAME); /* scan destination */
248 dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
250 pm_strcat(dest, " "); /* separate multiple destinations with space */
253 pm_strcat(dest, lc->str);
254 dest_len += lc->str_len;
255 Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
256 token = lex_get_token(lc, T_SKIP_EOL);
257 if (token == T_COMMA) {
258 continue; /* get another destination */
260 if (token != T_EQUALS) {
261 scan_err1(lc, _("expected an =, got: %s"), lc->str);
265 Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
266 scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
267 free_pool_memory(dest);
268 Dmsg0(900, "done with dest codes\n");
270 case MD_FILE: /* file */
271 case MD_APPEND: /* append */
272 dest = get_pool_memory(PM_MESSAGE);
273 /* Pick up a single destination */
274 token = lex_get_token(lc, T_NAME); /* scan destination */
275 pm_strcpy(dest, lc->str);
276 dest_len = lc->str_len;
277 token = lex_get_token(lc, T_SKIP_EOL);
278 Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
279 if (token != T_EQUALS) {
280 scan_err1(lc, _("expected an =, got: %s"), lc->str);
282 scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
283 free_pool_memory(dest);
284 Dmsg0(900, "done with dest codes\n");
288 scan_err1(lc, _("Unknown item code: %d\n"), item->code);
293 set_bit(index, res_all.hdr.item_present);
294 Dmsg0(900, "Done store_msgs\n");
298 * Scan for message types and add them to the message
299 * destination. The basic job here is to connect message types
300 * (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
301 * destination (MAIL, FILE, OPERATOR, ...)
303 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
305 int i, found, quit, is_not;
309 for (quit=0; !quit;) {
310 lex_get_token(lc, T_NAME); /* expect at least one type */
312 if (lc->str[0] == '!') {
319 for (i=0; msg_types[i].name; i++) {
320 if (strcasecmp(str, msg_types[i].name) == 0) {
321 msg_type = msg_types[i].token;
327 scan_err1(lc, _("message type: %s not found"), str);
331 if (msg_type == M_MAX+1) { /* all? */
332 for (i=1; i<=M_MAX; i++) { /* yes set all types */
333 add_msg_dest(msg, dest_code, i, where, cmd);
337 rem_msg_dest(msg, dest_code, msg_type, where);
339 add_msg_dest(msg, dest_code, msg_type, where, cmd);
345 Dmsg0(900, "call lex_get_token() to eat comma\n");
346 lex_get_token(lc, T_ALL); /* eat comma */
348 Dmsg0(900, "Done scan_types()\n");
353 * This routine is ONLY for resource names
354 * Store a name at specified address.
356 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
358 POOLMEM *msg = get_pool_memory(PM_EMSG);
359 lex_get_token(lc, T_NAME);
360 if (!is_name_valid(lc->str, &msg)) {
361 scan_err1(lc, "%s\n", msg);
363 free_pool_memory(msg);
364 /* Store the name both pass 1 and pass 2 */
365 if (*(item->value)) {
366 scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."),
367 *(item->value), lc->str);
369 *(item->value) = bstrdup(lc->str);
371 set_bit(index, res_all.hdr.item_present);
376 * Store a name string at specified address
377 * A name string is limited to MAX_RES_NAME_LENGTH
379 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
381 lex_get_token(lc, T_NAME);
384 *(item->value) = bstrdup(lc->str);
387 set_bit(index, res_all.hdr.item_present);
390 /* Store a string at specified address */
391 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
393 lex_get_token(lc, T_STRING);
395 *(item->value) = bstrdup(lc->str);
398 set_bit(index, res_all.hdr.item_present);
402 * Store a directory name at specified address. Note, we do
403 * shell expansion except if the string begins with a vertical
404 * bar (i.e. it will likely be passed to the shell later).
406 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
408 lex_get_token(lc, T_STRING);
410 if (lc->str[0] != '|') {
411 do_shell_expansion(lc->str, sizeof(lc->str));
413 *(item->value) = bstrdup(lc->str);
416 set_bit(index, res_all.hdr.item_present);
420 /* Store a password specified address in MD5 coding */
421 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
424 struct MD5Context md5c;
425 unsigned char signature[16];
429 lex_get_token(lc, T_STRING);
432 MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
433 MD5Final(signature, &md5c);
434 for (i = j = 0; i < sizeof(signature); i++) {
435 sprintf(&sig[j], "%02x", signature[i]);
438 *(item->value) = bstrdup(sig);
441 set_bit(index, res_all.hdr.item_present);
445 /* Store a resource at specified address.
446 * If we are in pass 2, do a lookup of the
449 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
453 lex_get_token(lc, T_NAME);
455 res = GetResWithName(item->code, lc->str);
457 scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
458 lc->str, lc->line_no, lc->line);
460 if (*(item->value)) {
461 scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
462 item->name, lc->line_no, lc->line);
464 *(item->value) = (char *)res;
467 set_bit(index, res_all.hdr.item_present);
471 * Store a resource pointer in an alist. default_value indicates how many
472 * times this routine can be called -- i.e. how many alists
474 * If we are in pass 2, do a lookup of the
477 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
480 int count = item->default_value;
485 if (count == 0) { /* always store in item->value */
487 if ((item->value)[i] == NULL) {
488 list = New(alist(10, not_owned_by_alist));
490 list = (alist *)(item->value)[i];
493 /* Find empty place to store this directive */
494 while ((item->value)[i] != NULL && i++ < count) { }
496 scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
497 lc->str, count, lc->line_no, lc->line);
499 list = New(alist(10, not_owned_by_alist));
503 lex_get_token(lc, T_NAME); /* scan next item */
504 res = GetResWithName(item->code, lc->str);
506 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
507 item->name, lc->line_no, lc->line);
509 Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
510 res, list, list->size(), i, item->name);
512 (item->value)[i] = (char *)list;
513 if (lc->ch != ',') { /* if no other item follows */
516 lex_get_token(lc, T_ALL); /* eat comma */
520 set_bit(index, res_all.hdr.item_present);
525 * Store a string in an alist.
527 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
532 if (*(item->value) == NULL) {
533 list = New(alist(10, owned_by_alist));
535 list = (alist *)(*(item->value));
538 lex_get_token(lc, T_STRING); /* scan next item */
539 Dmsg4(900, "Append %s to alist %p size=%d %s\n",
540 lc->str, list, list->size(), item->name);
541 list->append(bstrdup(lc->str));
542 *(item->value) = (char *)list;
545 set_bit(index, res_all.hdr.item_present);
551 * Store default values for Resource from xxxDefs
552 * If we are in pass 2, do a lookup of the
553 * resource and store everything not explicitly set
556 * Note, here item points to the main resource (e.g. Job, not
557 * the jobdefs, which we look up).
559 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
563 lex_get_token(lc, T_NAME);
565 Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
566 res = GetResWithName(item->code, lc->str);
568 scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
569 lc->str, lc->line_no, lc->line);
571 /* for each item not set, we copy the field from res */
573 for (int i=0; item->name;; i++, item++) {
574 if (bit_is_set(i, res->item_present)) {
575 Dmsg2(900, "Item %d is present in %s\n", i, res->name);
577 Dmsg2(900, "Item %d is not present in %s\n", i, res->name);
580 /* ***FIXME **** add code */
588 /* Store an integer at specified address */
589 void store_int(LEX *lc, RES_ITEM *item, int index, int pass)
591 lex_get_token(lc, T_INT32);
592 *(int *)(item->value) = lc->int32_val;
594 set_bit(index, res_all.hdr.item_present);
597 /* Store a positive integer at specified address */
598 void store_pint(LEX *lc, RES_ITEM *item, int index, int pass)
600 lex_get_token(lc, T_PINT32);
601 *(int *)(item->value) = lc->pint32_val;
603 set_bit(index, res_all.hdr.item_present);
607 /* Store an 64 bit integer at specified address */
608 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
610 lex_get_token(lc, T_INT64);
611 *(int64_t *)(item->value) = lc->int64_val;
613 set_bit(index, res_all.hdr.item_present);
616 /* Store a size in bytes */
617 void store_size(LEX *lc, RES_ITEM *item, int index, int pass)
623 Dmsg0(900, "Enter store_size\n");
624 token = lex_get_token(lc, T_SKIP_EOL);
629 case T_UNQUOTED_STRING:
630 bstrncpy(bsize, lc->str, sizeof(bsize)); /* save first part */
631 /* if terminated by space, scan and get modifier */
633 token = lex_get_token(lc, T_ALL);
636 case T_UNQUOTED_STRING:
637 bstrncat(bsize, lc->str, sizeof(bsize));
641 if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
642 scan_err1(lc, _("expected a size number, got: %s"), lc->str);
644 *(uint64_t *)(item->value) = uvalue;
647 scan_err1(lc, _("expected a size, got: %s"), lc->str);
651 set_bit(index, res_all.hdr.item_present);
652 Dmsg0(900, "Leave store_size\n");
656 /* Store a time period in seconds */
657 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
663 token = lex_get_token(lc, T_SKIP_EOL);
668 case T_UNQUOTED_STRING:
669 bstrncpy(period, lc->str, sizeof(period)); /* get first part */
670 /* if terminated by space, scan and get modifier */
672 token = lex_get_token(lc, T_ALL);
675 case T_UNQUOTED_STRING:
676 bstrncat(period, lc->str, sizeof(period));
680 if (!duration_to_utime(period, &utime)) {
681 scan_err1(lc, _("expected a time period, got: %s"), period);
683 *(utime_t *)(item->value) = utime;
686 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
689 if (token != T_EOL) {
692 set_bit(index, res_all.hdr.item_present);
696 /* Store a yes/no in a bit field */
697 void store_yesno(LEX *lc, RES_ITEM *item, int index, int pass)
699 lex_get_token(lc, T_NAME);
700 if (strcasecmp(lc->str, "yes") == 0) {
701 *(int *)(item->value) |= item->code;
702 } else if (strcasecmp(lc->str, "no") == 0) {
703 *(int *)(item->value) &= ~(item->code);
705 scan_err1(lc, _("Expect a YES or NO, got: %s"), lc->str);
708 set_bit(index, res_all.hdr.item_present);
712 * Store Tape Label Type (Bacula, ANSI, IBM)
715 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
719 token = lex_get_token(lc, T_NAME);
720 /* Store the label pass 2 so that type is defined */
721 for (i=0; tapelabels[i].name; i++) {
722 if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
723 *(int *)(item->value) = tapelabels[i].token;
729 scan_err1(lc, "Expected a Tape Label keyword, got: %s", lc->str);
732 set_bit(index, res_all.hdr.item_present);
742 /*********************************************************************
744 * Parse configuration file
746 * Return 0 if reading failed, 1 otherwise
747 * Note, the default behavior unless you have set an alternate
748 * scan_error handler is to die on an error.
751 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error)
756 enum parse_state state = p_none;
757 RES_ITEM *items = NULL;
760 /* Make two passes. The first builds the name symbol table,
761 * and the second picks up the items.
763 Dmsg0(900, "Enter parse_config()\n");
764 for (pass=1; pass <= 2; pass++) {
765 Dmsg1(900, "parse_config pass %d\n", pass);
766 if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
768 /* We must create a lex packet to print the error */
769 lc = (LEX *)malloc(sizeof(LEX));
770 memset(lc, 0, sizeof(LEX));
772 lc->scan_error = scan_error;
774 lex_set_default_error_handler(lc);
776 bstrncpy(lc->str, cf, sizeof(lc->str));
778 scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
779 lc->str, be.strerror());
783 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
784 Dmsg1(900, "parse got token=%s\n", lex_tok_to_str(token));
787 if (token == T_EOL) {
790 if (token != T_IDENTIFIER) {
791 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
794 for (i=0; resources[i].name; i++)
795 if (strcasecmp(resources[i].name, lc->str) == 0) {
797 items = resources[i].items;
798 res_type = resources[i].rcode;
799 init_resource(res_type, items, pass);
802 if (state == p_none) {
803 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
814 scan_err1(lc, _("not in resource definition: %s"), lc->str);
817 for (i=0; items[i].name; i++) {
818 if (strcasecmp(items[i].name, lc->str) == 0) {
819 /* If the ITEM_NO_EQUALS flag is set we do NOT
820 * scan for = after the keyword */
821 if (!(items[i].flags & ITEM_NO_EQUALS)) {
822 token = lex_get_token(lc, T_SKIP_EOL);
823 Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
824 if (token != T_EQUALS) {
825 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
829 Dmsg1(900, "calling handler for %s\n", items[i].name);
830 /* Call item handler */
831 items[i].handler(lc, &items[i], i, pass);
837 Dmsg2(900, "level=%d id=%s\n", level, lc->str);
838 Dmsg1(900, "Keyword = %s\n", lc->str);
839 scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
840 "Perhaps you left the trailing brace off of the previous resource."), lc->str);
848 Dmsg0(900, "T_EOB => define new resource\n");
849 save_resource(res_type, items, pass); /* save resource */
856 scan_err2(lc, _("unexpected token %d %s in resource definition"),
857 token, lex_tok_to_str(token));
862 scan_err1(lc, _("Unknown parser state %d\n"), state);
866 if (state != p_none) {
867 scan_err0(lc, _("End of conf file reached with unclosed resource."));
870 if (debug_level >= 900 && pass == 2) {
872 for (i=r_first; i<=r_last; i++) {
873 dump_resource(i, res_head[i-r_first], prtmsg, NULL);
876 lc = lex_close_file(lc);
878 Dmsg0(900, "Leave parse_config()\n");
882 /*********************************************************************
884 * Free configuration resources
887 void free_config_resources()
889 for (int i=r_first; i<=r_last; i++) {
890 free_resource(res_head[i-r_first], i);
891 res_head[i-r_first] = NULL;
895 RES **save_config_resources()
897 int num = r_last - r_first + 1;
898 RES **res = (RES **)malloc(num*sizeof(RES *));
899 for (int i=0; i<num; i++) {
900 res[i] = res_head[i];
908 int size = (r_last - r_first + 1) * sizeof(RES *);
909 RES **res = (RES **)malloc(size);
910 memset(res, 0, size);