]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/parse_conf.c
Implement store_size32 and store_size64
[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 two of the GNU 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 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                return 0;
917             } else if (token != T_IDENTIFIER) {
918                scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str);
919                return 0;
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                return 0;
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                   return 0;
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                            return 0;
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                   return 0;
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                   return 0;
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                return 0;
994             }
995             break;
996          default:
997             scan_err1(lc, _("Unknown parser state %d\n"), state);
998             return 0;
999          }
1000       }
1001       if (state != p_none) {
1002          scan_err0(lc, _("End of conf file reached with unclosed resource."));
1003          return 0;
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 }
1016
1017 const char *get_default_configdir()
1018 {
1019 #if defined(HAVE_WIN32)
1020    HRESULT hr;
1021    static char szConfigDir[MAX_PATH + 1] = { 0 };
1022
1023    if (!p_SHGetFolderPath) {
1024       bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1025       return szConfigDir;
1026    }
1027
1028    if (szConfigDir[0] == '\0') {
1029       hr = p_SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szConfigDir);
1030
1031       if (SUCCEEDED(hr)) {
1032          bstrncat(szConfigDir, "\\Bacula", sizeof(szConfigDir));
1033       } else {
1034          bstrncpy(szConfigDir, DEFAULT_CONFIGDIR, sizeof(szConfigDir));
1035       }
1036    }
1037    return szConfigDir;
1038 #else
1039    return SYSCONFDIR;
1040 #endif
1041 }
1042
1043 /*
1044  * Returns false on error
1045  *         true  on OK, with full_path set to where config file should be 
1046  */
1047 static bool
1048 find_config_file(const char *config_file, char *full_path, int max_path)
1049 {
1050    int file_length = strlen(config_file) + 1;
1051
1052    /* If a full path specified, use it */
1053    if (first_path_separator(config_file) != NULL) {
1054       if (file_length > max_path) {
1055          return false;
1056       }
1057       bstrncpy(full_path, config_file, file_length);
1058       return true;
1059    }
1060
1061    /* config_file is default file name, now find default dir */
1062    const char *config_dir = get_default_configdir();
1063    int dir_length = strlen(config_dir);
1064
1065    if ((dir_length + 1 + file_length) > max_path) {
1066       return false;
1067    }
1068
1069    memcpy(full_path, config_dir, dir_length + 1);
1070
1071    if (!IsPathSeparator(full_path[dir_length - 1])) {
1072       full_path[dir_length++] = '/';
1073    }
1074
1075    memcpy(&full_path[dir_length], config_file, file_length);
1076
1077    return true;
1078 }
1079
1080 /*********************************************************************
1081  *
1082  *      Free configuration resources
1083  *
1084  */
1085 void CONFIG::free_resources()
1086 {
1087    for (int i=m_r_first; i<=m_r_last; i++) {
1088       free_resource(m_res_head[i-m_r_first], i);
1089       m_res_head[i-m_r_first] = NULL;
1090    }
1091 }
1092
1093 RES **CONFIG::save_resources()
1094 {
1095    int num = m_r_last - m_r_first + 1;
1096    RES **res = (RES **)malloc(num*sizeof(RES *));
1097    for (int i=0; i<num; i++) {
1098       res[i] = m_res_head[i];
1099       m_res_head[i] = NULL;
1100    }
1101    return res;
1102 }
1103
1104 RES **CONFIG::new_res_head()
1105 {
1106    int size = (m_r_last - m_r_first + 1) * sizeof(RES *);
1107    RES **res = (RES **)malloc(size);
1108    memset(res, 0, size);
1109    return res;
1110 }
1111
1112
1113 #ifdef xxx
1114 void free_config_resources()
1115 {
1116    for (int i=r_first; i<=r_last; i++) {
1117       free_resource(res_head[i-r_first], i);
1118       res_head[i-r_first] = NULL;
1119    }
1120 }
1121
1122 RES **save_config_resources()
1123 {
1124    int num = r_last - r_first + 1;
1125    RES **res = (RES **)malloc(num*sizeof(RES *));
1126    for (int i=0; i<num; i++) {
1127       res[i] = res_head[i];
1128       res_head[i] = NULL;
1129    }
1130    return res;
1131 }
1132
1133 RES **new_res_head()
1134 {
1135    int size = (r_last - r_first + 1) * sizeof(RES *);
1136    RES **res = (RES **)malloc(size);
1137    memset(res, 0, size);
1138    return res;
1139 }
1140 #endif