]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/lex.c
crypto: convert EVP_PKEY access and remainings bits for OpenSSL 1.1
[bacula/bacula] / bacula / src / lib / lex.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  * Lexical scanner for Bacula configuration file
21  *
22  *   Kern Sibbald, 2000
23  *
24  */
25
26 #include "bacula.h"
27 #include "lex.h"
28
29 /* Debug level for this source file */
30 static const int dbglvl = 5000;
31
32 /* 
33  * Return false if the end of the line contains anything other
34  *   than spaces, or a semicolon or a comment.
35  */
36 bool lex_check_eol(LEX *lf)
37 {
38    char *ch = lf->line+lf->col_no;
39    while (*ch != '\0' && *ch != '#' && B_ISSPACE(*ch) && *ch != ';') {
40       ch++;
41    }
42    return *ch == '\0' || *ch == '#' || *ch == ';';
43 }
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 eol\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       if (token == T_EOF) {
60          return;
61       }
62    }
63 }
64
65 /*
66  * Get next token, but skip EOL
67  */
68 int scan_to_next_not_eol(LEX * lc)
69 {
70    int token;
71    do {
72       token = lex_get_token(lc, T_ALL);
73    } while (token == T_EOL);
74    return token;
75 }
76
77 /*
78  * Format a scanner error message
79  */
80 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
81 {
82    va_list arg_ptr;
83    char buf[MAXSTRING];
84    char more[MAXSTRING];
85
86    va_start(arg_ptr, msg);
87    bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
88    va_end(arg_ptr);
89
90    if (lc->err_type == 0) {     /* M_ERROR_TERM by default */
91       lc->err_type = M_ERROR_TERM;
92    }
93
94    if (lc->line_no > lc->begin_line_no) {
95       bsnprintf(more, sizeof(more),
96                 _("Problem probably begins at line %d.\n"), lc->begin_line_no);
97    } else {
98       more[0] = 0;
99    }
100    if (lc->line_no > 0) {
101       e_msg(file, line, lc->err_type, 0, _("Config error: %s\n"
102 "            : line %d, col %d of file %s\n%s\n%s"),
103          buf, lc->line_no, lc->col_no, lc->fname, lc->line, more);
104    } else {
105       e_msg(file, line, lc->err_type, 0, _("Config error: %s\n"), buf);
106    }
107 }
108
109 void lex_set_default_error_handler(LEX *lf)
110 {
111    lf->scan_error = s_err;
112 }
113
114 /*
115  * Set err_type used in error_handler
116  * return the old value
117  */
118 int lex_set_error_handler_error_type(LEX *lf, int err_type)
119 {
120    int old = lf->err_type;
121    lf->err_type = err_type;
122    return old;
123 }
124
125 /* Store passwords in clear text or with MD5 encoding */
126 void lex_store_clear_passwords(LEX *lf)
127 {
128    lf->options |= LOPT_NO_MD5;
129 }
130
131 /*
132  * Free the current file, and retrieve the contents
133  * of the previous packet if any.
134  */
135 LEX *lex_close_file(LEX *lf)
136 {
137    LEX *of;
138
139    if (lf == NULL) {
140       Emsg0(M_ABORT, 0, _("Close of NULL file\n"));
141    }
142    Dmsg1(dbglvl, "Close lex file: %s\n", lf->fname);
143
144    of = lf->next;
145    if (lf->bpipe) {
146       close_bpipe(lf->bpipe);
147       lf->bpipe = NULL;
148    } else if (lf->fd) {
149       fclose(lf->fd);
150    }
151    Dmsg1(dbglvl, "Close cfg file %s\n", lf->fname);
152    if (lf->fname) {
153       free(lf->fname);
154    }
155    free_memory(lf->line);
156    lf->line = NULL;
157    free_memory(lf->str);
158    lf->str = NULL;
159    if (of) {
160       of->options = lf->options;      /* preserve options */
161       memcpy(lf, of, sizeof(LEX));
162       Dmsg1(dbglvl, "Restart scan of cfg file %s\n", of->fname);
163    } else {
164       of = lf;
165       lf = NULL;
166    }
167    if (of) {
168       free(of);
169    }
170    return lf;
171 }
172
173 /*
174  * Open a configuration in memory buffer. We push the
175  * state of the current file (lf) so that we
176  * can do includes.  This is a bit of a hammer.
177  * Instead of passing back the pointer to the
178  * new packet, I simply replace the contents
179  * of the caller's packet with the new packet,
180  * and link the contents of the old packet into
181  * the next field.
182  *
183  */
184 LEX *lex_open_buf(LEX *lf, const char *buffer, LEX_ERROR_HANDLER *scan_error)
185
186 {
187    LEX *nf;
188
189    Dmsg0(400, "Open config buffer\n");
190    nf = (LEX *)malloc(sizeof(LEX));
191    if (lf) {
192       memcpy(nf, lf, sizeof(LEX));
193       memset(lf, 0, sizeof(LEX));
194       lf->next = nf;                  /* if have lf, push it behind new one */
195       lf->options = nf->options;      /* preserve user options */
196       /*
197        * preserve err_type to prevent bacula exiting on 'reload'
198        * if config is invalid. Fixes bug #877
199        */
200       lf->err_type = nf->err_type;
201    } else {
202       lf = nf;                        /* start new packet */
203       memset(lf, 0, sizeof(LEX));
204       lex_set_error_handler_error_type(lf, M_ERROR_TERM);
205    }
206    if (scan_error) {
207       lf->scan_error = scan_error;
208    } else {
209       lex_set_default_error_handler(lf);
210    }
211    lf->fd = NULL;
212    lf->bpipe = NULL;
213    lf->fname = NULL;
214    lf->line = get_memory(5000);
215    pm_strcpy(lf->line, buffer);
216    pm_strcat(lf->line, "");
217    lf->state = lex_none;
218    lf->ch = 0;
219    lf->str = get_memory(5000);
220    return lf;
221 }
222
223 /*
224  * Open a new configuration file. We push the
225  * state of the current file (lf) so that we
226  * can do includes.  This is a bit of a hammer.
227  * Instead of passing back the pointer to the
228  * new packet, I simply replace the contents
229  * of the caller's packet with the new packet,
230  * and link the contents of the old packet into
231  * the next field.
232  *
233  */
234 LEX *lex_open_file(LEX *lf, const char *filename, LEX_ERROR_HANDLER *scan_error)
235
236 {
237    LEX *nf;
238    FILE *fd;
239    BPIPE *bpipe = NULL;
240    char *fname = bstrdup(filename);
241
242    if (fname[0] == '|') {
243       if ((bpipe = open_bpipe(fname+1, 0, "rb")) == NULL) {
244          free(fname);
245          return NULL;
246       }
247       fd = bpipe->rfd;
248    } else if ((fd = fopen(fname, "rb")) == NULL) {
249       free(fname);
250       return NULL;
251    }
252    Dmsg1(400, "Open config file: %s\n", fname);
253    nf = (LEX *)malloc(sizeof(LEX));
254    if (lf) {
255       memcpy(nf, lf, sizeof(LEX));
256       memset(lf, 0, sizeof(LEX));
257       lf->next = nf;                  /* if have lf, push it behind new one */
258       lf->options = nf->options;      /* preserve user options */
259       /*
260        * preserve err_type to prevent bacula exiting on 'reload'
261        * if config is invalid. Fixes bug #877
262        */
263       lf->err_type = nf->err_type;
264    } else {
265       lf = nf;                        /* start new packet */
266       memset(lf, 0, sizeof(LEX));
267       lex_set_error_handler_error_type(lf, M_ERROR_TERM);
268    }
269    if (scan_error) {
270       lf->scan_error = scan_error;
271    } else {
272       lex_set_default_error_handler(lf);
273    }
274    lf->fd = fd;
275    lf->bpipe = bpipe;
276    lf->fname = fname;
277    lf->line = get_memory(5000);
278    lf->state = lex_none;
279    lf->ch = L_EOL;
280    lf->str = get_memory(5000);
281    Dmsg1(dbglvl, "Return lex=%x\n", lf);
282    return lf;
283 }
284
285 /*
286  * Get the next character from the input.
287  *  Returns the character or
288  *    L_EOF if end of file
289  *    L_EOL if end of line
290  */
291 int lex_get_char(LEX *lf)
292 {
293    if (lf->ch == L_EOF) {
294       Emsg0(M_ABORT, 0, _("get_char: called after EOF."
295          " You may have a open double quote without the closing double quote.\n"));
296    }
297    if (lf->fd && lf->ch == L_EOL) {
298       if (bfgets(lf->line, lf->fd) == NULL) {
299          lf->ch = L_EOF;
300          if (lf->next) {
301             lex_close_file(lf);
302          }
303          return lf->ch;
304       }
305       lf->line_no++;
306       lf->col_no = 0;
307       Dmsg2(1000, "fget line=%d %s", lf->line_no, lf->line);
308    } else if (lf->ch == L_EOL) {
309       lf->line_no++;
310       lf->col_no++;
311    }
312    lf->ch = (uint8_t)lf->line[lf->col_no];
313    if (lf->fd) {
314       if (lf->ch == 0) {
315          lf->ch = L_EOL;           /* reached end of line, force bfgets */
316       } else {
317          lf->col_no++;
318       }
319    } else {
320       if (lf->ch == 0) {           /* End of buffer, stop scan */
321          lf->ch = L_EOF;
322          if (lf->next) {
323             lex_close_file(lf);
324          }
325          return lf->ch;
326       } else if (lf->ch == '\n') {  /* End of line */
327          Dmsg0(dbglvl, "Found newline return L_EOL\n");
328          lf->ch = L_EOL;
329       } else {
330          lf->col_no++;
331       }
332    }
333    Dmsg3(dbglvl, "lex_get_char: %c %d col=%d\n", lf->ch, lf->ch, lf->col_no);
334    return lf->ch;
335 }
336
337 void lex_unget_char(LEX *lf)
338 {
339    if (lf->ch == L_EOL) {
340       lf->ch = 0;                     /* End of line, force read of next one */
341    } else {
342       lf->col_no--;                   /* Backup to re-read char */
343    }
344 }
345
346
347 /*
348  * Add a character to the current string
349  */
350 static void add_str(LEX *lf, int ch)
351 {
352    if (lf->str_len >= sizeof_pool_memory(lf->str)) {
353       Emsg3(M_ERROR_TERM, 0, _(
354            _("Config token too long, file: %s, line %d, begins at line %d\n")),
355              lf->fname, lf->line_no, lf->begin_line_no);
356    }
357    lf->str[lf->str_len++] = ch;
358    lf->str[lf->str_len] = 0;
359 }
360
361 /*
362  * Begin the string
363  */
364 static void begin_str(LEX *lf, int ch)
365 {
366    lf->str_len = 0;
367    lf->str[0] = 0;
368    if (ch != 0) {
369       add_str(lf, ch);
370    }
371    lf->begin_line_no = lf->line_no;   /* save start string line no */
372 }
373
374 #ifdef DEBUG
375 static const char *lex_state_to_str(int state)
376 {
377    switch (state) {
378    case lex_none:          return _("none");
379    case lex_comment:       return _("comment");
380    case lex_number:        return _("number");
381    case lex_ip_addr:       return _("ip_addr");
382    case lex_identifier:    return _("identifier");
383    case lex_string:        return _("string");
384    case lex_quoted_string: return _("quoted_string");
385    case lex_include:       return _("include");
386    case lex_include_quoted_string: return _("include_quoted_string");
387    case lex_utf8_bom:      return _("UTF-8 Byte Order Mark");
388    case lex_utf16_le_bom:  return _("UTF-16le Byte Order Mark");
389    default:                return "??????";
390    }
391 }
392 #endif
393
394 /*
395  * Convert a lex token to a string
396  * used for debug/error printing.
397  */
398 const char *lex_tok_to_str(int token)
399 {
400    switch(token) {
401    case L_EOF:             return "L_EOF";
402    case L_EOL:             return "L_EOL";
403    case T_NONE:            return "T_NONE";
404    case T_NUMBER:          return "T_NUMBER";
405    case T_IPADDR:          return "T_IPADDR";
406    case T_IDENTIFIER:      return "T_IDENTIFIER";
407    case T_UNQUOTED_STRING: return "T_UNQUOTED_STRING";
408    case T_QUOTED_STRING:   return "T_QUOTED_STRING";
409    case T_BOB:             return "T_BOB";
410    case T_EOB:             return "T_EOB";
411    case T_EQUALS:          return "T_EQUALS";
412    case T_ERROR:           return "T_ERROR";
413    case T_EOF:             return "T_EOF";
414    case T_COMMA:           return "T_COMMA";
415    case T_EOL:             return "T_EOL";
416    case T_UTF8_BOM:        return "T_UTF8_BOM";
417    case T_UTF16_BOM:       return "T_UTF16_BOM";
418    default:                return "??????";
419    }
420 }
421
422 static uint32_t scan_pint(LEX *lf, char *str)
423 {
424    int64_t val = 0;
425    if (!is_a_number(str)) {
426       scan_err1(lf, _("expected a positive integer number, got: %s"), str);
427       /* NOT REACHED */
428    } else {
429       errno = 0;
430       val = str_to_int64(str);
431       if (errno != 0 || val < 0) {
432          scan_err1(lf, _("expected a positive integer number, got: %s"), str);
433          /* NOT REACHED */
434       }
435    }
436    return (uint32_t)val;
437 }
438
439 static uint64_t scan_pint64(LEX *lf, char *str)
440 {
441    uint64_t val = 0;
442    if (!is_a_number(str)) {
443       scan_err1(lf, _("expected a positive integer number, got: %s"), str);
444       /* NOT REACHED */
445    } else {
446       errno = 0;
447       val = str_to_uint64(str);
448       if (errno != 0) {
449          scan_err1(lf, _("expected a positive integer number, got: %s"), str);
450          /* NOT REACHED */
451       }
452    }
453    return val;
454 }
455
456 /*
457  *
458  * Get the next token from the input
459  *
460  */
461 int
462 lex_get_token(LEX *lf, int expect)
463 {
464    int ch, nch;
465    int token = T_NONE;
466    bool esc_next = false;
467    /* Unicode files, especially on Win32, may begin with a "Byte Order Mark"
468       to indicate which transmission format the file is in. The codepoint for
469       this mark is U+FEFF and is represented as the octets EF-BB-BF in UTF-8
470       and as FF-FE in UTF-16le(little endian) and  FE-FF in UTF-16(big endian).
471       We use a distinct state for UTF-8 and UTF-16le, and use bom_bytes_seen
472       to tell which byte we are expecting. */
473    int bom_bytes_seen = 0;
474
475    Dmsg1(dbglvl, "enter lex_get_token state=%s\n", lex_state_to_str(lf->state));
476    while (token == T_NONE) {
477       ch = lex_get_char(lf);
478       switch (lf->state) {
479       case lex_none:
480          Dmsg2(dbglvl, "Lex state lex_none ch=%c,%d\n", ch, ch);
481          if (B_ISSPACE(ch))
482             break;
483          if (B_ISALPHA(ch)) {
484             if (lf->options & LOPT_NO_IDENT || lf->options & LOPT_STRING) {
485                lf->state = lex_string;
486             } else {
487                lf->state = lex_identifier;
488             }
489             begin_str(lf, ch);
490             break;
491          }
492          if (B_ISDIGIT(ch)) {
493             if (lf->options & LOPT_STRING) {
494                lf->state = lex_string;
495             } else {
496                lf->state = lex_number;
497             }
498             begin_str(lf, ch);
499             break;
500          }
501          Dmsg0(dbglvl, "Enter lex_none switch\n");
502          switch (ch) {
503          case L_EOF:
504             token = T_EOF;
505             Dmsg0(dbglvl, "got L_EOF set token=T_EOF\n");
506             break;
507          case '\\':
508             nch = lex_get_char(lf);
509             if (nch == ' ' || nch == '\n' || nch == '\r' || nch == L_EOL) {
510                lf->ch = L_EOL;        /* force end of line */
511             }
512             break;
513          case '#':
514             lf->state = lex_comment;
515             break;
516          case '{':
517             token = T_BOB;
518             begin_str(lf, ch);
519             break;
520          case '}':
521             token = T_EOB;
522             begin_str(lf, ch);
523             break;
524          case '"':
525             lf->state = lex_quoted_string;
526             begin_str(lf, 0);
527             break;
528          case '=':
529             token = T_EQUALS;
530             begin_str(lf, ch);
531             break;
532          case ',':
533             token = T_COMMA;
534             begin_str(lf, ch);
535             break;
536          case ';':
537             if (expect != T_SKIP_EOL) {
538                token = T_EOL;      /* treat ; like EOL */
539             }
540             break;
541          case L_EOL:
542             Dmsg0(dbglvl, "got L_EOL set token=T_EOL\n");
543             if (expect != T_SKIP_EOL) {
544                token = T_EOL;
545             }
546             break;
547          case '@':
548             /* In NO_EXTERN mode, @ is part of a string */
549             if (lf->options & LOPT_NO_EXTERN) {
550                lf->state = lex_string;
551                begin_str(lf, ch);
552             } else {
553                lf->state = lex_include;
554                begin_str(lf, 0);
555             }
556             break;
557          case 0xEF: /* probably a UTF-8 BOM */
558          case 0xFF: /* probably a UTF-16le BOM */
559          case 0xFE: /* probably a UTF-16be BOM (error)*/
560             if (lf->line_no != 1 || lf->col_no != 1)
561             {
562                lf->state = lex_string;
563                begin_str(lf, ch);
564             } else {
565                bom_bytes_seen = 1;
566                if (ch == 0xEF) {
567                   lf->state = lex_utf8_bom;
568                } else if (ch == 0xFF) {
569                   lf->state = lex_utf16_le_bom;
570                } else {
571                   scan_err0(lf, _("This config file appears to be in an "
572                      "unsupported Unicode format (UTF-16be). Please resave as UTF-8\n"));
573                   return T_ERROR;
574                }
575             }
576             break;
577          default:
578             lf->state = lex_string;
579             begin_str(lf, ch);
580             break;
581          }
582          break;
583       case lex_comment:
584          Dmsg1(dbglvl, "Lex state lex_comment ch=%x\n", ch);
585          if (ch == L_EOL) {
586             lf->state = lex_none;
587             if (expect != T_SKIP_EOL) {
588                token = T_EOL;
589             }
590          } else if (ch == L_EOF) {
591             token = T_ERROR;
592          }
593          break;
594       case lex_number:
595          Dmsg2(dbglvl, "Lex state lex_number ch=%x %c\n", ch, ch);
596          if (ch == L_EOF) {
597             token = T_ERROR;
598             break;
599          }
600          /* Might want to allow trailing specifications here */
601          if (B_ISDIGIT(ch)) {
602             add_str(lf, ch);
603             break;
604          }
605
606          /* A valid number can be terminated by the following */
607          if (B_ISSPACE(ch) || ch == L_EOL || ch == ',' || ch == ';') {
608             token = T_NUMBER;
609             lf->state = lex_none;
610          } else {
611             lf->state = lex_string;
612          }
613          lex_unget_char(lf);
614          break;
615       case lex_ip_addr:
616          if (ch == L_EOF) {
617             token = T_ERROR;
618             break;
619          }
620          Dmsg1(dbglvl, "Lex state lex_ip_addr ch=%x\n", ch);
621          break;
622       case lex_string:
623          Dmsg1(dbglvl, "Lex state lex_string ch=%x\n", ch);
624          if (ch == L_EOF) {
625             token = T_ERROR;
626             break;
627          }
628          if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
629              ch == '\r' || ch == ';' || ch == ',' || ch == '#' || (B_ISSPACE(ch)) ) {
630             lex_unget_char(lf);
631             token = T_UNQUOTED_STRING;
632             lf->state = lex_none;
633             break;
634          }
635          add_str(lf, ch);
636          break;
637       case lex_identifier:
638          Dmsg2(dbglvl, "Lex state lex_identifier ch=%x %c\n", ch, ch);
639          if (B_ISALPHA(ch)) {
640             add_str(lf, ch);
641             break;
642          } else if (B_ISSPACE(ch)) {
643             break;
644          } else if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' ||
645                     ch == '\r' || ch == ';' || ch == ','   || ch == '"' || ch == '#') {
646             lex_unget_char(lf);
647             token = T_IDENTIFIER;
648             lf->state = lex_none;
649             break;
650          } else if (ch == L_EOF) {
651             token = T_ERROR;
652             lf->state = lex_none;
653             begin_str(lf, ch);
654             break;
655          }
656          /* Some non-alpha character => string */
657          lf->state = lex_string;
658          add_str(lf, ch);
659          break;
660       case lex_quoted_string:
661          Dmsg2(dbglvl, "Lex state lex_quoted_string ch=%x %c\n", ch, ch);
662          if (ch == L_EOF) {
663             token = T_ERROR;
664             break;
665          }
666          if (ch == L_EOL) {
667             esc_next = false;
668             break;
669          }
670          if (esc_next) {
671             add_str(lf, ch);
672             esc_next = false;
673             break;
674          }
675          if (ch == '\\') {
676             esc_next = true;
677             break;
678          }
679          if (ch == '"') {
680             token = T_QUOTED_STRING;
681             /*
682              * Since we may be scanning a quoted list of names,
683              *  we get the next character (a comma indicates another
684              *  one), then we put it back for rescanning.
685              */
686             lex_get_char(lf);
687             lex_unget_char(lf);
688             lf->state = lex_none;
689             break;
690          }
691          add_str(lf, ch);
692          break;
693       case lex_include_quoted_string:
694          if (ch == L_EOF) {
695             token = T_ERROR;
696             break;
697          }
698          if (esc_next) {
699             add_str(lf, ch);
700             esc_next = false;
701             break;
702          }
703          if (ch == '\\') {
704             esc_next = true;
705             break;
706          }
707          if (ch == '"') {
708             /* Keep the original LEX so we can print an error if the included file can't be opened. */
709             LEX* lfori = lf;
710             /* Skip the double quote when restarting parsing */
711             lex_get_char(lf);
712
713             lf->state = lex_none;
714             lf = lex_open_file(lf, lf->str, lf->scan_error);
715             if (lf == NULL) {
716                berrno be;
717                scan_err2(lfori, _("Cannot open included config file %s: %s\n"),
718                   lfori->str, be.bstrerror());
719                return T_ERROR;
720             }
721             break;
722          }
723          add_str(lf, ch);
724          break;
725       case lex_include:            /* scanning a filename */
726          if (ch == L_EOF) {
727             token = T_ERROR;
728             break;
729          }
730          if (ch == '"') {
731             lf->state = lex_include_quoted_string;
732             break;
733          }
734
735
736          if (B_ISSPACE(ch) || ch == '\n' || ch == L_EOL || ch == '}' || ch == '{' ||
737              ch == ';' || ch == ','   || ch == '"' || ch == '#') {
738             /* Keep the original LEX so we can print an error if the included file can't be opened. */
739             LEX* lfori = lf;
740
741             lf->state = lex_none;
742             lf = lex_open_file(lf, lf->str, lf->scan_error);
743             if (lf == NULL) {
744                berrno be;
745                scan_err2(lfori, _("Cannot open included config file %s: %s\n"),
746                   lfori->str, be.bstrerror());
747                return T_ERROR;
748             }
749             break;
750          }
751          add_str(lf, ch);
752          break;
753       case lex_utf8_bom:
754          /* we only end up in this state if we have read an 0xEF
755             as the first byte of the file, indicating we are probably
756             reading a UTF-8 file */
757          if (ch == 0xBB && bom_bytes_seen == 1) {
758             bom_bytes_seen++;
759          } else if (ch == 0xBF && bom_bytes_seen == 2) {
760             token = T_UTF8_BOM;
761             lf->state = lex_none;
762          } else {
763             token = T_ERROR;
764          }
765          break;
766       case lex_utf16_le_bom:
767          /* we only end up in this state if we have read an 0xFF
768             as the first byte of the file -- indicating that we are
769             probably dealing with an Intel based (little endian) UTF-16 file*/
770          if (ch == 0xFE) {
771             token = T_UTF16_BOM;
772             lf->state = lex_none;
773          } else {
774             token = T_ERROR;
775          }
776          break;
777       }
778       Dmsg4(dbglvl, "ch=%d state=%s token=%s %c\n", ch, lex_state_to_str(lf->state),
779         lex_tok_to_str(token), ch);
780    }
781    Dmsg2(dbglvl, "lex returning: line %d token: %s\n", lf->line_no, lex_tok_to_str(token));
782    lf->token = token;
783
784    /*
785     * Here is where we check to see if the user has set certain
786     *  expectations (e.g. 32 bit integer). If so, we do type checking
787     *  and possible additional scanning (e.g. for range).
788     */
789    switch (expect) {
790    case T_PINT32:
791       lf->pint32_val = scan_pint(lf, lf->str);
792       lf->pint32_val2 = lf->pint32_val;
793       token = T_PINT32;
794       break;
795
796    case T_PINT32_RANGE:
797       if (token == T_NUMBER) {
798          lf->pint32_val = scan_pint(lf, lf->str);
799          lf->pint32_val2 = lf->pint32_val;
800          token = T_PINT32;
801       } else {
802          char *p = strchr(lf->str, '-');
803          if (!p) {
804             scan_err2(lf, _("expected an integer or a range, got %s: %s"),
805                lex_tok_to_str(token), lf->str);
806             token = T_ERROR;
807             break;
808          }
809          *p++ = 0;                       /* terminate first half of range */
810          lf->pint32_val  = scan_pint(lf, lf->str);
811          lf->pint32_val2 = scan_pint(lf, p);
812          token = T_PINT32_RANGE;
813       }
814       break;
815
816    case T_INT32:
817       if (token != T_NUMBER || !is_a_number(lf->str)) {
818          scan_err2(lf, _("expected an integer number, got %s: %s"),
819                lex_tok_to_str(token), lf->str);
820          token = T_ERROR;
821          break;
822       }
823       errno = 0;
824       lf->int32_val = (int32_t)str_to_int64(lf->str);
825       if (errno != 0) {
826          scan_err2(lf, _("expected an integer number, got %s: %s"),
827                lex_tok_to_str(token), lf->str);
828          token = T_ERROR;
829       } else {
830          token = T_INT32;
831       }
832       break;
833
834    case T_INT64:
835       Dmsg2(dbglvl, "int64=:%s: %f\n", lf->str, strtod(lf->str, NULL));
836       if (token != T_NUMBER || !is_a_number(lf->str)) {
837          scan_err2(lf, _("expected an integer number, got %s: %s"),
838                lex_tok_to_str(token), lf->str);
839          token = T_ERROR;
840          break;
841       }
842       errno = 0;
843       lf->int64_val = str_to_int64(lf->str);
844       if (errno != 0) {
845          scan_err2(lf, _("expected an integer number, got %s: %s"),
846                lex_tok_to_str(token), lf->str);
847          token = T_ERROR;
848       } else {
849          token = T_INT64;
850       }
851       break;
852
853    case T_PINT64_RANGE:
854       if (token == T_NUMBER) {
855          lf->pint64_val = scan_pint64(lf, lf->str);
856          lf->pint64_val2 = lf->pint64_val;
857          token = T_PINT64;
858       } else {
859          char *p = strchr(lf->str, '-');
860          if (!p) {
861             scan_err2(lf, _("expected an integer or a range, got %s: %s"),
862                lex_tok_to_str(token), lf->str);
863             token = T_ERROR;
864             break;
865          }
866          *p++ = 0;                       /* terminate first half of range */
867          lf->pint64_val  = scan_pint64(lf, lf->str);
868          lf->pint64_val2 = scan_pint64(lf, p);
869          token = T_PINT64_RANGE;
870       }
871       break;
872
873    case T_NAME:
874       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
875          scan_err2(lf, _("expected a name, got %s: %s"),
876                lex_tok_to_str(token), lf->str);
877          token = T_ERROR;
878       } else if (lf->str_len > MAX_RES_NAME_LENGTH) {
879          scan_err3(lf, _("name %s length %d too long, max is %d\n"), lf->str,
880             lf->str_len, MAX_RES_NAME_LENGTH);
881          token = T_ERROR;
882       }
883       break;
884
885    case T_STRING:
886       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
887          scan_err2(lf, _("expected a string, got %s: %s"),
888                lex_tok_to_str(token), lf->str);
889          token = T_ERROR;
890       } else {
891          token = T_STRING;
892       }
893       break;
894
895
896    default:
897       break;                          /* no expectation given */
898    }
899    lf->token = token;                 /* set possible new token */
900    return token;
901 }