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
37 Copyright (C) 2000-2005 Kern Sibbald
39 This program is free software; you can redistribute it and/or
40 modify it under the terms of the GNU General Public License as
41 published by the Free Software Foundation; either version 2 of
42 the License, or (at your option) any later version.
44 This program is distributed in the hope that it will be useful,
45 but WITHOUT ANY WARRANTY; without even the implied warranty of
46 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
47 General Public License for more details.
49 You should have received a copy of the GNU General Public
50 License along with this program; if not, write to the Free
51 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
59 extern int debug_level;
61 /* Each daemon has a slightly different set of
62 * resources, so it will define the following
67 extern RES_TABLE resources[];
68 extern RES **res_head;
71 // work around visual studio name manling preventing external linkage since res_all
72 // is declared as a different type when instantiated.
73 extern "C" CURES res_all;
74 extern "C" int res_all_size;
77 extern int res_all_size;
80 extern brwlock_t res_lock; /* resource lock */
83 /* Forward referenced subroutines */
84 static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd);
87 /* Common Resource definitions */
89 /* Message resource directives
90 * name handler value code flags default_value
92 RES_ITEM msgs_items[] = {
93 {"name", store_name, ITEM(res_msgs.hdr.name), 0, 0, 0},
94 {"description", store_str, ITEM(res_msgs.hdr.desc), 0, 0, 0},
95 {"mailcommand", store_str, ITEM(res_msgs.mail_cmd), 0, 0, 0},
96 {"operatorcommand", store_str, ITEM(res_msgs.operator_cmd), 0, 0, 0},
97 {"syslog", store_msgs, ITEM(res_msgs), MD_SYSLOG, 0, 0},
98 {"mail", store_msgs, ITEM(res_msgs), MD_MAIL, 0, 0},
99 {"mailonerror", store_msgs, ITEM(res_msgs), MD_MAIL_ON_ERROR, 0, 0},
100 {"file", store_msgs, ITEM(res_msgs), MD_FILE, 0, 0},
101 {"append", store_msgs, ITEM(res_msgs), MD_APPEND, 0, 0},
102 {"stdout", store_msgs, ITEM(res_msgs), MD_STDOUT, 0, 0},
103 {"stderr", store_msgs, ITEM(res_msgs), MD_STDERR, 0, 0},
104 {"director", store_msgs, ITEM(res_msgs), MD_DIRECTOR, 0, 0},
105 {"console", store_msgs, ITEM(res_msgs), MD_CONSOLE, 0, 0},
106 {"operator", store_msgs, ITEM(res_msgs), MD_OPERATOR, 0, 0},
107 {NULL, NULL, NULL, 0, 0}
114 /* Various message types */
115 static struct s_mtypes msg_types[] = {
120 {"warning", M_WARNING},
123 {"notsaved", M_NOTSAVED},
124 {"skipped", M_SKIPPED},
126 {"terminate", M_TERM},
127 {"restored", M_RESTORED},
128 {"security", M_SECURITY},
134 /* Used for certain KeyWord tables */
141 * Tape Label types permitted in Pool records
143 * tape label label code = token
145 struct s_kw tapelabels[] = {
146 {"bacula", B_BACULA_LABEL},
147 {"ansi", B_ANSI_LABEL},
148 {"ibm", B_IBM_LABEL},
153 /* Simply print a message */
154 static void prtmsg(void *sock, const char *fmt, ...)
158 va_start(arg_ptr, fmt);
159 vfprintf(stdout, fmt, arg_ptr);
163 const char *res_to_str(int rcode)
165 if (rcode < r_first || rcode > r_last) {
166 return _("***UNKNOWN***");
168 return resources[rcode-r_first].name;
174 * Initialize the static structure to zeros, then
175 * apply all the default values.
177 void init_resource(int type, RES_ITEM *items, int pass)
180 int rindex = type - r_first;
181 static bool first = true;
184 if (first && (errstat=rwl_init(&res_lock)) != 0) {
185 Emsg1(M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
190 memset(&res_all, 0, res_all_size);
191 res_all.hdr.rcode = type;
192 res_all.hdr.refcnt = 1;
194 for (i=0; items[i].name; i++) {
195 Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name,
196 (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
197 items[i].default_value);
198 if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) {
199 if (items[i].handler == store_yesno) {
200 *(int *)(items[i].value) |= items[i].code;
201 } else if (items[i].handler == store_pint ||
202 items[i].handler == store_int) {
203 *(int *)(items[i].value) = items[i].default_value;
204 } else if (items[i].handler == store_int64) {
205 *(int64_t *)(items[i].value) = items[i].default_value;
206 } else if (items[i].handler == store_size) {
207 *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value;
208 } else if (items[i].handler == store_time) {
209 *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
210 } else if (pass == 1 && items[i].handler == store_addresses) {
211 init_default_addresses((dlist**)items[i].value, items[i].default_value);
214 /* If this triggers, take a look at lib/parse_conf.h */
215 if (i >= MAX_RES_ITEMS) {
216 Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
222 /* Store Messages Destination information */
223 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
230 Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
232 switch (item->code) {
235 case MD_SYSLOG: /* syslog */
237 scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
239 case MD_OPERATOR: /* send to operator */
240 case MD_DIRECTOR: /* send to Director */
241 case MD_MAIL: /* mail */
242 case MD_MAIL_ON_ERROR: /* mail if Job errors */
243 if (item->code == MD_OPERATOR) {
244 cmd = res_all.res_msgs.operator_cmd;
246 cmd = res_all.res_msgs.mail_cmd;
248 dest = get_pool_memory(PM_MESSAGE);
251 /* Pick up comma separated list of destinations */
253 token = lex_get_token(lc, T_NAME); /* scan destination */
254 dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
256 pm_strcat(dest, " "); /* separate multiple destinations with space */
259 pm_strcat(dest, lc->str);
260 dest_len += lc->str_len;
261 Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
262 token = lex_get_token(lc, T_SKIP_EOL);
263 if (token == T_COMMA) {
264 continue; /* get another destination */
266 if (token != T_EQUALS) {
267 scan_err1(lc, _("expected an =, got: %s"), lc->str);
271 Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
272 scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
273 free_pool_memory(dest);
274 Dmsg0(900, "done with dest codes\n");
276 case MD_FILE: /* file */
277 case MD_APPEND: /* append */
278 dest = get_pool_memory(PM_MESSAGE);
279 /* Pick up a single destination */
280 token = lex_get_token(lc, T_NAME); /* scan destination */
281 pm_strcpy(dest, lc->str);
282 dest_len = lc->str_len;
283 token = lex_get_token(lc, T_SKIP_EOL);
284 Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
285 if (token != T_EQUALS) {
286 scan_err1(lc, _("expected an =, got: %s"), lc->str);
288 scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
289 free_pool_memory(dest);
290 Dmsg0(900, "done with dest codes\n");
294 scan_err1(lc, _("Unknown item code: %d\n"), item->code);
299 set_bit(index, res_all.hdr.item_present);
300 Dmsg0(900, "Done store_msgs\n");
304 * Scan for message types and add them to the message
305 * destination. The basic job here is to connect message types
306 * (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
307 * destination (MAIL, FILE, OPERATOR, ...)
309 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
311 int i, found, quit, is_not;
315 for (quit=0; !quit;) {
316 lex_get_token(lc, T_NAME); /* expect at least one type */
318 if (lc->str[0] == '!') {
325 for (i=0; msg_types[i].name; i++) {
326 if (strcasecmp(str, msg_types[i].name) == 0) {
327 msg_type = msg_types[i].token;
333 scan_err1(lc, _("message type: %s not found"), str);
337 if (msg_type == M_MAX+1) { /* all? */
338 for (i=1; i<=M_MAX; i++) { /* yes set all types */
339 add_msg_dest(msg, dest_code, i, where, cmd);
343 rem_msg_dest(msg, dest_code, msg_type, where);
345 add_msg_dest(msg, dest_code, msg_type, where, cmd);
351 Dmsg0(900, "call lex_get_token() to eat comma\n");
352 lex_get_token(lc, T_ALL); /* eat comma */
354 Dmsg0(900, "Done scan_types()\n");
359 * This routine is ONLY for resource names
360 * Store a name at specified address.
362 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
364 POOLMEM *msg = get_pool_memory(PM_EMSG);
365 lex_get_token(lc, T_NAME);
366 if (!is_name_valid(lc->str, &msg)) {
367 scan_err1(lc, "%s\n", msg);
369 free_pool_memory(msg);
370 /* Store the name both pass 1 and pass 2 */
371 if (*(item->value)) {
372 scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."),
373 *(item->value), lc->str);
375 *(item->value) = bstrdup(lc->str);
377 set_bit(index, res_all.hdr.item_present);
382 * Store a name string at specified address
383 * A name string is limited to MAX_RES_NAME_LENGTH
385 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
387 lex_get_token(lc, T_NAME);
390 *(item->value) = bstrdup(lc->str);
393 set_bit(index, res_all.hdr.item_present);
396 /* Store a string at specified address */
397 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
399 lex_get_token(lc, T_STRING);
401 *(item->value) = bstrdup(lc->str);
404 set_bit(index, res_all.hdr.item_present);
408 * Store a directory name at specified address. Note, we do
409 * shell expansion except if the string begins with a vertical
410 * bar (i.e. it will likely be passed to the shell later).
412 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
414 lex_get_token(lc, T_STRING);
416 if (lc->str[0] != '|') {
417 do_shell_expansion(lc->str, sizeof(lc->str));
419 *(item->value) = bstrdup(lc->str);
422 set_bit(index, res_all.hdr.item_present);
426 /* Store a password specified address in MD5 coding */
427 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
430 struct MD5Context md5c;
431 unsigned char signature[16];
435 lex_get_token(lc, T_STRING);
438 MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
439 MD5Final(signature, &md5c);
440 for (i = j = 0; i < sizeof(signature); i++) {
441 sprintf(&sig[j], "%02x", signature[i]);
444 *(item->value) = bstrdup(sig);
447 set_bit(index, res_all.hdr.item_present);
451 /* Store a resource at specified address.
452 * If we are in pass 2, do a lookup of the
455 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
459 lex_get_token(lc, T_NAME);
461 res = GetResWithName(item->code, lc->str);
463 scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
464 lc->str, lc->line_no, lc->line);
466 if (*(item->value)) {
467 scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
468 item->name, lc->line_no, lc->line);
470 *(item->value) = (char *)res;
473 set_bit(index, res_all.hdr.item_present);
477 * Store a resource pointer in an alist. default_value indicates how many
478 * times this routine can be called -- i.e. how many alists
480 * If we are in pass 2, do a lookup of the
483 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
486 int count = item->default_value;
491 if (count == 0) { /* always store in item->value */
493 if ((item->value)[i] == NULL) {
494 list = New(alist(10, not_owned_by_alist));
496 list = (alist *)(item->value)[i];
499 /* Find empty place to store this directive */
500 while ((item->value)[i] != NULL && i++ < count) { }
502 scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
503 lc->str, count, lc->line_no, lc->line);
505 list = New(alist(10, not_owned_by_alist));
509 lex_get_token(lc, T_NAME); /* scan next item */
510 res = GetResWithName(item->code, lc->str);
512 scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
513 item->name, lc->line_no, lc->line);
515 Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
516 res, list, list->size(), i, item->name);
518 (item->value)[i] = (char *)list;
519 if (lc->ch != ',') { /* if no other item follows */
522 lex_get_token(lc, T_ALL); /* eat comma */
526 set_bit(index, res_all.hdr.item_present);
531 * Store a string in an alist.
533 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
538 if (*(item->value) == NULL) {
539 list = New(alist(10, owned_by_alist));
541 list = (alist *)(*(item->value));
544 lex_get_token(lc, T_STRING); /* scan next item */
545 Dmsg4(900, "Append %s to alist %p size=%d %s\n",
546 lc->str, list, list->size(), item->name);
547 list->append(bstrdup(lc->str));
548 *(item->value) = (char *)list;
551 set_bit(index, res_all.hdr.item_present);
557 * Store default values for Resource from xxxDefs
558 * If we are in pass 2, do a lookup of the
559 * resource and store everything not explicitly set
562 * Note, here item points to the main resource (e.g. Job, not
563 * the jobdefs, which we look up).
565 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
569 lex_get_token(lc, T_NAME);
571 Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
572 res = GetResWithName(item->code, lc->str);
574 scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
575 lc->str, lc->line_no, lc->line);
577 /* for each item not set, we copy the field from res */
579 for (int i=0; item->name;; i++, item++) {
580 if (bit_is_set(i, res->item_present)) {
581 Dmsg2(900, "Item %d is present in %s\n", i, res->name);
583 Dmsg2(900, "Item %d is not present in %s\n", i, res->name);
586 /* ***FIXME **** add code */
594 /* Store an integer at specified address */
595 void store_int(LEX *lc, RES_ITEM *item, int index, int pass)
597 lex_get_token(lc, T_INT32);
598 *(int *)(item->value) = lc->int32_val;
600 set_bit(index, res_all.hdr.item_present);
603 /* Store a positive integer at specified address */
604 void store_pint(LEX *lc, RES_ITEM *item, int index, int pass)
606 lex_get_token(lc, T_PINT32);
607 *(int *)(item->value) = lc->pint32_val;
609 set_bit(index, res_all.hdr.item_present);
613 /* Store an 64 bit integer at specified address */
614 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
616 lex_get_token(lc, T_INT64);
617 *(int64_t *)(item->value) = lc->int64_val;
619 set_bit(index, res_all.hdr.item_present);
622 /* Store a size in bytes */
623 void store_size(LEX *lc, RES_ITEM *item, int index, int pass)
628 Dmsg0(900, "Enter store_size\n");
629 token = lex_get_token(lc, T_SKIP_EOL);
634 case T_UNQUOTED_STRING:
635 if (!size_to_uint64(lc->str, lc->str_len, &uvalue)) {
636 scan_err1(lc, _("expected a size number, got: %s"), lc->str);
638 *(uint64_t *)(item->value) = uvalue;
641 scan_err1(lc, _("expected a size, got: %s"), lc->str);
645 set_bit(index, res_all.hdr.item_present);
646 Dmsg0(900, "Leave store_size\n");
650 /* Store a time period in seconds */
651 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
657 token = lex_get_token(lc, T_SKIP_EOL);
662 case T_UNQUOTED_STRING:
663 bstrncpy(period, lc->str, sizeof(period));
665 token = lex_get_token(lc, T_ALL);
668 case T_UNQUOTED_STRING:
669 bstrncat(period, lc->str, sizeof(period));
673 if (!duration_to_utime(period, &utime)) {
674 scan_err1(lc, _("expected a time period, got: %s"), period);
676 *(utime_t *)(item->value) = utime;
679 scan_err1(lc, _("expected a time period, got: %s"), lc->str);
682 if (token != T_EOL) {
685 set_bit(index, res_all.hdr.item_present);
689 /* Store a yes/no in a bit field */
690 void store_yesno(LEX *lc, RES_ITEM *item, int index, int pass)
692 lex_get_token(lc, T_NAME);
693 if (strcasecmp(lc->str, "yes") == 0) {
694 *(int *)(item->value) |= item->code;
695 } else if (strcasecmp(lc->str, "no") == 0) {
696 *(int *)(item->value) &= ~(item->code);
698 scan_err1(lc, _("Expect a YES or NO, got: %s"), lc->str);
701 set_bit(index, res_all.hdr.item_present);
705 * Store Tape Label Type (Bacula, ANSI, IBM)
708 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
712 token = lex_get_token(lc, T_NAME);
713 /* Store the label pass 2 so that type is defined */
714 for (i=0; tapelabels[i].name; i++) {
715 if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
716 *(int *)(item->value) = tapelabels[i].token;
722 scan_err1(lc, "Expected a Tape Label keyword, got: %s", lc->str);
725 set_bit(index, res_all.hdr.item_present);
735 /*********************************************************************
737 * Parse configuration file
739 * Return 0 if reading failed, 1 otherwise
742 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error)
747 enum parse_state state = p_none;
748 RES_ITEM *items = NULL;
751 /* Make two passes. The first builds the name symbol table,
752 * and the second picks up the items.
754 Dmsg0(900, "Enter parse_config()\n");
755 for (pass=1; pass <= 2; pass++) {
756 Dmsg1(900, "parse_config pass %d\n", pass);
757 if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
758 lc = (LEX *)malloc(sizeof(LEX));
759 memset(lc, 0, sizeof(LEX));
760 lc->scan_error = scan_error;
762 scan_err2(lc, _("Cannot open config file %s: %s\n"),
763 lc->str, be.strerror());
767 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
768 Dmsg1(900, "parse got token=%s\n", lex_tok_to_str(token));
771 if (token == T_EOL) {
774 if (token != T_IDENTIFIER) {
775 scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
778 for (i=0; resources[i].name; i++)
779 if (strcasecmp(resources[i].name, lc->str) == 0) {
781 items = resources[i].items;
782 res_type = resources[i].rcode;
783 init_resource(res_type, items, pass);
786 if (state == p_none) {
787 scan_err1(lc, _("expected resource name, got: %s"), lc->str);
798 scan_err1(lc, _("not in resource definition: %s"), lc->str);
801 for (i=0; items[i].name; i++) {
802 if (strcasecmp(items[i].name, lc->str) == 0) {
803 /* If the ITEM_NO_EQUALS flag is set we do NOT
804 * scan for = after the keyword */
805 if (!(items[i].flags & ITEM_NO_EQUALS)) {
806 token = lex_get_token(lc, T_SKIP_EOL);
807 Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
808 if (token != T_EQUALS) {
809 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
813 Dmsg1(900, "calling handler for %s\n", items[i].name);
814 /* Call item handler */
815 items[i].handler(lc, &items[i], i, pass);
821 Dmsg2(900, "level=%d id=%s\n", level, lc->str);
822 Dmsg1(900, "Keyword = %s\n", lc->str);
823 scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
824 "Perhaps you left the trailing brace off of the previous resource."), lc->str);
832 Dmsg0(900, "T_EOB => define new resource\n");
833 save_resource(res_type, items, pass); /* save resource */
840 scan_err2(lc, _("unexpected token %d %s in resource definition"),
841 token, lex_tok_to_str(token));
846 scan_err1(lc, _("Unknown parser state %d\n"), state);
850 if (state != p_none) {
851 scan_err0(lc, _("End of conf file reached with unclosed resource."));
854 if (debug_level >= 900 && pass == 2) {
856 for (i=r_first; i<=r_last; i++) {
857 dump_resource(i, res_head[i-r_first], prtmsg, NULL);
860 lc = lex_close_file(lc);
862 Dmsg0(900, "Leave parse_config()\n");
866 /*********************************************************************
868 * Free configuration resources
871 void free_config_resources()
873 for (int i=r_first; i<=r_last; i++) {
874 free_resource(res_head[i-r_first], i);
875 res_head[i-r_first] = NULL;
879 RES **save_config_resources()
881 int num = r_last - r_first + 1;
882 RES **res = (RES **)malloc(num*sizeof(RES *));
883 for (int i=0; i<num; i++) {
884 res[i] = res_head[i];
892 int size = (r_last - r_first + 1) * sizeof(RES *);
893 RES **res = (RES **)malloc(size);
894 memset(res, 0, size);