]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/parse_conf.c
Fix typo.
[bacula/bacula] / bacula / src / lib / parse_conf.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
5
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
11    in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  *   Master Configuration routines.
30  *
31  *   This file contains the common parts of the Bacula
32  *   configuration routines.
33  *
34  *   Note, the configuration file parser consists of three parts
35  *
36  *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
37  *
38  *   2. The generic config  scanner in lib/parse_conf.c and
39  *      lib/parse_conf.h.
40  *      These files contain the parser code, some utility
41  *      routines, and the common store routines (name, int,
42  *      string, time, int64, size, ...).
43  *
44  *   3. The daemon specific file, which contains the Resource
45  *      definitions as well as any specific store routines
46  *      for the resource records.
47  *
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
56  *         it is done.
57  *
58  *     Kern Sibbald, January MM
59  *
60  *   Version $Id$
61  */
62
63
64 #include "bacula.h"
65
66 #if defined(HAVE_WIN32)
67 #include "shlobj.h"
68 #else
69 #define MAX_PATH  1024
70 #endif
71
72 /*
73  * Define the Union of all the common resource structure definitions.
74  */
75 union URES {
76    MSGS  res_msgs;
77    RES hdr;
78 };
79
80 #if defined(_MSC_VER)
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;
84 #else
85 extern  URES res_all;
86 #endif
87
88 extern brwlock_t res_lock;            /* resource lock */
89
90
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);
95
96 /* Common Resource definitions */
97
98 /* Message resource directives
99  *  name         handler      value       code   flags  default_value
100  */
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}
119 };
120
121 struct s_mtypes {
122    const char *name;
123    int token;
124 };
125 /* Various message types */
126 static struct s_mtypes msg_types[] = {
127    {"debug",         M_DEBUG},
128    {"abort",         M_ABORT},
129    {"fatal",         M_FATAL},
130    {"error",         M_ERROR},
131    {"warning",       M_WARNING},
132    {"info",          M_INFO},
133    {"saved",         M_SAVED},
134    {"notsaved",      M_NOTSAVED},
135    {"skipped",       M_SKIPPED},
136    {"mount",         M_MOUNT},
137    {"terminate",     M_TERM},
138    {"restored",      M_RESTORED},
139    {"security",      M_SECURITY},
140    {"alert",         M_ALERT},
141    {"volmgmt",       M_VOLMGMT},
142    {"all",           M_MAX+1},
143    {NULL,            0}
144 };
145
146 /* Used for certain KeyWord tables */
147 struct s_kw {
148    const char *name;
149    int token;
150 };
151
152 /*
153  * Tape Label types permitted in Pool records 
154  *
155  *   tape label      label code = token
156  */
157 static s_kw tapelabels[] = {
158    {"bacula",        B_BACULA_LABEL},
159    {"ansi",          B_ANSI_LABEL},
160    {"ibm",           B_IBM_LABEL},
161    {NULL,            0}
162 };
163
164
165 /* Simply print a message */
166 static void prtmsg(void *sock, const char *fmt, ...)
167 {
168    va_list arg_ptr;
169
170    va_start(arg_ptr, fmt);
171    vfprintf(stdout, fmt, arg_ptr);
172    va_end(arg_ptr);
173 }
174
175 const char *res_to_str(int rcode)
176 {
177    if (rcode < r_first || rcode > r_last) {
178       return _("***UNKNOWN***");
179    } else {
180       return resources[rcode-r_first].name;
181    }
182 }
183
184
185 /*
186  * Initialize the static structure to zeros, then
187  *  apply all the default values.
188  */
189 static void init_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
190 {
191    int i;
192    int rindex = type - r_first;
193
194    memset(config->m_res_all, 0, config->m_res_all_size);
195    res_all.hdr.rcode = type;
196    res_all.hdr.refcnt = 1;
197
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_time) {
217             *(utime_t *)(items[i].value) = (utime_t)items[i].default_value;
218          } else if (pass == 1 && items[i].handler == store_addresses) {
219             init_default_addresses((dlist**)items[i].value, items[i].default_value);
220          }
221       }
222       /* If this triggers, take a look at lib/parse_conf.h */
223       if (i >= MAX_RES_ITEMS) {
224          Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
225       }
226    }
227 }
228
229
230 /* Store Messages Destination information */
231 void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass)
232 {
233    int token;
234    char *cmd;
235    POOLMEM *dest;
236    int dest_len;
237
238    Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
239    if (pass == 1) {
240       switch (item->code) {
241       case MD_STDOUT:
242       case MD_STDERR:
243       case MD_SYSLOG:              /* syslog */
244       case MD_CONSOLE:
245       case MD_CATALOG:
246          scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL);
247          break;
248       case MD_OPERATOR:            /* send to operator */
249       case MD_DIRECTOR:            /* send to Director */
250       case MD_MAIL:                /* mail */
251       case MD_MAIL_ON_ERROR:       /* mail if Job errors */
252       case MD_MAIL_ON_SUCCESS:     /* mail if Job succeeds */
253          if (item->code == MD_OPERATOR) {
254             cmd = res_all.res_msgs.operator_cmd;
255          } else {
256             cmd = res_all.res_msgs.mail_cmd;
257          }
258          dest = get_pool_memory(PM_MESSAGE);
259          dest[0] = 0;
260          dest_len = 0;
261          /* Pick up comma separated list of destinations */
262          for ( ;; ) {
263             token = lex_get_token(lc, T_NAME);   /* scan destination */
264             dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
265             if (dest[0] != 0) {
266                pm_strcat(dest, " ");  /* separate multiple destinations with space */
267                dest_len++;
268             }
269             pm_strcat(dest, lc->str);
270             dest_len += lc->str_len;
271             Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
272             token = lex_get_token(lc, T_SKIP_EOL);
273             if (token == T_COMMA) {
274                continue;           /* get another destination */
275             }
276             if (token != T_EQUALS) {
277                scan_err1(lc, _("expected an =, got: %s"), lc->str);
278                return;
279             }
280             break;
281          }
282          Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
283          scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
284          free_pool_memory(dest);
285          Dmsg0(900, "done with dest codes\n");
286          break;
287
288       case MD_FILE:                /* file */
289       case MD_APPEND:              /* append */
290          dest = get_pool_memory(PM_MESSAGE);
291          /* Pick up a single destination */
292          token = lex_get_token(lc, T_NAME);   /* scan destination */
293          pm_strcpy(dest, lc->str);
294          dest_len = lc->str_len;
295          token = lex_get_token(lc, T_SKIP_EOL);
296          Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
297          if (token != T_EQUALS) {
298             scan_err1(lc, _("expected an =, got: %s"), lc->str);
299             return;
300          }
301          scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
302          free_pool_memory(dest);
303          Dmsg0(900, "done with dest codes\n");
304          break;
305
306       default:
307          scan_err1(lc, _("Unknown item code: %d\n"), item->code);
308          return;
309       }
310    }
311    scan_to_eol(lc);
312    set_bit(index, res_all.hdr.item_present);
313    Dmsg0(900, "Done store_msgs\n");
314 }
315
316 /*
317  * Scan for message types and add them to the message
318  * destination. The basic job here is to connect message types
319  *  (WARNING, ERROR, FATAL, INFO, ...) with an appropriate
320  *  destination (MAIL, FILE, OPERATOR, ...)
321  */
322 static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd)
323 {
324    int i; 
325    bool found, is_not;
326    int msg_type = 0;
327    char *str;
328
329    for ( ;; ) {
330       lex_get_token(lc, T_NAME);            /* expect at least one type */
331       found = false;
332       if (lc->str[0] == '!') {
333          is_not = true;
334          str = &lc->str[1];
335       } else {
336          is_not = false;
337          str = &lc->str[0];
338       }
339       for (i=0; msg_types[i].name; i++) {
340          if (strcasecmp(str, msg_types[i].name) == 0) {
341             msg_type = msg_types[i].token;
342             found = true;
343             break;
344          }
345       }
346       if (!found) {
347          scan_err1(lc, _("message type: %s not found"), str);
348          return;
349       }
350
351       if (msg_type == M_MAX+1) {         /* all? */
352          for (i=1; i<=M_MAX; i++) {      /* yes set all types */
353             add_msg_dest(msg, dest_code, i, where, cmd);
354          }
355       } else if (is_not) {
356          rem_msg_dest(msg, dest_code, msg_type, where);
357       } else {
358          add_msg_dest(msg, dest_code, msg_type, where, cmd);
359       }
360       if (lc->ch != ',') {
361          break;
362       }
363       Dmsg0(900, "call lex_get_token() to eat comma\n");
364       lex_get_token(lc, T_ALL);          /* eat comma */
365    }
366    Dmsg0(900, "Done scan_types()\n");
367 }
368
369
370 /*
371  * This routine is ONLY for resource names
372  *  Store a name at specified address.
373  */
374 void store_name(LEX *lc, RES_ITEM *item, int index, int pass)
375 {
376    POOLMEM *msg = get_pool_memory(PM_EMSG);
377    lex_get_token(lc, T_NAME);
378    if (!is_name_valid(lc->str, &msg)) {
379       scan_err1(lc, "%s\n", msg);
380       return;
381    }
382    free_pool_memory(msg);
383    /* Store the name both pass 1 and pass 2 */
384    if (*(item->value)) {
385       scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."),
386          *(item->value), lc->str);
387       return;
388    }
389    *(item->value) = bstrdup(lc->str);
390    scan_to_eol(lc);
391    set_bit(index, res_all.hdr.item_present);
392 }
393
394
395 /*
396  * Store a name string at specified address
397  * A name string is limited to MAX_RES_NAME_LENGTH
398  */
399 void store_strname(LEX *lc, RES_ITEM *item, int index, int pass)
400 {
401    lex_get_token(lc, T_NAME);
402    /* Store the name */
403    if (pass == 1) {
404       *(item->value) = bstrdup(lc->str);
405    }
406    scan_to_eol(lc);
407    set_bit(index, res_all.hdr.item_present);
408 }
409
410 /* Store a string at specified address */
411 void store_str(LEX *lc, RES_ITEM *item, int index, int pass)
412 {
413    lex_get_token(lc, T_STRING);
414    if (pass == 1) {
415       *(item->value) = bstrdup(lc->str);
416    }
417    scan_to_eol(lc);
418    set_bit(index, res_all.hdr.item_present);
419 }
420
421 /*
422  * Store a directory name at specified address. Note, we do
423  *   shell expansion except if the string begins with a vertical
424  *   bar (i.e. it will likely be passed to the shell later).
425  */
426 void store_dir(LEX *lc, RES_ITEM *item, int index, int pass)
427 {
428    lex_get_token(lc, T_STRING);
429    if (pass == 1) {
430       if (lc->str[0] != '|') {
431          do_shell_expansion(lc->str, sizeof(lc->str));
432       }
433       *(item->value) = bstrdup(lc->str);
434    }
435    scan_to_eol(lc);
436    set_bit(index, res_all.hdr.item_present);
437 }
438
439
440 /* Store a password specified address in MD5 coding */
441 void store_password(LEX *lc, RES_ITEM *item, int index, int pass)
442 {
443    unsigned int i, j;
444    struct MD5Context md5c;
445    unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
446    char sig[100];
447
448
449    lex_get_token(lc, T_STRING);
450    if (pass == 1) {
451       MD5Init(&md5c);
452       MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
453       MD5Final(digest, &md5c);
454       for (i = j = 0; i < sizeof(digest); i++) {
455          sprintf(&sig[j], "%02x", digest[i]);
456          j += 2;
457       }
458       *(item->value) = bstrdup(sig);
459    }
460    scan_to_eol(lc);
461    set_bit(index, res_all.hdr.item_present);
462 }
463
464
465 /* Store a resource at specified address.
466  * If we are in pass 2, do a lookup of the
467  * resource.
468  */
469 void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
470 {
471    RES *res;
472
473    lex_get_token(lc, T_NAME);
474    if (pass == 2) {
475       res = GetResWithName(item->code, lc->str);
476       if (res == NULL) {
477          scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
478             lc->str, lc->line_no, lc->line);
479          return;
480       }
481       if (*(item->value)) {
482          scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
483             item->name, lc->line_no, lc->line);
484          return;
485       }
486       *(item->value) = (char *)res;
487    }
488    scan_to_eol(lc);
489    set_bit(index, res_all.hdr.item_present);
490 }
491
492 /*
493  * Store a resource pointer in an alist. default_value indicates how many
494  *   times this routine can be called -- i.e. how many alists
495  *   there are.
496  * If we are in pass 2, do a lookup of the
497  *   resource.
498  */
499 void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
500 {
501    RES *res;
502    int count = item->default_value;
503    int i = 0;
504    alist *list;
505
506    if (pass == 2) {
507       if (count == 0) {               /* always store in item->value */
508          i = 0;
509          if ((item->value)[i] == NULL) {
510             list = New(alist(10, not_owned_by_alist));
511          } else {
512             list = (alist *)(item->value)[i];
513          }
514       } else {
515          /* Find empty place to store this directive */
516          while ((item->value)[i] != NULL && i++ < count) { }
517          if (i >= count) {
518             scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
519                lc->str, count, lc->line_no, lc->line);
520             return;
521          }
522          list = New(alist(10, not_owned_by_alist));
523       }
524
525       for (;;) {
526          lex_get_token(lc, T_NAME);   /* scan next item */
527          res = GetResWithName(item->code, lc->str);
528          if (res == NULL) {
529             scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
530                item->name, lc->line_no, lc->line);
531             return;
532          }
533          Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n", 
534                res, list, list->size(), i, item->name);
535          list->append(res);
536          (item->value)[i] = (char *)list;
537          if (lc->ch != ',') {         /* if no other item follows */
538             break;                    /* get out */
539          }
540          lex_get_token(lc, T_ALL);    /* eat comma */
541       }
542    }
543    scan_to_eol(lc);
544    set_bit(index, res_all.hdr.item_present);
545 }
546
547
548 /*
549  * Store a string in an alist.
550  */
551 void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
552 {
553    alist *list;
554
555    if (pass == 2) {
556       if (*(item->value) == NULL) {
557          list = New(alist(10, owned_by_alist));
558       } else {
559          list = (alist *)(*(item->value));    
560       }
561
562       lex_get_token(lc, T_STRING);   /* scan next item */
563       Dmsg4(900, "Append %s to alist %p size=%d %s\n", 
564          lc->str, list, list->size(), item->name);
565       list->append(bstrdup(lc->str));
566       *(item->value) = (char *)list;
567    }
568    scan_to_eol(lc);
569    set_bit(index, res_all.hdr.item_present);
570 }
571
572
573
574 /*
575  * Store default values for Resource from xxxDefs
576  * If we are in pass 2, do a lookup of the
577  * resource and store everything not explicitly set
578  * in main resource.
579  *
580  * Note, here item points to the main resource (e.g. Job, not
581  *  the jobdefs, which we look up).
582  */
583 void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
584 {
585    RES *res;
586
587    lex_get_token(lc, T_NAME);
588    if (pass == 2) {
589      Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
590      res = GetResWithName(item->code, lc->str);
591      if (res == NULL) {
592         scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
593            lc->str, lc->line_no, lc->line);
594         return;
595      }
596    }
597    scan_to_eol(lc);
598 }
599
600
601
602 /* Store an integer at specified address */
603 void store_int32(LEX *lc, RES_ITEM *item, int index, int pass)
604 {
605    lex_get_token(lc, T_INT32);
606    *(uint32_t *)(item->value) = lc->int32_val;
607    scan_to_eol(lc);
608    set_bit(index, res_all.hdr.item_present);
609 }
610
611 /* Store a positive integer at specified address */
612 void store_pint32(LEX *lc, RES_ITEM *item, int index, int pass)
613 {
614    lex_get_token(lc, T_PINT32);
615    *(uint32_t *)(item->value) = lc->pint32_val;
616    scan_to_eol(lc);
617    set_bit(index, res_all.hdr.item_present);
618 }
619
620
621 /* Store an 64 bit integer at specified address */
622 void store_int64(LEX *lc, RES_ITEM *item, int index, int pass)
623 {
624    lex_get_token(lc, T_INT64);
625    *(int64_t *)(item->value) = lc->int64_val;
626    scan_to_eol(lc);
627    set_bit(index, res_all.hdr.item_present);
628 }
629
630 /* Store a size in bytes */
631 static void store_size(LEX *lc, RES_ITEM *item, int index, int pass, bool size32)
632 {
633    int token;
634    uint64_t uvalue;
635    char bsize[500];
636
637    Dmsg0(900, "Enter store_size\n");
638    token = lex_get_token(lc, T_SKIP_EOL);
639    errno = 0;
640    switch (token) {
641    case T_NUMBER:
642    case T_IDENTIFIER:
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);
648          switch (token) {
649          case T_NUMBER:
650          case T_IDENTIFIER:
651          case T_UNQUOTED_STRING:
652             bstrncat(bsize, lc->str, sizeof(bsize));
653             break;
654          }
655       }
656       if (!size_to_uint64(bsize, strlen(bsize), &uvalue)) {
657          scan_err1(lc, _("expected a size number, got: %s"), lc->str);
658          return;
659       }
660       if (size32) {
661          *(uint32_t *)(item->value) = (uint32_t)uvalue;
662       } else {
663          *(uint64_t *)(item->value) = uvalue;
664       }
665       break;
666    default:
667       scan_err1(lc, _("expected a size, got: %s"), lc->str);
668       return;
669    }
670    if (token != T_EOL) {
671       scan_to_eol(lc);
672    }
673    set_bit(index, res_all.hdr.item_present);
674    Dmsg0(900, "Leave store_size\n");
675 }
676
677 /* Store a size in bytes */
678 void store_size32(LEX *lc, RES_ITEM *item, int index, int pass)
679 {
680    store_size(lc, item, index, pass, true /* 32 bit */);
681 }
682
683 /* Store a size in bytes */
684 void store_size64(LEX *lc, RES_ITEM *item, int index, int pass)
685 {
686    store_size(lc, item, index, pass, false /* not 32 bit */);
687 }
688
689
690 /* Store a time period in seconds */
691 void store_time(LEX *lc, RES_ITEM *item, int index, int pass)
692 {
693    int token;
694    utime_t utime;
695    char period[500];
696
697    token = lex_get_token(lc, T_SKIP_EOL);
698    errno = 0;
699    switch (token) {
700    case T_NUMBER:
701    case T_IDENTIFIER:
702    case T_UNQUOTED_STRING:
703       bstrncpy(period, lc->str, sizeof(period));  /* get first part */
704       /* if terminated by space, scan and get modifier */
705       while (lc->ch == ' ') {
706          token = lex_get_token(lc, T_ALL);
707          switch (token) {
708          case T_NUMBER:
709          case T_IDENTIFIER:
710          case T_UNQUOTED_STRING:
711             bstrncat(period, lc->str, sizeof(period));
712             break;
713          }
714       }
715       if (!duration_to_utime(period, &utime)) {
716          scan_err1(lc, _("expected a time period, got: %s"), period);
717          return;
718       }
719       *(utime_t *)(item->value) = utime;
720       break;
721    default:
722       scan_err1(lc, _("expected a time period, got: %s"), lc->str);
723       return;
724    }
725    if (token != T_EOL) {
726       scan_to_eol(lc);
727    }
728    set_bit(index, res_all.hdr.item_present);
729 }
730
731
732 /* Store a yes/no in a bit field */
733 void store_bit(LEX *lc, RES_ITEM *item, int index, int pass)
734 {
735    lex_get_token(lc, T_NAME);
736    if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
737       *(uint32_t *)(item->value) |= item->code;
738    } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
739       *(uint32_t *)(item->value) &= ~(item->code);
740    } else {
741       scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
742       return;
743    }
744    scan_to_eol(lc);
745    set_bit(index, res_all.hdr.item_present);
746 }
747
748 /* Store a bool in a bit field */
749 void store_bool(LEX *lc, RES_ITEM *item, int index, int pass)
750 {
751    lex_get_token(lc, T_NAME);
752    if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
753       *(bool *)(item->value) = true;
754    } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
755       *(bool *)(item->value) = false;
756    } else {
757       scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */
758       return;
759    }
760    scan_to_eol(lc);
761    set_bit(index, res_all.hdr.item_present);
762 }
763
764
765 /*
766  * Store Tape Label Type (Bacula, ANSI, IBM)
767  *
768  */
769 void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
770 {
771    int token, i;
772
773    token = lex_get_token(lc, T_NAME);
774    /* Store the label pass 2 so that type is defined */
775    for (i=0; tapelabels[i].name; i++) {
776       if (strcasecmp(lc->str, tapelabels[i].name) == 0) {
777          *(uint32_t *)(item->value) = tapelabels[i].token;
778          i = 0;
779          break;
780       }
781    }
782    if (i != 0) {
783       scan_err1(lc, _("Expected a Tape Label keyword, got: %s"), lc->str);
784       return;
785    }
786    scan_to_eol(lc);
787    set_bit(index, res_all.hdr.item_present);
788 }
789
790
791 /* Parser state */
792 enum parse_state {
793    p_none,
794    p_resource
795 };
796
797 CONFIG *new_config_parser()
798 {
799    CONFIG *config;
800    config = (CONFIG *)malloc(sizeof(CONFIG));
801    memset(config, 0, sizeof(CONFIG));
802    return config;
803 }
804
805 void CONFIG::init(
806    const char *cf,
807    LEX_ERROR_HANDLER *scan_error,
808    int32_t err_type,
809    void *vres_all,
810    int32_t res_all_size,
811    int32_t r_first,
812    int32_t r_last,
813    RES_TABLE *resources,
814    RES **res_head)
815 {
816    m_cf = cf;
817    m_scan_error = scan_error;
818    m_err_type = err_type;
819    m_res_all = vres_all;
820    m_res_all_size = res_all_size;
821    m_r_first = r_first;
822    m_r_last = r_last;
823    m_resources = resources;
824    m_res_head = res_head;
825 }
826
827 /*********************************************************************
828  *
829  * Parse configuration file
830  *
831  * Return 0 if reading failed, 1 otherwise
832  *  Note, the default behavior unless you have set an alternate
833  *  scan_error handler is to die on an error.
834  */
835 #ifdef xxx
836 int
837 parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error, int err_type)
838 {
839    int ok;
840    CONFIG *config = new_config_parser();
841    config->init(cf, scan_error, err_type, (void *)&res_all, res_all_size,    
842                 r_first, r_last, resources, res_head);
843    ok = config->parse_config();
844    free(config);
845    return ok;
846 }
847 #endif
848       
849    
850 bool CONFIG::parse_config()
851 {
852    LEX *lc = NULL;
853    int token, i, pass;
854    int res_type = 0;
855    enum parse_state state = p_none;
856    RES_ITEM *items = NULL;
857    int level = 0;
858    static bool first = true;
859    int errstat;
860    const char *cf = m_cf;
861    LEX_ERROR_HANDLER *scan_error = m_scan_error;
862    int err_type = m_err_type;
863
864    if (first && (errstat=rwl_init(&res_lock)) != 0) {
865       berrno be;
866       Jmsg1(NULL, M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"),
867             be.bstrerror(errstat));
868    }
869    first = false;
870
871    char *full_path = (char *)alloca(MAX_PATH + 1);
872
873    if (!find_config_file(cf, full_path, MAX_PATH +1)) {
874       Jmsg0(NULL, M_ABORT, 0, _("Config filename too long.\n"));
875    }
876    cf = full_path;
877
878    /* Make two passes. The first builds the name symbol table,
879     * and the second picks up the items.
880     */
881    Dmsg0(900, "Enter parse_config()\n");
882    for (pass=1; pass <= 2; pass++) {
883       Dmsg1(900, "parse_config pass %d\n", pass);
884       if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) {
885          berrno be;
886          /* We must create a lex packet to print the error */
887          lc = (LEX *)malloc(sizeof(LEX));
888          memset(lc, 0, sizeof(LEX));
889          if (scan_error) {
890             lc->scan_error = scan_error;
891          } else {
892             lex_set_default_error_handler(lc);
893          }
894          lex_set_error_handler_error_type(lc, err_type) ;
895          bstrncpy(lc->str, cf, sizeof(lc->str));
896          lc->fname = lc->str;
897          scan_err2(lc, _("Cannot open config file \"%s\": %s\n"),
898             lc->str, be.bstrerror());
899          free(lc);
900          return 0;
901       }
902       lex_set_error_handler_error_type(lc, err_type) ;
903       while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
904          Dmsg3(900, "parse state=%d pass=%d got token=%s\n", state, pass,
905               lex_tok_to_str(token));
906          switch (state) {
907          case p_none:
908             if (token == T_EOL) {
909                break;
910             } else if (token == T_UTF8_BOM) {
911                /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */
912                break;
913             } else if (token == T_UTF16_BOM) {
914                scan_err0(lc, _("Currently we cannot handle UTF-16 source files. "
915                    "Please convert the conf file to UTF-8\n"));
916                goto bail_out;
917             } else if (token != T_IDENTIFIER) {
918                scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
919                goto bail_out;
920             }
921             for (i=0; resources[i].name; i++) {
922                if (strcasecmp(resources[i].name, lc->str) == 0) {
923                   items = resources[i].items;
924                   if (!items) {
925                      break;
926                   }
927                   state = p_resource;
928                   res_type = resources[i].rcode;
929                   init_resource(this, res_type, items, pass);
930                   break;
931                }
932             }
933             if (state == p_none) {
934                scan_err1(lc, _("expected resource name, got: %s"), lc->str);
935                goto bail_out;
936             }
937             break;
938          case p_resource:
939             switch (token) {
940             case T_BOB:
941                level++;
942                break;
943             case T_IDENTIFIER:
944                if (level != 1) {
945                   scan_err1(lc, _("not in resource definition: %s"), lc->str);
946                   goto bail_out;
947                }
948                for (i=0; items[i].name; i++) {
949                   if (strcasecmp(items[i].name, lc->str) == 0) {
950                      /* If the ITEM_NO_EQUALS flag is set we do NOT
951                       *   scan for = after the keyword  */
952                      if (!(items[i].flags & ITEM_NO_EQUALS)) {
953                         token = lex_get_token(lc, T_SKIP_EOL);
954                         Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
955                         if (token != T_EQUALS) {
956                            scan_err1(lc, _("expected an equals, got: %s"), lc->str);
957                            goto bail_out;
958                         }
959                      }
960                      Dmsg1(800, "calling handler for %s\n", items[i].name);
961                      /* Call item handler */
962                      items[i].handler(lc, &items[i], i, pass);
963                      i = -1;
964                      break;
965                   }
966                }
967                if (i >= 0) {
968                   Dmsg2(900, "level=%d id=%s\n", level, lc->str);
969                   Dmsg1(900, "Keyword = %s\n", lc->str);
970                   scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
971                      "Perhaps you left the trailing brace off of the previous resource."), lc->str);
972                   goto bail_out;
973                }
974                break;
975
976             case T_EOB:
977                level--;
978                state = p_none;
979                Dmsg0(900, "T_EOB => define new resource\n");
980                if (res_all.hdr.name == NULL) {
981                   scan_err0(lc, _("Name not specified for resource"));
982                   goto bail_out;
983                }
984                save_resource(res_type, items, pass);  /* save resource */
985                break;
986
987             case T_EOL:
988                break;
989
990             default:
991                scan_err2(lc, _("unexpected token %d %s in resource definition"),
992                   token, lex_tok_to_str(token));
993                goto bail_out;
994             }
995             break;
996          default:
997             scan_err1(lc, _("Unknown parser state %d\n"), state);
998             goto bail_out;
999          }
1000       }
1001       if (state != p_none) {
1002          scan_err0(lc, _("End of conf file reached with unclosed resource."));
1003          goto bail_out;
1004       }
1005       if (debug_level >= 900 && pass == 2) {
1006          int i;
1007          for (i=m_r_first; i<=m_r_last; i++) {
1008             dump_resource(i, m_res_head[i-m_r_first], prtmsg, NULL);
1009          }
1010       }
1011       lc = lex_close_file(lc);
1012    }
1013    Dmsg0(900, "Leave parse_config()\n");
1014    return 1;
1015 bail_out:
1016    if (lc) {
1017       lc = lex_close_file(lc);
1018    }
1019    return 0;
1020 }
1021
1022 const char *get_default_configdir()
1023 {
1024 #if defined(HAVE_WIN32)
1025    HRESULT hr;
1026    static char szConfigDir[MAX_PATH + 1] = { 0 };
1027
1028    if (!p_SHGetFolderPath) {
1029       bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1030       return szConfigDir;
1031    }
1032
1033    if (szConfigDir[0] == '\0') {
1034       hr = p_SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szConfigDir);
1035
1036       if (SUCCEEDED(hr)) {
1037          bstrncat(szConfigDir, "\\Bacula", sizeof(szConfigDir));
1038       } else {
1039          bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1040       }
1041    }
1042    return szConfigDir;
1043 #else
1044    return SYSCONFDIR;
1045 #endif
1046 }
1047
1048 /*
1049  * Returns false on error
1050  *         true  on OK, with full_path set to where config file should be 
1051  */
1052 static bool
1053 find_config_file(const char *config_file, char *full_path, int max_path)
1054 {
1055    int file_length = strlen(config_file) + 1;
1056
1057    /* If a full path specified, use it */
1058    if (first_path_separator(config_file) != NULL) {
1059       if (file_length > max_path) {
1060          return false;
1061       }
1062       bstrncpy(full_path, config_file, file_length);
1063       return true;
1064    }
1065
1066    /* config_file is default file name, now find default dir */
1067    const char *config_dir = get_default_configdir();
1068    int dir_length = strlen(config_dir);
1069
1070    if ((dir_length + 1 + file_length) > max_path) {
1071       return false;
1072    }
1073
1074    memcpy(full_path, config_dir, dir_length + 1);
1075
1076    if (!IsPathSeparator(full_path[dir_length - 1])) {
1077       full_path[dir_length++] = '/';
1078    }
1079
1080    memcpy(&full_path[dir_length], config_file, file_length);
1081
1082    return true;
1083 }
1084
1085 /*********************************************************************
1086  *
1087  *      Free configuration resources
1088  *
1089  */
1090 void CONFIG::free_resources()
1091 {
1092    for (int i=m_r_first; i<=m_r_last; i++) {
1093       free_resource(m_res_head[i-m_r_first], i);
1094       m_res_head[i-m_r_first] = NULL;
1095    }
1096 }
1097
1098 RES **CONFIG::save_resources()
1099 {
1100    int num = m_r_last - m_r_first + 1;
1101    RES **res = (RES **)malloc(num*sizeof(RES *));
1102    for (int i=0; i<num; i++) {
1103       res[i] = m_res_head[i];
1104       m_res_head[i] = NULL;
1105    }
1106    return res;
1107 }
1108
1109 RES **CONFIG::new_res_head()
1110 {
1111    int size = (m_r_last - m_r_first + 1) * sizeof(RES *);
1112    RES **res = (RES **)malloc(size);
1113    memset(res, 0, size);
1114    return res;
1115 }
1116
1117
1118 #ifdef xxx
1119 void free_config_resources()
1120 {
1121    for (int i=r_first; i<=r_last; i++) {
1122       free_resource(res_head[i-r_first], i);
1123       res_head[i-r_first] = NULL;
1124    }
1125 }
1126
1127 RES **save_config_resources()
1128 {
1129    int num = r_last - r_first + 1;
1130    RES **res = (RES **)malloc(num*sizeof(RES *));
1131    for (int i=0; i<num; i++) {
1132       res[i] = res_head[i];
1133       res_head[i] = NULL;
1134    }
1135    return res;
1136 }
1137
1138 RES **new_res_head()
1139 {
1140    int size = (r_last - r_first + 1) * sizeof(RES *);
1141    RES **res = (RES **)malloc(size);
1142    memset(res, 0, size);
1143    return res;
1144 }
1145 #endif