]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/lex.c
kes Remove a few malloc()s from the encryption code.
[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       /*
194        * preserve err_type to prevent bacula exiting on 'reload' 
195        * if config is invalid. Fixes bug #877         
196        */
197       lf->err_type = nf->err_type;    
198    } else {
199       lf = nf;                        /* start new packet */
200       memset(lf, 0, sizeof(LEX));
201       lex_set_error_handler_error_type(lf, M_ERROR_TERM);
202    }
203    if (scan_error) {
204       lf->scan_error = scan_error;
205    } else {
206       lex_set_default_error_handler(lf);
207    }
208    lf->fd = fd;
209    lf->bpipe = bpipe;
210    lf->fname = fname;
211    lf->state = lex_none;
212    lf->ch = L_EOL;
213    Dmsg1(dbglvl, "Return lex=%x\n", lf);
214    return lf;
215 }
216
217 /*
218  * Get the next character from the input.
219  *  Returns the character or
220  *    L_EOF if end of file
221  *    L_EOL if end of line
222  */
223 int lex_get_char(LEX *lf)
224 {
225    if (lf->ch == L_EOF) {
226       Emsg0(M_ABORT, 0, _("get_char: called after EOF\n"));
227    }
228    if (lf->ch == L_EOL) {
229       if (bfgets(lf->line, MAXSTRING, lf->fd) == NULL) {
230          lf->ch = L_EOF;
231          if (lf->next) {
232             lex_close_file(lf);
233          }
234          return lf->ch;
235       }
236       lf->line_no++;
237       lf->col_no = 0;
238       Dmsg2(1000, "fget line=%d %s", lf->line_no, lf->line);
239    }
240    lf->ch = (uint8_t)lf->line[lf->col_no];
241    if (lf->ch == 0) {
242       lf->ch = L_EOL;
243    } else {
244       lf->col_no++;
245    }
246    Dmsg2(dbglvl, "lex_get_char: %c %d\n", lf->ch, lf->ch);
247    return lf->ch;
248 }
249
250 void lex_unget_char(LEX *lf)
251 {
252    if (lf->ch == L_EOL) {
253       lf->ch = 0;                     /* End of line, force read of next one */
254    } else {
255       lf->col_no--;                   /* Backup to re-read char */
256    }
257
258 }
259
260
261 /*
262  * Add a character to the current string
263  */
264 static void add_str(LEX *lf, int ch)
265 {
266    if (lf->str_len >= MAXSTRING-3) {
267       Emsg3(M_ERROR_TERM, 0, _(
268            _("Config token too long, file: %s, line %d, begins at line %d\n")),
269              lf->fname, lf->line_no, lf->begin_line_no);
270    }
271    lf->str[lf->str_len++] = ch;
272    lf->str[lf->str_len] = 0;
273 }
274
275 /*
276  * Begin the string
277  */
278 static void begin_str(LEX *lf, int ch)
279 {
280    lf->str_len = 0;
281    lf->str[0] = 0;
282    if (ch != 0) {
283       add_str(lf, ch);
284    }
285    lf->begin_line_no = lf->line_no;   /* save start string line no */
286 }
287
288 #ifdef DEBUG
289 static const char *lex_state_to_str(int state)
290 {
291    switch (state) {
292    case lex_none:          return _("none");
293    case lex_comment:       return _("comment");
294    case lex_number:        return _("number");
295    case lex_ip_addr:       return _("ip_addr");
296    case lex_identifier:    return _("identifier");
297    case lex_string:        return _("string");
298    case lex_quoted_string: return _("quoted_string");
299    case lex_utf8_bom:      return _("UTF-8 Byte Order Mark");
300    case lex_utf16_le_bom:  return _("UTF-16le Byte Order Mark");
301    default:                return "??????";
302    }
303 }
304 #endif
305
306 /*
307  * Convert a lex token to a string
308  * used for debug/error printing.
309  */
310 const char *lex_tok_to_str(int token)
311 {
312    switch(token) {
313    case L_EOF:             return "L_EOF";
314    case L_EOL:             return "L_EOL";
315    case T_NONE:            return "T_NONE";
316    case T_NUMBER:          return "T_NUMBER";
317    case T_IPADDR:          return "T_IPADDR";
318    case T_IDENTIFIER:      return "T_IDENTIFIER";
319    case T_UNQUOTED_STRING: return "T_UNQUOTED_STRING";
320    case T_QUOTED_STRING:   return "T_QUOTED_STRING";
321    case T_BOB:             return "T_BOB";
322    case T_EOB:             return "T_EOB";
323    case T_EQUALS:          return "T_EQUALS";
324    case T_ERROR:           return "T_ERROR";
325    case T_EOF:             return "T_EOF";
326    case T_COMMA:           return "T_COMMA";
327    case T_EOL:             return "T_EOL";
328    case T_UTF8_BOM:        return "T_UTF8_BOM";
329    case T_UTF16_BOM:       return "T_UTF16_BOM";
330    default:                return "??????";
331    }
332 }
333
334 static uint32_t scan_pint(LEX *lf, char *str)
335 {
336    int64_t val = 0;
337    if (!is_a_number(str)) {
338       scan_err1(lf, _("expected a positive integer number, got: %s"), str);
339       /* NOT REACHED */
340    } else {
341       errno = 0;
342       val = str_to_int64(str);
343       if (errno != 0 || val < 0) {
344          scan_err1(lf, _("expected a positive integer number, got: %s"), str);
345          /* NOT REACHED */
346       }
347    }
348    return (uint32_t)val;
349 }
350
351 /*
352  *
353  * Get the next token from the input
354  *
355  */
356 int
357 lex_get_token(LEX *lf, int expect)
358 {
359    int ch;
360    int token = T_NONE;
361    bool esc_next = false;
362    /* Unicode files, especially on Win32, may begin with a "Byte Order Mark"
363       to indicate which transmission format the file is in. The codepoint for
364       this mark is U+FEFF and is represented as the octets EF-BB-BF in UTF-8
365       and as FF-FE in UTF-16le(little endian) and  FE-FF in UTF-16(big endian).
366       We use a distinct state for UTF-8 and UTF-16le, and use bom_bytes_seen
367       to tell which byte we are expecting. */
368    int bom_bytes_seen = 0;
369
370    Dmsg0(dbglvl, "enter lex_get_token\n");
371    while (token == T_NONE) {
372       ch = lex_get_char(lf);
373       switch (lf->state) {
374       case lex_none:
375          Dmsg2(dbglvl, "Lex state lex_none ch=%d,%x\n", ch, ch);
376          if (B_ISSPACE(ch))
377             break;
378          if (B_ISALPHA(ch)) {
379             if (lf->options & LOPT_NO_IDENT || lf->options & LOPT_STRING) {
380                lf->state = lex_string;
381             } else {
382                lf->state = lex_identifier;
383             }
384             begin_str(lf, ch);
385             break;
386          }
387          if (B_ISDIGIT(ch)) {
388             if (lf->options & LOPT_STRING) {
389                lf->state = lex_string;
390             } else {
391                lf->state = lex_number;
392             }
393             begin_str(lf, ch);
394             break;
395          }
396          Dmsg0(dbglvl, "Enter lex_none switch\n");
397          switch (ch) {
398          case L_EOF:
399             token = T_EOF;
400             Dmsg0(dbglvl, "got L_EOF set token=T_EOF\n");
401             break;
402          case '#':
403             lf->state = lex_comment;
404             break;
405          case '{':
406             token = T_BOB;
407             begin_str(lf, ch);
408             break;
409          case '}':
410             token = T_EOB;
411             begin_str(lf, ch);
412             break;
413          case '"':
414             lf->state = lex_quoted_string;
415             begin_str(lf, 0);
416             break;
417          case '=':
418             token = T_EQUALS;
419             begin_str(lf, ch);
420             break;
421          case ',':
422             token = T_COMMA;
423             begin_str(lf, ch);
424             break;
425          case ';':
426             if (expect != T_SKIP_EOL) {
427                token = T_EOL;      /* treat ; like EOL */
428             }
429             break;
430          case L_EOL:
431             Dmsg0(dbglvl, "got L_EOL set token=T_EOL\n");
432             if (expect != T_SKIP_EOL) {
433                token = T_EOL;
434             }
435             break;
436          case '@':
437             lf->state = lex_include;
438             begin_str(lf, 0);
439             break;
440          case 0xEF: /* probably a UTF-8 BOM */
441          case 0xFF: /* probably a UTF-16le BOM */
442          case 0xFE: /* probably a UTF-16be BOM (error)*/
443             if (lf->line_no != 1 || lf->col_no != 1)
444             {
445                lf->state = lex_string;
446                begin_str(lf, ch);
447             } else {
448                bom_bytes_seen = 1;
449                if (ch == 0xEF) {
450                   lf->state = lex_utf8_bom;
451                } else if (ch == 0xFF) {
452                   lf->state = lex_utf16_le_bom;
453                } else {
454                   scan_err0(lf, _("This config file appears to be in an "
455                      "unsupported Unicode format (UTF-16be). Please resave as UTF-8\n"));
456                   return T_ERROR;
457                }
458             }
459             break;
460          default:
461             lf->state = lex_string;
462             begin_str(lf, ch);
463             break;
464          }
465          break;
466       case lex_comment:
467          Dmsg1(dbglvl, "Lex state lex_comment ch=%x\n", ch);
468          if (ch == L_EOL) {
469             lf->state = lex_none;
470             if (expect != T_SKIP_EOL) {
471                token = T_EOL;
472             }
473          } else if (ch == L_EOF) {
474             token = T_ERROR;
475          }
476          break;
477       case lex_number:
478          Dmsg2(dbglvl, "Lex state lex_number ch=%x %c\n", ch, ch);
479          if (ch == L_EOF) {
480             token = T_ERROR;
481             break;
482          }
483          /* Might want to allow trailing specifications here */
484          if (B_ISDIGIT(ch)) {
485             add_str(lf, ch);
486             break;
487          }
488
489          /* A valid number can be terminated by the following */
490          if (B_ISSPACE(ch) || ch == L_EOL || ch == ',' || ch == ';') {
491             token = T_NUMBER;
492             lf->state = lex_none;
493          } else {
494             lf->state = lex_string;
495          }
496          lex_unget_char(lf);
497          break;
498       case lex_ip_addr:
499          if (ch == L_EOF) {
500             token = T_ERROR;
501             break;
502          }
503          Dmsg1(dbglvl, "Lex state lex_ip_addr ch=%x\n", ch);
504          break;
505       case lex_string:
506          Dmsg1(dbglvl, "Lex state lex_string ch=%x\n", ch);
507          if (ch == L_EOF) {
508             token = T_ERROR;
509             break;
510          }
511          if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
512              ch == '\r' || ch == ';' || ch == ',' || ch == '#' || (B_ISSPACE(ch)) ) {
513             lex_unget_char(lf);
514             token = T_UNQUOTED_STRING;
515             lf->state = lex_none;
516             break;
517          }
518          add_str(lf, ch);
519          break;
520       case lex_identifier:
521          Dmsg2(dbglvl, "Lex state lex_identifier ch=%x %c\n", ch, ch);
522          if (B_ISALPHA(ch)) {
523             add_str(lf, ch);
524             break;
525          } else if (B_ISSPACE(ch)) {
526             break;
527          } else if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
528                     ch == '\r' || ch == ';' || ch == ','   || ch == '"' || ch == '#') {
529             lex_unget_char(lf);
530             token = T_IDENTIFIER;
531             lf->state = lex_none;
532             break;
533          } else if (ch == L_EOF) {
534             token = T_ERROR;
535             lf->state = lex_none;
536             begin_str(lf, ch);
537             break;
538          }
539          /* Some non-alpha character => string */
540          lf->state = lex_string;
541          add_str(lf, ch);
542          break;
543       case lex_quoted_string:
544          Dmsg2(dbglvl, "Lex state lex_quoted_string ch=%x %c\n", ch, ch);
545          if (ch == L_EOF) {
546             token = T_ERROR;
547             break;
548          }
549          if (ch == L_EOL) {
550             esc_next = false;
551             break;
552          }
553          if (esc_next) {
554             add_str(lf, ch);
555             esc_next = false;
556             break;
557          }
558          if (ch == '\\') {
559             esc_next = true;
560             break;
561          }
562          if (ch == '"') {
563             token = T_QUOTED_STRING;
564             lf->state = lex_none;
565             break;
566          }
567          add_str(lf, ch);
568          break;
569       case lex_include:            /* scanning a filename */
570          if (ch == L_EOF) {
571             token = T_ERROR;
572             break;
573          }
574          if (B_ISSPACE(ch) || ch == '\n' || ch == L_EOL || ch == '}' || ch == '{' ||
575              ch == ';' || ch == ','   || ch == '"' || ch == '#') {
576             /* Keep the original LEX so we can print an error if the included file can't be opened. */
577             LEX* lfori = lf;
578
579             lf->state = lex_none;
580             lf = lex_open_file(lf, lf->str, lf->scan_error);
581             if (lf == NULL) {
582                berrno be;
583                scan_err2(lfori, _("Cannot open included config file %s: %s\n"),
584                   lfori->str, be.bstrerror());
585                return T_ERROR;
586             }
587             break;
588          }
589          add_str(lf, ch);
590          break;
591       case lex_utf8_bom:
592          /* we only end up in this state if we have read an 0xEF 
593             as the first byte of the file, indicating we are probably
594             reading a UTF-8 file */
595          if (ch == 0xBB && bom_bytes_seen == 1) {
596             bom_bytes_seen++;
597          } else if (ch == 0xBF && bom_bytes_seen == 2) {
598             token = T_UTF8_BOM;
599             lf->state = lex_none;
600          } else {
601             token = T_ERROR;
602          }
603          break;
604       case lex_utf16_le_bom:
605          /* we only end up in this state if we have read an 0xFF 
606             as the first byte of the file -- indicating that we are
607             probably dealing with an Intel based (little endian) UTF-16 file*/
608          if (ch == 0xFE) {
609             token = T_UTF16_BOM;
610             lf->state = lex_none;
611          } else {
612             token = T_ERROR;
613          }
614          break;
615       }
616       Dmsg4(dbglvl, "ch=%d state=%s token=%s %c\n", ch, lex_state_to_str(lf->state),
617         lex_tok_to_str(token), ch);
618    }
619    Dmsg2(dbglvl, "lex returning: line %d token: %s\n", lf->line_no, lex_tok_to_str(token));
620    lf->token = token;
621
622    /*
623     * Here is where we check to see if the user has set certain
624     *  expectations (e.g. 32 bit integer). If so, we do type checking
625     *  and possible additional scanning (e.g. for range).
626     */
627    switch (expect) {
628    case T_PINT32:
629       lf->pint32_val = scan_pint(lf, lf->str);
630       lf->pint32_val2 = lf->pint32_val;
631       token = T_PINT32;
632       break;
633
634    case T_PINT32_RANGE:
635       if (token == T_NUMBER) {
636          lf->pint32_val = scan_pint(lf, lf->str);
637          lf->pint32_val2 = lf->pint32_val;
638          token = T_PINT32;
639       } else {
640          char *p = strchr(lf->str, '-');
641          if (!p) {
642             scan_err2(lf, _("expected an integer or a range, got %s: %s"),
643                lex_tok_to_str(token), lf->str);
644             token = T_ERROR;
645             break;
646          }
647          *p++ = 0;                       /* terminate first half of range */
648          lf->pint32_val  = scan_pint(lf, lf->str);
649          lf->pint32_val2 = scan_pint(lf, p);
650          token = T_PINT32_RANGE;
651       }
652       break;
653
654    case T_INT32:
655       if (token != T_NUMBER || !is_a_number(lf->str)) {
656          scan_err2(lf, _("expected an integer number, got %s: %s"),
657                lex_tok_to_str(token), lf->str);
658          token = T_ERROR;
659          break;
660       }
661       errno = 0;
662       lf->int32_val = (int32_t)str_to_int64(lf->str);
663       if (errno != 0) {
664          scan_err2(lf, _("expected an integer number, got %s: %s"),
665                lex_tok_to_str(token), lf->str);
666          token = T_ERROR;
667       } else {
668          token = T_INT32;
669       }
670       break;
671
672    case T_INT64:
673       Dmsg2(dbglvl, "int64=:%s: %f\n", lf->str, strtod(lf->str, NULL));
674       if (token != T_NUMBER || !is_a_number(lf->str)) {
675          scan_err2(lf, _("expected an integer number, got %s: %s"),
676                lex_tok_to_str(token), lf->str);
677          token = T_ERROR;
678          break;
679       }
680       errno = 0;
681       lf->int64_val = str_to_int64(lf->str);
682       if (errno != 0) {
683          scan_err2(lf, _("expected an integer number, got %s: %s"),
684                lex_tok_to_str(token), lf->str);
685          token = T_ERROR;
686       } else {
687          token = T_INT64;
688       }
689       break;
690
691    case T_NAME:
692       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
693          scan_err2(lf, _("expected a name, got %s: %s"),
694                lex_tok_to_str(token), lf->str);
695          token = T_ERROR;
696       } else if (lf->str_len > MAX_RES_NAME_LENGTH) {
697          scan_err3(lf, _("name %s length %d too long, max is %d\n"), lf->str,
698             lf->str_len, MAX_RES_NAME_LENGTH);
699          token = T_ERROR;
700       }
701       break;
702
703    case T_STRING:
704       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
705          scan_err2(lf, _("expected a string, got %s: %s"),
706                lex_tok_to_str(token), lf->str);
707          token = T_ERROR;
708       } else {
709          token = T_STRING;
710       }
711       break;
712
713
714    default:
715       break;                          /* no expectation given */
716    }
717    lf->token = token;                 /* set possible new token */
718    return token;
719 }