]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/lex.c
Convert to pure GPL v2 license.
[bacula/bacula] / bacula / src / lib / lex.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 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 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.
27 */
28 /*
29  * Lexical scanner for Bacula configuration file
30  *
31  *   Kern Sibbald, 2000
32  *
33  *   Version $Id$
34  *
35  */
36
37 #include "bacula.h"
38 #include "lex.h"
39
40 extern int debug_level;
41
42 /* Debug level for this source file */
43 static const int dbglvl = 5000;
44
45 /*
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).
49  */
50 void scan_to_eol(LEX *lc)
51 {
52    int token;
53    Dmsg0(dbglvl, "start scan to eof\n");
54    while ((token = lex_get_token(lc, T_ALL)) != T_EOL) {
55       if (token == T_EOB) {
56          lex_unget_char(lc);
57          return;
58       }
59    }
60 }
61
62 /*
63  * Get next token, but skip EOL
64  */
65 int scan_to_next_not_eol(LEX * lc)
66 {
67    int token;
68    do {
69       token = lex_get_token(lc, T_ALL);
70    } while (token == T_EOL);
71    return token;
72 }
73
74 /*
75  * Format a scanner error message
76  */
77 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
78 {
79    va_list arg_ptr;
80    char buf[MAXSTRING];
81    char more[MAXSTRING];
82
83    va_start(arg_ptr, msg);
84    bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
85    va_end(arg_ptr);
86
87    if (lc->err_type == 0) {     /* M_ERROR_TERM by default */
88       lc->err_type = M_ERROR_TERM;
89    }
90
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);
94    } else {
95       more[0] = 0;
96    }  
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);
101    } else {
102       e_msg(file, line, lc->err_type, 0, _("Config error: %s\n"), buf);
103    }
104 }
105
106 void lex_set_default_error_handler(LEX *lf)
107 {
108    lf->scan_error = s_err;
109 }
110
111 /*
112  * Set err_type used in error_handler
113  * return the old value
114  */
115 int lex_set_error_handler_error_type(LEX *lf, int err_type)
116 {
117    int old = lf->err_type;
118    lf->err_type = err_type;
119    return old;
120 }
121
122 /*
123  * Free the current file, and retrieve the contents
124  * of the previous packet if any.
125  */
126 LEX *lex_close_file(LEX *lf)
127 {
128    LEX *of;
129
130    if (lf == NULL) {
131       Emsg0(M_ABORT, 0, _("Close of NULL file\n"));
132    }
133    Dmsg1(dbglvl, "Close lex file: %s\n", lf->fname);
134
135    of = lf->next;
136    if (lf->bpipe) {
137       close_bpipe(lf->bpipe);
138       lf->bpipe = NULL;
139    } else {
140       fclose(lf->fd);
141    }
142    Dmsg1(dbglvl, "Close cfg file %s\n", lf->fname);
143    free(lf->fname);
144    if (of) {
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);
148    } else {
149       of = lf;
150       lf = NULL;
151    }
152    free(of);
153    return lf;
154 }
155
156 /*
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
164  * the next field.
165  *
166  */
167 LEX *lex_open_file(LEX *lf, const char *filename, LEX_ERROR_HANDLER *scan_error)
168
169 {
170    LEX *nf;
171    FILE *fd;
172    BPIPE *bpipe = NULL;
173    char *fname = bstrdup(filename);
174
175
176    if (fname[0] == '|') {
177       if ((bpipe = open_bpipe(fname, 0, "rb")) == NULL) {
178          free(fname);
179          return NULL;
180       }
181       fd = bpipe->rfd;
182    } else if ((fd = fopen(fname, "rb")) == NULL) {
183       free(fname);
184       return NULL;
185    }
186    Dmsg1(400, "Open config file: %s\n", fname);
187    nf = (LEX *)malloc(sizeof(LEX));
188    if (lf) {
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 */
193    } else {
194       lf = nf;                        /* start new packet */
195       memset(lf, 0, sizeof(LEX));
196       lex_set_error_handler_error_type(lf, M_ERROR_TERM);
197    }
198    if (scan_error) {
199       lf->scan_error = scan_error;
200    } else {
201       lex_set_default_error_handler(lf);
202    }
203    lf->fd = fd;
204    lf->bpipe = bpipe;
205    lf->fname = fname;
206    lf->state = lex_none;
207    lf->ch = L_EOL;
208    Dmsg1(dbglvl, "Return lex=%x\n", lf);
209    return lf;
210 }
211
212 /*
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
217  */
218 int lex_get_char(LEX *lf)
219 {
220    if (lf->ch == L_EOF) {
221       Emsg0(M_ABORT, 0, _("get_char: called after EOF\n"));
222    }
223    if (lf->ch == L_EOL) {
224       if (bfgets(lf->line, MAXSTRING, lf->fd) == NULL) {
225          lf->ch = L_EOF;
226          if (lf->next) {
227             lex_close_file(lf);
228          }
229          return lf->ch;
230       }
231       lf->line_no++;
232       lf->col_no = 0;
233       Dmsg2(1000, "fget line=%d %s", lf->line_no, lf->line);
234    }
235    lf->ch = (uint8_t)lf->line[lf->col_no];
236    if (lf->ch == 0) {
237       lf->ch = L_EOL;
238    } else {
239       lf->col_no++;
240    }
241    Dmsg2(dbglvl, "lex_get_char: %c %d\n", lf->ch, lf->ch);
242    return lf->ch;
243 }
244
245 void lex_unget_char(LEX *lf)
246 {
247    if (lf->ch == L_EOL) {
248       lf->ch = 0;                     /* End of line, force read of next one */
249    } else {
250       lf->col_no--;                   /* Backup to re-read char */
251    }
252
253 }
254
255
256 /*
257  * Add a character to the current string
258  */
259 static void add_str(LEX *lf, int ch)
260 {
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);
265    }
266    lf->str[lf->str_len++] = ch;
267    lf->str[lf->str_len] = 0;
268 }
269
270 /*
271  * Begin the string
272  */
273 static void begin_str(LEX *lf, int ch)
274 {
275    lf->str_len = 0;
276    lf->str[0] = 0;
277    if (ch != 0) {
278       add_str(lf, ch);
279    }
280    lf->begin_line_no = lf->line_no;   /* save start string line no */
281 }
282
283 #ifdef DEBUG
284 static const char *lex_state_to_str(int state)
285 {
286    switch (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    case lex_utf8_bom:      return _("UTF-8 Byte Order Mark");
295    case lex_utf16_le_bom:  return _("UTF-16le Byte Order Mark");
296    default:                return "??????";
297    }
298 }
299 #endif
300
301 /*
302  * Convert a lex token to a string
303  * used for debug/error printing.
304  */
305 const char *lex_tok_to_str(int token)
306 {
307    switch(token) {
308    case L_EOF:             return "L_EOF";
309    case L_EOL:             return "L_EOL";
310    case T_NONE:            return "T_NONE";
311    case T_NUMBER:          return "T_NUMBER";
312    case T_IPADDR:          return "T_IPADDR";
313    case T_IDENTIFIER:      return "T_IDENTIFIER";
314    case T_UNQUOTED_STRING: return "T_UNQUOTED_STRING";
315    case T_QUOTED_STRING:   return "T_QUOTED_STRING";
316    case T_BOB:             return "T_BOB";
317    case T_EOB:             return "T_EOB";
318    case T_EQUALS:          return "T_EQUALS";
319    case T_ERROR:           return "T_ERROR";
320    case T_EOF:             return "T_EOF";
321    case T_COMMA:           return "T_COMMA";
322    case T_EOL:             return "T_EOL";
323    case T_UTF8_BOM:        return "T_UTF8_BOM";
324    case T_UTF16_BOM:       return "T_UTF16_BOM";
325    default:                return "??????";
326    }
327 }
328
329 static uint32_t scan_pint(LEX *lf, char *str)
330 {
331    int64_t val = 0;
332    if (!is_a_number(str)) {
333       scan_err1(lf, _("expected a positive integer number, got: %s"), str);
334       /* NOT REACHED */
335    } else {
336       errno = 0;
337       val = str_to_int64(str);
338       if (errno != 0 || val < 0) {
339          scan_err1(lf, _("expected a positive integer number, got: %s"), str);
340          /* NOT REACHED */
341       }
342    }
343    return (uint32_t)val;
344 }
345
346 /*
347  *
348  * Get the next token from the input
349  *
350  */
351 int
352 lex_get_token(LEX *lf, int expect)
353 {
354    int ch;
355    int token = T_NONE;
356    bool esc_next = false;
357    /* Unicode files, especially on Win32, may begin with a "Byte Order Mark"
358       to indicate which transmission format the file is in. The codepoint for
359       this mark is U+FEFF and is represented as the octets EF-BB-BF in UTF-8
360       and as FF-FE in UTF-16le(little endian) and  FE-FF in UTF-16(big endian).
361       We use a distinct state for UTF-8 and UTF-16le, and use bom_bytes_seen
362       to tell which byte we are expecting. */
363    int bom_bytes_seen = 0;
364
365    Dmsg0(dbglvl, "enter lex_get_token\n");
366    while (token == T_NONE) {
367       ch = lex_get_char(lf);
368       switch (lf->state) {
369       case lex_none:
370          Dmsg2(dbglvl, "Lex state lex_none ch=%d,%x\n", ch, ch);
371          if (B_ISSPACE(ch))
372             break;
373          if (B_ISALPHA(ch)) {
374             if (lf->options & LOPT_NO_IDENT || lf->options & LOPT_STRING) {
375                lf->state = lex_string;
376             } else {
377                lf->state = lex_identifier;
378             }
379             begin_str(lf, ch);
380             break;
381          }
382          if (B_ISDIGIT(ch)) {
383             if (lf->options & LOPT_STRING) {
384                lf->state = lex_string;
385             } else {
386                lf->state = lex_number;
387             }
388             begin_str(lf, ch);
389             break;
390          }
391          Dmsg0(dbglvl, "Enter lex_none switch\n");
392          switch (ch) {
393          case L_EOF:
394             token = T_EOF;
395             Dmsg0(dbglvl, "got L_EOF set token=T_EOF\n");
396             break;
397          case '#':
398             lf->state = lex_comment;
399             break;
400          case '{':
401             token = T_BOB;
402             begin_str(lf, ch);
403             break;
404          case '}':
405             token = T_EOB;
406             begin_str(lf, ch);
407             break;
408          case '"':
409             lf->state = lex_quoted_string;
410             begin_str(lf, 0);
411             break;
412          case '=':
413             token = T_EQUALS;
414             begin_str(lf, ch);
415             break;
416          case ',':
417             token = T_COMMA;
418             begin_str(lf, ch);
419             break;
420          case ';':
421             if (expect != T_SKIP_EOL) {
422                token = T_EOL;      /* treat ; like EOL */
423             }
424             break;
425          case L_EOL:
426             Dmsg0(dbglvl, "got L_EOL set token=T_EOL\n");
427             if (expect != T_SKIP_EOL) {
428                token = T_EOL;
429             }
430             break;
431          case '@':
432             lf->state = lex_include;
433             begin_str(lf, 0);
434             break;
435          case 0xEF: /* probably a UTF-8 BOM */
436          case 0xFF: /* probably a UTF-16le BOM */
437          case 0xFE: /* probably a UTF-16be BOM (error)*/
438             if (lf->line_no != 1 || lf->col_no != 1)
439             {
440                lf->state = lex_string;
441                begin_str(lf, ch);
442             } else {
443                bom_bytes_seen = 1;
444                if (ch == 0xEF) {
445                   lf->state = lex_utf8_bom;
446                } else if (ch == 0xFF) {
447                   lf->state = lex_utf16_le_bom;
448                } else {
449                   scan_err0(lf, _("This config file appears to be in an "
450                      "unsupported Unicode format (UTF-16be). Please resave as UTF-8\n"));
451                   return T_ERROR;
452                }
453             }
454             break;
455          default:
456             lf->state = lex_string;
457             begin_str(lf, ch);
458             break;
459          }
460          break;
461       case lex_comment:
462          Dmsg1(dbglvl, "Lex state lex_comment ch=%x\n", ch);
463          if (ch == L_EOL) {
464             lf->state = lex_none;
465             if (expect != T_SKIP_EOL) {
466                token = T_EOL;
467             }
468          } else if (ch == L_EOF) {
469             token = T_ERROR;
470          }
471          break;
472       case lex_number:
473          Dmsg2(dbglvl, "Lex state lex_number ch=%x %c\n", ch, ch);
474          if (ch == L_EOF) {
475             token = T_ERROR;
476             break;
477          }
478          /* Might want to allow trailing specifications here */
479          if (B_ISDIGIT(ch)) {
480             add_str(lf, ch);
481             break;
482          }
483
484          /* A valid number can be terminated by the following */
485          if (B_ISSPACE(ch) || ch == L_EOL || ch == ',' || ch == ';') {
486             token = T_NUMBER;
487             lf->state = lex_none;
488          } else {
489             lf->state = lex_string;
490          }
491          lex_unget_char(lf);
492          break;
493       case lex_ip_addr:
494          if (ch == L_EOF) {
495             token = T_ERROR;
496             break;
497          }
498          Dmsg1(dbglvl, "Lex state lex_ip_addr ch=%x\n", ch);
499          break;
500       case lex_string:
501          Dmsg1(dbglvl, "Lex state lex_string ch=%x\n", ch);
502          if (ch == L_EOF) {
503             token = T_ERROR;
504             break;
505          }
506          if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
507              ch == '\r' || ch == ';' || ch == ',' || ch == '#' || (B_ISSPACE(ch)) ) {
508             lex_unget_char(lf);
509             token = T_UNQUOTED_STRING;
510             lf->state = lex_none;
511             break;
512          }
513          add_str(lf, ch);
514          break;
515       case lex_identifier:
516          Dmsg2(dbglvl, "Lex state lex_identifier ch=%x %c\n", ch, ch);
517          if (B_ISALPHA(ch)) {
518             add_str(lf, ch);
519             break;
520          } else if (B_ISSPACE(ch)) {
521             break;
522          } else if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
523                     ch == '\r' || ch == ';' || ch == ','   || ch == '"' || ch == '#') {
524             lex_unget_char(lf);
525             token = T_IDENTIFIER;
526             lf->state = lex_none;
527             break;
528          } else if (ch == L_EOF) {
529             token = T_ERROR;
530             lf->state = lex_none;
531             begin_str(lf, ch);
532             break;
533          }
534          /* Some non-alpha character => string */
535          lf->state = lex_string;
536          add_str(lf, ch);
537          break;
538       case lex_quoted_string:
539          Dmsg2(dbglvl, "Lex state lex_quoted_string ch=%x %c\n", ch, ch);
540          if (ch == L_EOF) {
541             token = T_ERROR;
542             break;
543          }
544          if (ch == L_EOL) {
545             esc_next = false;
546             break;
547          }
548          if (esc_next) {
549             add_str(lf, ch);
550             esc_next = false;
551             break;
552          }
553          if (ch == '\\') {
554             esc_next = true;
555             break;
556          }
557          if (ch == '"') {
558             token = T_QUOTED_STRING;
559             lf->state = lex_none;
560             break;
561          }
562          add_str(lf, ch);
563          break;
564       case lex_include:            /* scanning a filename */
565          if (ch == L_EOF) {
566             token = T_ERROR;
567             break;
568          }
569          if (B_ISSPACE(ch) || ch == '\n' || ch == L_EOL || ch == '}' || ch == '{' ||
570              ch == ';' || ch == ','   || ch == '"' || ch == '#') {
571             /* Keep the original LEX so we can print an error if the included file can't be opened. */
572             LEX* lfori = lf;
573
574             lf->state = lex_none;
575             lf = lex_open_file(lf, lf->str, lf->scan_error);
576             if (lf == NULL) {
577                berrno be;
578                scan_err2(lfori, _("Cannot open included config file %s: %s\n"),
579                   lfori->str, be.bstrerror());
580                return T_ERROR;
581             }
582             break;
583          }
584          add_str(lf, ch);
585          break;
586       case lex_utf8_bom:
587          /* we only end up in this state if we have read an 0xEF 
588             as the first byte of the file, indicating we are probably
589             reading a UTF-8 file */
590          if (ch == 0xBB && bom_bytes_seen == 1) {
591             bom_bytes_seen++;
592          } else if (ch == 0xBF && bom_bytes_seen == 2) {
593             token = T_UTF8_BOM;
594             lf->state = lex_none;
595          } else {
596             token = T_ERROR;
597          }
598          break;
599       case lex_utf16_le_bom:
600          /* we only end up in this state if we have read an 0xFF 
601             as the first byte of the file -- indicating that we are
602             probably dealing with an Intel based (little endian) UTF-16 file*/
603          if (ch == 0xFE) {
604             token = T_UTF16_BOM;
605             lf->state = lex_none;
606          } else {
607             token = T_ERROR;
608          }
609          break;
610       }
611       Dmsg4(dbglvl, "ch=%d state=%s token=%s %c\n", ch, lex_state_to_str(lf->state),
612         lex_tok_to_str(token), ch);
613    }
614    Dmsg2(dbglvl, "lex returning: line %d token: %s\n", lf->line_no, lex_tok_to_str(token));
615    lf->token = token;
616
617    /*
618     * Here is where we check to see if the user has set certain
619     *  expectations (e.g. 32 bit integer). If so, we do type checking
620     *  and possible additional scanning (e.g. for range).
621     */
622    switch (expect) {
623    case T_PINT32:
624       lf->pint32_val = scan_pint(lf, lf->str);
625       lf->pint32_val2 = lf->pint32_val;
626       token = T_PINT32;
627       break;
628
629    case T_PINT32_RANGE:
630       if (token == T_NUMBER) {
631          lf->pint32_val = scan_pint(lf, lf->str);
632          lf->pint32_val2 = lf->pint32_val;
633          token = T_PINT32;
634       } else {
635          char *p = strchr(lf->str, '-');
636          if (!p) {
637             scan_err2(lf, _("expected an integer or a range, got %s: %s"),
638                lex_tok_to_str(token), lf->str);
639             token = T_ERROR;
640             break;
641          }
642          *p++ = 0;                       /* terminate first half of range */
643          lf->pint32_val  = scan_pint(lf, lf->str);
644          lf->pint32_val2 = scan_pint(lf, p);
645          token = T_PINT32_RANGE;
646       }
647       break;
648
649    case T_INT32:
650       if (token != T_NUMBER || !is_a_number(lf->str)) {
651          scan_err2(lf, _("expected an integer number, got %s: %s"),
652                lex_tok_to_str(token), lf->str);
653          token = T_ERROR;
654          break;
655       }
656       errno = 0;
657       lf->int32_val = (int32_t)str_to_int64(lf->str);
658       if (errno != 0) {
659          scan_err2(lf, _("expected an integer number, got %s: %s"),
660                lex_tok_to_str(token), lf->str);
661          token = T_ERROR;
662       } else {
663          token = T_INT32;
664       }
665       break;
666
667    case T_INT64:
668       Dmsg2(dbglvl, "int64=:%s: %f\n", lf->str, strtod(lf->str, NULL));
669       if (token != T_NUMBER || !is_a_number(lf->str)) {
670          scan_err2(lf, _("expected an integer number, got %s: %s"),
671                lex_tok_to_str(token), lf->str);
672          token = T_ERROR;
673          break;
674       }
675       errno = 0;
676       lf->int64_val = str_to_int64(lf->str);
677       if (errno != 0) {
678          scan_err2(lf, _("expected an integer number, got %s: %s"),
679                lex_tok_to_str(token), lf->str);
680          token = T_ERROR;
681       } else {
682          token = T_INT64;
683       }
684       break;
685
686    case T_NAME:
687       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
688          scan_err2(lf, _("expected a name, got %s: %s"),
689                lex_tok_to_str(token), lf->str);
690          token = T_ERROR;
691       } else if (lf->str_len > MAX_RES_NAME_LENGTH) {
692          scan_err3(lf, _("name %s length %d too long, max is %d\n"), lf->str,
693             lf->str_len, MAX_RES_NAME_LENGTH);
694          token = T_ERROR;
695       }
696       break;
697
698    case T_STRING:
699       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
700          scan_err2(lf, _("expected a string, got %s: %s"),
701                lex_tok_to_str(token), lf->str);
702          token = T_ERROR;
703       } else {
704          token = T_STRING;
705       }
706       break;
707
708
709    default:
710       break;                          /* no expectation given */
711    }
712    lf->token = token;                 /* set possible new token */
713    return token;
714 }