2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Lexical scanner for Bacula configuration file
40 extern int debug_level;
42 /* Debug level for this source file */
43 static const int dbglvl = 5000;
46 * Scan to "logical" end of line. I.e. end of line,
47 * or semicolon, but stop on T_EOB (same as end of
48 * line except it is not eaten).
50 void scan_to_eol(LEX *lc)
53 Dmsg0(dbglvl, "start scan to eof\n");
54 while ((token = lex_get_token(lc, T_ALL)) != T_EOL) {
63 * Get next token, but skip EOL
65 int scan_to_next_not_eol(LEX * lc)
69 token = lex_get_token(lc, T_ALL);
70 } while (token == T_EOL);
75 * Format a scanner error message
77 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
83 va_start(arg_ptr, msg);
84 bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
87 if (lc->err_type == 0) { /* M_ERROR_TERM by default */
88 lc->err_type = M_ERROR_TERM;
91 if (lc->line_no > lc->begin_line_no) {
92 bsnprintf(more, sizeof(more),
93 _("Problem probably begins at line %d.\n"), lc->begin_line_no);
97 if (lc->line_no > 0) {
98 e_msg(file, line, lc->err_type, 0, _("Config error: %s\n"
99 " : line %d, col %d of file %s\n%s\n%s"),
100 buf, lc->line_no, lc->col_no, lc->fname, lc->line, more);
102 e_msg(file, line, lc->err_type, 0, _("Config error: %s\n"), buf);
106 void lex_set_default_error_handler(LEX *lf)
108 lf->scan_error = s_err;
112 * Set err_type used in error_handler
113 * return the old value
115 int lex_set_error_handler_error_type(LEX *lf, int err_type)
117 int old = lf->err_type;
118 lf->err_type = err_type;
123 * Free the current file, and retrieve the contents
124 * of the previous packet if any.
126 LEX *lex_close_file(LEX *lf)
131 Emsg0(M_ABORT, 0, _("Close of NULL file\n"));
133 Dmsg1(dbglvl, "Close lex file: %s\n", lf->fname);
137 close_bpipe(lf->bpipe);
142 Dmsg1(dbglvl, "Close cfg file %s\n", lf->fname);
145 of->options = lf->options; /* preserve options */
146 memcpy(lf, of, sizeof(LEX));
147 Dmsg1(dbglvl, "Restart scan of cfg file %s\n", of->fname);
157 * Open a new configuration file. We push the
158 * state of the current file (lf) so that we
159 * can do includes. This is a bit of a hammer.
160 * Instead of passing back the pointer to the
161 * new packet, I simply replace the contents
162 * of the caller's packet with the new packet,
163 * and link the contents of the old packet into
167 LEX *lex_open_file(LEX *lf, const char *filename, LEX_ERROR_HANDLER *scan_error)
173 char *fname = bstrdup(filename);
176 if (fname[0] == '|') {
177 if ((bpipe = open_bpipe(fname, 0, "rb")) == NULL) {
182 } else if ((fd = fopen(fname, "rb")) == NULL) {
186 Dmsg1(400, "Open config file: %s\n", fname);
187 nf = (LEX *)malloc(sizeof(LEX));
189 memcpy(nf, lf, sizeof(LEX));
190 memset(lf, 0, sizeof(LEX));
191 lf->next = nf; /* if have lf, push it behind new one */
192 lf->options = nf->options; /* preserve user options */
194 lf = nf; /* start new packet */
195 memset(lf, 0, sizeof(LEX));
196 lex_set_error_handler_error_type(lf, M_ERROR_TERM);
199 lf->scan_error = scan_error;
201 lex_set_default_error_handler(lf);
206 lf->state = lex_none;
208 Dmsg1(dbglvl, "Return lex=%x\n", lf);
213 * Get the next character from the input.
214 * Returns the character or
215 * L_EOF if end of file
216 * L_EOL if end of line
218 int lex_get_char(LEX *lf)
220 if (lf->ch == L_EOF) {
221 Emsg0(M_ABORT, 0, _("get_char: called after EOF\n"));
223 if (lf->ch == L_EOL) {
224 if (bfgets(lf->line, MAXSTRING, lf->fd) == NULL) {
233 Dmsg2(1000, "fget line=%d %s", lf->line_no, lf->line);
235 lf->ch = (uint8_t)lf->line[lf->col_no];
241 Dmsg2(dbglvl, "lex_get_char: %c %d\n", lf->ch, lf->ch);
245 void lex_unget_char(LEX *lf)
247 if (lf->ch == L_EOL) {
248 lf->ch = 0; /* End of line, force read of next one */
250 lf->col_no--; /* Backup to re-read char */
257 * Add a character to the current string
259 static void add_str(LEX *lf, int ch)
261 if (lf->str_len >= MAXSTRING-3) {
262 Emsg3(M_ERROR_TERM, 0, _(
263 _("Config token too long, file: %s, line %d, begins at line %d\n")),
264 lf->fname, lf->line_no, lf->begin_line_no);
266 lf->str[lf->str_len++] = ch;
267 lf->str[lf->str_len] = 0;
273 static void begin_str(LEX *lf, int ch)
280 lf->begin_line_no = lf->line_no; /* save start string line no */
284 static const char *lex_state_to_str(int state)
287 case lex_none: return _("none");
288 case lex_comment: return _("comment");
289 case lex_number: return _("number");
290 case lex_ip_addr: return _("ip_addr");
291 case lex_identifier: return _("identifier");
292 case lex_string: return _("string");
293 case lex_quoted_string: return _("quoted_string");
294 default: return "??????";
300 * Convert a lex token to a string
301 * used for debug/error printing.
303 const char *lex_tok_to_str(int token)
306 case L_EOF: return "L_EOF";
307 case L_EOL: return "L_EOL";
308 case T_NONE: return "T_NONE";
309 case T_NUMBER: return "T_NUMBER";
310 case T_IPADDR: return "T_IPADDR";
311 case T_IDENTIFIER: return "T_IDENTIFIER";
312 case T_UNQUOTED_STRING: return "T_UNQUOTED_STRING";
313 case T_QUOTED_STRING: return "T_QUOTED_STRING";
314 case T_BOB: return "T_BOB";
315 case T_EOB: return "T_EOB";
316 case T_EQUALS: return "T_EQUALS";
317 case T_ERROR: return "T_ERROR";
318 case T_EOF: return "T_EOF";
319 case T_COMMA: return "T_COMMA";
320 case T_EOL: return "T_EOL";
321 default: return "??????";
325 static uint32_t scan_pint(LEX *lf, char *str)
328 if (!is_a_number(str)) {
329 scan_err1(lf, _("expected a positive integer number, got: %s"), str);
333 val = str_to_int64(str);
334 if (errno != 0 || val < 0) {
335 scan_err1(lf, _("expected a positive integer number, got: %s"), str);
339 return (uint32_t)val;
344 * Get the next token from the input
348 lex_get_token(LEX *lf, int expect)
352 bool esc_next = false;
353 int unicode_count = 0;
355 Dmsg0(dbglvl, "enter lex_get_token\n");
356 while (token == T_NONE) {
357 ch = lex_get_char(lf);
360 Dmsg2(dbglvl, "Lex state lex_none ch=%d,%x\n", ch, ch);
364 if (lf->options & LOPT_NO_IDENT || lf->options & LOPT_STRING) {
365 lf->state = lex_string;
367 lf->state = lex_identifier;
373 if (lf->options & LOPT_STRING) {
374 lf->state = lex_string;
376 lf->state = lex_number;
381 Dmsg0(dbglvl, "Enter lex_none switch\n");
385 Dmsg0(dbglvl, "got L_EOF set token=T_EOF\n");
388 lf->state = lex_comment;
399 lf->state = lex_quoted_string;
411 if (expect != T_SKIP_EOL) {
412 token = T_EOL; /* treat ; like EOL */
416 Dmsg0(dbglvl, "got L_EOL set token=T_EOL\n");
417 if (expect != T_SKIP_EOL) {
422 lf->state = lex_include;
426 if (lf->line_no != 1 || lf->col_no != 1)
428 lf->state = lex_string;
432 lf->state = lex_unicode_mark;
436 lf->state = lex_string;
442 Dmsg1(dbglvl, "Lex state lex_comment ch=%x\n", ch);
444 lf->state = lex_none;
445 if (expect != T_SKIP_EOL) {
448 } else if (ch == L_EOF) {
453 Dmsg2(dbglvl, "Lex state lex_number ch=%x %c\n", ch, ch);
458 /* Might want to allow trailing specifications here */
464 /* A valid number can be terminated by the following */
465 if (B_ISSPACE(ch) || ch == L_EOL || ch == ',' || ch == ';') {
467 lf->state = lex_none;
469 lf->state = lex_string;
478 Dmsg1(dbglvl, "Lex state lex_ip_addr ch=%x\n", ch);
481 Dmsg1(dbglvl, "Lex state lex_string ch=%x\n", ch);
486 if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
487 ch == '\r' || ch == ';' || ch == ',' || ch == '#' || (B_ISSPACE(ch)) ) {
489 token = T_UNQUOTED_STRING;
490 lf->state = lex_none;
496 Dmsg2(dbglvl, "Lex state lex_identifier ch=%x %c\n", ch, ch);
500 } else if (B_ISSPACE(ch)) {
502 } else if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
503 ch == '\r' || ch == ';' || ch == ',' || ch == '"' || ch == '#') {
505 token = T_IDENTIFIER;
506 lf->state = lex_none;
508 } else if (ch == L_EOF) {
510 lf->state = lex_none;
514 /* Some non-alpha character => string */
515 lf->state = lex_string;
518 case lex_quoted_string:
519 Dmsg2(dbglvl, "Lex state lex_quoted_string ch=%x %c\n", ch, ch);
538 token = T_QUOTED_STRING;
539 lf->state = lex_none;
544 case lex_include: /* scanning a filename */
549 if (B_ISSPACE(ch) || ch == '\n' || ch == L_EOL || ch == '}' || ch == '{' ||
550 ch == ';' || ch == ',' || ch == '"' || ch == '#') {
551 /* Keep the original LEX so we can print an error if the included file can't be opened. */
554 lf->state = lex_none;
555 lf = lex_open_file(lf, lf->str, lf->scan_error);
558 scan_err2(lfori, _("Cannot open included config file %s: %s\n"),
559 lfori->str, be.strerror());
566 case lex_unicode_mark:
572 if (unicode_count == 2) {
577 } else if (unicode_count == 3) {
582 token = T_UNICODE_MARK;
583 lf->state = lex_none;
588 Dmsg4(dbglvl, "ch=%d state=%s token=%s %c\n", ch, lex_state_to_str(lf->state),
589 lex_tok_to_str(token), ch);
591 Dmsg2(dbglvl, "lex returning: line %d token: %s\n", lf->line_no, lex_tok_to_str(token));
595 * Here is where we check to see if the user has set certain
596 * expectations (e.g. 32 bit integer). If so, we do type checking
597 * and possible additional scanning (e.g. for range).
601 lf->pint32_val = scan_pint(lf, lf->str);
602 lf->pint32_val2 = lf->pint32_val;
607 if (token == T_NUMBER) {
608 lf->pint32_val = scan_pint(lf, lf->str);
609 lf->pint32_val2 = lf->pint32_val;
612 char *p = strchr(lf->str, '-');
614 scan_err2(lf, _("expected an integer or a range, got %s: %s"),
615 lex_tok_to_str(token), lf->str);
619 *p++ = 0; /* terminate first half of range */
620 lf->pint32_val = scan_pint(lf, lf->str);
621 lf->pint32_val2 = scan_pint(lf, p);
622 token = T_PINT32_RANGE;
627 if (token != T_NUMBER || !is_a_number(lf->str)) {
628 scan_err2(lf, _("expected an integer number, got %s: %s"),
629 lex_tok_to_str(token), lf->str);
634 lf->int32_val = (int32_t)str_to_int64(lf->str);
636 scan_err2(lf, _("expected an integer number, got %s: %s"),
637 lex_tok_to_str(token), lf->str);
645 Dmsg2(dbglvl, "int64=:%s: %f\n", lf->str, strtod(lf->str, NULL));
646 if (token != T_NUMBER || !is_a_number(lf->str)) {
647 scan_err2(lf, _("expected an integer number, got %s: %s"),
648 lex_tok_to_str(token), lf->str);
653 lf->int64_val = str_to_int64(lf->str);
655 scan_err2(lf, _("expected an integer number, got %s: %s"),
656 lex_tok_to_str(token), lf->str);
664 if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
665 scan_err2(lf, _("expected a name, got %s: %s"),
666 lex_tok_to_str(token), lf->str);
668 } else if (lf->str_len > MAX_RES_NAME_LENGTH) {
669 scan_err3(lf, _("name %s length %d too long, max is %d\n"), lf->str,
670 lf->str_len, MAX_RES_NAME_LENGTH);
676 if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
677 scan_err2(lf, _("expected a string, got %s: %s"),
678 lex_tok_to_str(token), lf->str);
687 break; /* no expectation given */
689 lf->token = token; /* set possible new token */