Fix GCC 3.4 build
[dragonfly.git] / usr.sbin / pccard / pccardd / file.c
1 /*
2  * Copyright (c) 1995 Andrew McRae.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD: src/usr.sbin/pccard/pccardd/file.c,v 1.24.2.5 2001/06/05 07:01:40 imp Exp $
27  * $DragonFly: src/usr.sbin/pccard/pccardd/Attic/file.c,v 1.3 2004/06/19 20:38:22 joerg Exp $
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include "cardd.h"
35
36 static FILE *in;
37 static int includes = 0;
38 static struct {
39         FILE    *filep;
40         char    *filename;
41         int     lineno;
42 } configfiles[MAXINCLUDES] = {{NULL, NULL, 0}, };
43
44 static int pushc, pusht;
45 static int lineno;
46 static char *filename;
47
48 static char *keys[] = {
49         "__EOF__",              /* 1 */
50         "io",                   /* 2 */
51         "irq",                  /* 3 */
52         "memory",               /* 4 */
53         "card",                 /* 5 */
54         "device",               /* 6 */
55         "config",               /* 7 */
56         "reset",                /* 8 */
57         "ether",                /* 9 */
58         "insert",               /* 10 */
59         "remove",               /* 11 */
60         "iosize",               /* 12 */
61         "debuglevel",           /* 13 */
62         "include",              /* 14 */
63         "function",             /* 15 */
64         "logstr",               /* 16 */
65         0
66 };
67
68 #define KWD_EOF                 1
69 #define KWD_IO                  2
70 #define KWD_IRQ                 3
71 #define KWD_MEMORY              4
72 #define KWD_CARD                5
73 #define KWD_DEVICE              6
74 #define KWD_CONFIG              7
75 #define KWD_RESET               8
76 #define KWD_ETHER               9
77 #define KWD_INSERT              10
78 #define KWD_REMOVE              11
79 #define KWD_IOSIZE              12
80 #define KWD_DEBUGLEVEL          13
81 #define KWD_INCLUDE             14
82 #define KWD_FUNCTION            15
83 #define KWD_LOGSTR              16
84
85 /* for keyword compatibility with PAO/plain FreeBSD */
86 static struct {
87         char    *alias;
88         u_int   key;
89 } key_aliases[] = {
90         {"generic", KWD_FUNCTION},
91         {0, 0}
92 };
93
94 struct flags {
95         char   *name;
96         int     mask;
97 };
98
99 extern int      doverbose;
100
101 static void    parsefile(void);
102 static char   *getline(void);
103 static char   *next_tok(void);
104 static int     num_tok(void);
105 static void    error(char *);
106 static int     keyword(char *);
107 static int     irq_tok(int);
108 static int     config_tok(unsigned char *);
109 static int     func_tok(void);
110 static int     debuglevel_tok(int);
111 static struct allocblk *ioblk_tok(int);
112 static struct allocblk *memblk_tok(int);
113 static struct driver *new_driver(char *);
114 static int     iosize_tok(void);
115 static void    file_include(char *);
116
117 static void    addcmd(struct cmd **);
118 static void    parse_card(int);
119
120 static void
121 delete_card(struct card *cp)
122 {
123         struct ether    *etherp, *ether_next;
124         struct card_config *configp, *config_next;
125         struct cmd      *cmdp, *cmd_next;
126
127         /* free strings */
128         free(cp->manuf);
129         free(cp->version);
130         free(cp->add_info1);
131         free(cp->add_info2);
132         free(cp->logstr);
133
134         /* free structures */
135         for (etherp = cp->ether; etherp; etherp = ether_next) {
136                 ether_next = etherp->next;
137                 free(etherp);
138         }
139         for (configp = cp->config; configp; configp = config_next) {
140                 config_next = configp->next;
141                 free(configp);
142         }
143         for (cmdp = cp->insert; cmdp; cmdp = cmd_next) {
144                 cmd_next = cmdp->next;
145                 free(cmdp->line);
146                 free(cmdp);
147         }
148         for (cmdp = cp->remove; cmdp; cmdp = cmd_next) {
149                 cmd_next = cmdp->next;
150                 free(cmdp->line);
151                 free(cmdp);
152         }
153         free(cp);
154 }
155
156 /*
157  * Read a file and parse the pcmcia configuration data.
158  * After parsing, verify the links.
159  */
160 void
161 readfile(char *name)
162 {
163         int i, inuse;
164         struct card *cp, *card_next;
165         struct card *genericp, *tail_gp;
166         struct card_config *configp;
167
168         /* delete all card configuration data before we proceed */
169         genericp = 0;
170         cp = cards;
171         cards = last_card = 0;
172         while (cp) {
173                 card_next = cp->next;
174
175                 /* check whether this card is in use */
176                 inuse = 0;
177                 for (configp = cp->config; configp; configp = configp->next) {
178                         if (configp->inuse) {
179                                 inuse = 1;
180                                 break;
181                         }
182                 }
183
184                 /*
185                  * don't delete entry in use for consistency.
186                  * leave normal entry in the cards list,
187                  * insert generic entry into the list after re-loading config files.
188                  */
189                 if (inuse == 1) {
190                         cp->next = 0;   /* unchain from the cards list */
191                         switch (cp->deftype) {
192                         case DT_VERS:
193                                 /* don't delete this entry for consistency */
194                                 if (debug_level >= 1) {
195                                         logmsg("Card \"%s\"(\"%s\") is in use, "
196                                             "can't change configuration\n",
197                                             cp->manuf, cp->version);
198                                 }
199                                 /* add this to the card list */
200                                 if (!last_card) {
201                                         cards = last_card = cp;
202                                 } else {
203                                         last_card->next = cp;
204                                         last_card = cp;
205                                 }
206                                 break;
207
208                         case DT_FUNC:
209                                 /* generic entry must be inserted to the list later */
210                                 if (debug_level >= 1) {
211                                         logmsg("Generic entry is in use, "
212                                             "can't change configuration\n");
213                                 }
214                                 cp->next = genericp;
215                                 genericp = cp;
216                                 break;
217                         }
218                 } else {
219                         delete_card(cp);
220                 }
221
222                 cp = card_next;
223         }
224
225         for (i = 0; i < MAXINCLUDES; i++) {
226                 if (configfiles[i].filep) {
227                         fclose(configfiles[i].filep);
228                         configfiles[i].filep = NULL;
229                         if (i > 0) {
230                                 free(configfiles[i].filename);
231                         }
232                 }
233         }
234         in = fopen(name, "r");
235         if (in == 0) {
236                 logerr(name);
237                 die("readfile");
238         }
239         includes = 0;
240         configfiles[includes].filep = in;
241         filename = configfiles[includes].filename = name;
242
243         parsefile();
244         for (cp = cards; cp; cp = cp->next) {
245                 if (cp->config == 0)
246                         logmsg("warning: card %s(%s) has no valid configuration\n",
247                             cp->manuf, cp->version);
248         }
249
250         /* insert generic entries in use into the top of generic entries */
251         if (genericp) {
252                 /* search tail of generic entries in use */
253                 for (tail_gp = genericp; tail_gp->next; tail_gp = tail_gp->next)
254                         ;
255
256                 /*
257                  * if the top of cards list is generic entry,
258                  * insert generic entries in use before it.
259                  */
260                 if (cards && cards->deftype == DT_FUNC) {
261                         tail_gp->next = cards;
262                         cards = genericp;
263                         goto generic_done;
264                 }
265
266                 /* search top of generic entries */
267                 for (cp = cards; cp; cp = cp->next) {
268                         if (cp->next && cp->next->deftype == DT_FUNC) {
269                                 break;
270                         }
271                 }
272
273                 /*
274                  * if we have generic entry in the cards list,
275                  * insert generic entries in use into there.
276                  */
277                 if (cp) {
278                         tail_gp->next = cp->next;
279                         cp->next = genericp;
280                         goto generic_done;
281                 }
282
283                 /*
284                  * otherwise we don't have generic entries in
285                  * cards list, just add them to the list.
286                  */
287                 if (!last_card) {
288                         cards = genericp;
289                 } else {
290                         last_card->next = genericp;
291                         last_card = tail_gp;
292                 }
293 generic_done:
294                 ;
295         }
296
297         /* save the initial state of resource pool */
298         bcopy(io_avail, io_init, bitstr_size(IOPORTS));
299         bcopy(mem_avail, mem_init, bitstr_size(MEMBLKS));
300         bcopy(pool_irq, irq_init, sizeof(pool_irq));
301 }
302
303 static void
304 parsefile(void)
305 {
306         int     i;
307         int     errors = 0;
308         struct allocblk *bp, *next;
309         char    *incl;
310
311         pushc = 0;
312         lineno = 1;
313         for (;;)
314                 switch (keyword(next_tok())) {
315                 case KWD_EOF:
316                         /* EOF */
317                         return;
318                 case KWD_IO:
319                         /* override reserved I/O blocks */
320                         bit_nclear(io_avail, 0, IOPORTS-1);
321                         for (bp = pool_ioblks; bp; bp = next) {
322                                 next = bp->next;
323                                 free(bp);
324                         }
325                         pool_ioblks = NULL;
326
327                         while ((bp = ioblk_tok(0)) != 0) {
328                                 if (bp->size == 0 || bp->addr == 0) {
329                                         free(bp);
330                                         continue;
331                                 }
332                                 bit_nset(io_avail, bp->addr,
333                                          bp->addr + bp->size - 1);
334                                 bp->next = pool_ioblks;
335                                 pool_ioblks = bp;
336                         }
337                         pusht = 1;
338                         break;
339                 case KWD_IRQ:
340                         /* override reserved irqs */
341                         bzero(pool_irq, sizeof(pool_irq));
342                         while ((i = irq_tok(0)) > 0)
343                                 pool_irq[i] = 1;
344                         pusht = 1;
345                         break;
346                 case KWD_MEMORY:
347                         /* override reserved memory blocks. */
348                         bit_nclear(mem_avail, 0, MEMBLKS-1);
349                         for (bp = pool_mem; bp; bp = next) {
350                                 next = bp->next;
351                                 free(bp);
352                         }
353                         pool_mem = NULL;
354
355                         while ((bp = memblk_tok(0)) != 0) {
356                                 if (bp->size == 0 || bp->addr == 0) {
357                                         free(bp);
358                                         continue;
359                                 }
360                                 bit_nset(mem_avail, MEM2BIT(bp->addr),
361                                     MEM2BIT(bp->addr + bp->size) - 1);
362                                 bp->next = pool_mem;
363                                 pool_mem = bp;
364                         }
365                         pusht = 1;
366                         break;
367                 case KWD_CARD:
368                         /* Card definition. */
369                         parse_card(DT_VERS);
370                         break;
371                 case KWD_FUNCTION:
372                         /* Function definition. */
373                         parse_card(DT_FUNC);
374                         break;
375                 case KWD_DEBUGLEVEL:
376                         i = debuglevel_tok(0);
377                         if (i > 0)
378                                 debug_level = i;
379                         break;
380                 case KWD_INCLUDE:
381                         incl = newstr(next_tok());
382                         file_include(incl);
383                         break;
384                 default:
385                         error("syntax error");
386                         pusht = 0;
387                         if (errors++ >= MAXERRORS) {
388                                 error("too many errors, giving up");
389                                 return;
390                         }
391                         break;
392                 }
393 }
394
395 /*
396  *      Parse a card definition.
397  */
398 static void
399 parse_card(int deftype)
400 {
401         char   *man, *vers, *tmp;
402         char   *add_info;
403         unsigned char index_type;
404         struct card *cp;
405         int     i, iosize;
406         struct card_config *confp, *lastp;
407         struct ether *ether;
408
409         confp = 0;
410         cp = xmalloc(sizeof(*cp));
411         cp->deftype = deftype;
412         switch (deftype) {
413         case DT_VERS:
414                 man = newstr(next_tok());
415                 vers = newstr(next_tok());
416                 add_info = newstr(next_tok());
417                 if (keyword(add_info)) {
418                         pusht = 1;
419                         free(add_info);
420                         cp->add_info1 = NULL;
421                         cp->add_info2 = NULL;
422                 } else {
423                         cp->add_info1 = add_info;
424                         add_info = newstr(next_tok());
425                         if (keyword(add_info)) {
426                                 pusht = 1;
427                                 free(add_info);
428                                 cp->add_info2 = NULL;
429                         } else {
430                                 cp->add_info2 = add_info;
431                         }
432                 }
433                 cp->manuf = man;
434                 cp->version = vers;
435                 cp->logstr = NULL;
436                 asprintf(&cp->logstr, "%s (%s)", man, vers);
437                 cp->func_id = 0;
438                 break;
439         case DT_FUNC:
440                 cp->manuf = NULL;
441                 cp->version = NULL;
442                 cp->logstr = NULL;
443                 cp->func_id = (u_char) func_tok();
444                 break;
445         default:
446                 fprintf(stderr, "parse_card: unknown deftype %d\n", deftype);
447                 exit(1);
448         }
449         cp->reset_time = 50;
450         cp->next = 0;
451         if (!last_card) {
452                 cards = last_card = cp;
453         } else {
454                 last_card->next = cp;
455                 last_card = cp;
456         }
457         for (;;) {
458                 switch (keyword(next_tok())) {
459                 case KWD_CONFIG:
460                         /* config */
461                         i = config_tok(&index_type);
462                         if (i == -1) {
463                                 error("illegal card config index");
464                                 break;
465                         }
466                         confp = xmalloc(sizeof(*confp));
467                         man = next_tok();
468                         confp->driver = new_driver(man);
469                         confp->irq = irq_tok(1);
470                         confp->flags = num_tok();
471                         if (confp->flags == -1) {
472                                 pusht = 1;
473                                 confp->flags = 0;
474                         }
475                         if (confp->irq < 0 || confp->irq > 15) {
476                                 error("illegal card IRQ value");
477                                 break;
478                         }
479                         confp->index = i & 0x3F;
480                         confp->index_type = index_type;
481
482                         /*
483                          * If no valid driver for this config, then do not save
484                          * this configuration entry.
485                          */
486                         if (confp->driver) {
487                                 if (cp->config == 0)
488                                         cp->config = confp;
489                                 else {
490                                         for (lastp = cp->config; lastp->next;
491                                             lastp = lastp->next);
492                                         lastp->next = confp;
493                                 }
494                         } else
495                                 free(confp);
496                         break;
497                 case KWD_RESET:
498                         /* reset */
499                         i = num_tok();
500                         if (i == -1) {
501                                 error("illegal card reset time");
502                                 break;
503                         }
504                         cp->reset_time = i;
505                         break;
506                 case KWD_ETHER:
507                         /* ether */
508                         ether = xmalloc(sizeof(*ether));
509                         ether->type = ETHTYPE_GENERIC;
510                         tmp = next_tok();
511                         if (strcmp("attr2", tmp) == 0)
512                                 ether->type = ETHTYPE_ATTR2;
513                         else {
514                                 pusht = 1;
515                                 ether->value = num_tok();
516                                 if (ether->value == -1) {
517                                         error("illegal ether address offset");
518                                         free(ether);
519                                         break;
520                                 }
521                         }
522                         ether->next = cp->ether;
523                         cp->ether = ether;
524                         break;
525                 case KWD_INSERT:
526                         /* insert */
527                         addcmd(&cp->insert);
528                         break;
529                 case KWD_REMOVE:
530                         /* remove */
531                         addcmd(&cp->remove);
532                         break;
533                 case KWD_IOSIZE:
534                         /* iosize */
535                         iosize = iosize_tok();
536                         if (!iosize) {
537                                 error("Illegal cardio arguments");
538                                 break;
539                         }
540                         if (!confp) {
541                                 error("iosize should be placed after config");
542                                 break;
543                         }
544                         cp->iosize = iosize;
545                         break;
546                 case KWD_LOGSTR:
547                         free(cp->logstr);
548                         cp->logstr = newstr(next_tok());
549                         break;
550                 default:
551                         pusht = 1;
552                         return;
553                 }
554         }
555 }
556
557 /*
558  *      Generate a new driver structure. If one exists, use
559  *      that one after confirming the correct class.
560  */
561 static struct driver *
562 new_driver(char *name)
563 {
564         struct driver *drvp;
565         char   *p;
566
567         for (drvp = drivers; drvp; drvp = drvp->next)
568                 if (strcmp(drvp->name, name) == 0)
569                         return (drvp);
570         drvp = xmalloc(sizeof(*drvp));
571         drvp->next = drivers;
572         drivers = drvp;
573         drvp->name = newstr(name);
574         drvp->kernel = newstr(name);
575         p = drvp->kernel;
576         while (*p++)
577                 if (*p >= '0' && *p <= '9') {
578                         drvp->unit = atoi(p);
579                         *p = 0;
580                         break;
581                 }
582 #ifdef  DEBUG
583         printf("Drv %s%d created\n", drvp->kernel, drvp->unit);
584 #endif
585         return (drvp);
586 }
587
588
589 /*
590  *      Parse one I/O block.
591  */
592 static struct allocblk *
593 ioblk_tok(int force)
594 {
595         struct allocblk *io;
596         int     i, j;
597
598         /* ignore the keyword to allow separete blocks in multiple lines */
599         if (keyword(next_tok()) != KWD_IO) {
600                 pusht = 1;
601         }
602
603         if ((i = num_tok()) >= 0) {
604                 if (strcmp("-", next_tok()) || (j = num_tok()) < 0 || j < i) {
605                         error("I/O block format error");
606                         return (0);
607                 }
608                 io = xmalloc(sizeof(*io));
609                 io->addr = i;
610                 io->size = j - i + 1;
611                 if (j > IOPORTS) {
612                         error("I/O port out of range");
613                         if (force) {
614                                 free(io);
615                                 io = 0;
616                         } else
617                                 io->addr = io->size = 0;
618                 }
619                 return (io);
620         }
621         if (force)
622                 error("illegal or missing I/O block spec");
623         return (0);
624 }
625
626 /*
627  *      Parse a memory block.
628  */
629 static struct allocblk *
630 memblk_tok(int force)
631 {
632         struct allocblk *mem;
633         int     i, j;
634
635         /* ignore the keyword to allow separete blocks in multiple lines */
636         if (keyword(next_tok()) != KWD_MEMORY) {
637                 pusht = 1;
638         }
639
640         if ((i = num_tok()) >= 0) {
641                 if ((j = num_tok()) < 0)
642                         error("illegal memory block");
643                 else {
644                         mem = xmalloc(sizeof(*mem));
645                         mem->addr = i & ~(MEMUNIT - 1);
646                         mem->size = (j + MEMUNIT - 1) & ~(MEMUNIT - 1);
647                         if (i < MEMSTART || (i + j) > MEMEND) {
648                                 error("memory address out of range");
649                                 if (force) {
650                                         free(mem);
651                                         mem = 0;
652                                 } else
653                                         mem->addr = mem->size = 0;
654                         }
655                         return (mem);
656                 }
657         }
658         if (force)
659                 error("illegal or missing memory block spec");
660         return (0);
661 }
662
663 /*
664  *      IRQ token. Must be number > 0 && < 16.
665  *      If force is set, IRQ must exist, and can also be '?'.
666  */
667 static int
668 irq_tok(int force)
669 {
670         int     i;
671
672         /* ignore the keyword to allow separete blocks in multiple lines */
673         if (keyword(next_tok()) != KWD_IRQ) {
674                 pusht = 1;
675         }
676
677         if (strcmp("?", next_tok()) == 0 && force)
678                 return (0);
679         pusht = 1;
680         i = num_tok();
681         if (i > 0 && i < 16)
682                 return (i);
683         if (force)
684                 error("illegal IRQ value");
685         return (-1);
686 }
687
688 /*
689  *      Config index token
690  */
691 static int
692 config_tok(unsigned char *index_type)
693 {
694         if (strcmp("default", next_tok()) == 0) {
695                 *index_type = DEFAULT_INDEX;
696                 return 0;
697         }
698         pusht = 1;
699         if (strcmp("auto", next_tok()) == 0) {
700                 *index_type = AUTO_INDEX;
701                 return 0;
702         }
703         pusht = 1;
704         *index_type = NORMAL_INDEX;
705         return num_tok();
706 }
707 /*
708  *      Function ID token
709  */
710 static int
711 func_tok(void)
712 {
713         if (strcmp("serial", next_tok()) == 0)  
714                 return 2;
715         pusht = 1;
716         if (strcmp("fixed_disk", next_tok()) == 0)      
717                 return 4;
718         pusht = 1;
719         return num_tok();
720 }
721
722
723 /*
724  *      debuglevel token. Must be between 0 and 9.
725  */
726 static int
727 debuglevel_tok(int force)
728 {
729         int     i;
730
731         i = num_tok();
732         if (i >= 0 && i <= 9)
733                 return (i);
734         return (-1);
735 }
736
737 /*
738  *      iosize token
739  *      iosize {<size>|auto}
740  */
741 static int
742 iosize_tok(void)
743 {
744         int iosize = 0;
745         if (strcmp("auto", next_tok()) == 0)
746                 iosize = -1;    /* wildcard */
747         else {
748                 pusht = 1;
749                 iosize = num_tok();
750                 if (iosize == -1)
751                         return 0;
752         }
753 #ifdef DEBUG
754         if (doverbose)
755                 printf("iosize: size=%x\n", iosize);
756 #endif
757         return iosize;
758 }
759
760
761 /*
762  *      search the table for a match.
763  */
764 static int
765 keyword(char *str)
766 {
767         char  **s;
768         int     i = 1;
769
770         for (s = keys; *s; s++, i++)
771                 if (strcmp(*s, str) == 0)
772                         return (i);
773
774         /* search keyword aliases too */
775         for (i = 0; key_aliases[i].key ; i++)
776                 if (strcmp(key_aliases[i].alias, str) == 0)
777                         return (key_aliases[i].key);
778
779         return (0);
780 }
781
782 /*
783  *      addcmd - Append the command line to the list of
784  *      commands.
785  */
786 static void
787 addcmd(struct cmd **cp)
788 {
789         struct cmd *ncp;
790         char   *s = getline();
791
792         if (*s) {
793                 ncp = xmalloc(sizeof(*ncp));
794                 ncp->line = s;
795                 while (*cp)
796                         cp = &(*cp)->next;
797                 *cp = ncp;
798         }
799
800 }
801
802 static void
803 error(char *msg)
804 {
805         pusht = 1;
806         logmsg("%s: %s at line %d, near %s\n",
807             filename, msg, lineno, next_tok());
808         pusht = 1;
809 }
810
811 static int     last_char;
812
813 static int
814 get(void)
815 {
816         int     c;
817
818         if (pushc)
819                 c = pushc;
820         else
821                 c = getc(in);
822         pushc = 0;
823         while (c == '\\') {
824                 c = getc(in);
825                 switch (c) {
826                 case '#':
827                         return (last_char = c);
828                 case '\n':
829                         lineno++;
830                         c = getc(in);
831                         continue;
832                 }
833                 pushc = c;
834                 return ('\\');
835         }
836         if (c == '\n')
837                 lineno++;
838         if (c == '#') 
839                 while (((c = get()) != '\n') && (c != EOF));
840         return (last_char = c);
841 }
842
843 /*
844  *      num_tok - expecting a number token. If not a number,
845  *      return -1.
846  *      Handles octal (who uses octal anymore?)
847  *              hex
848  *              decimal
849  *      Looks for a 'k' at the end of decimal numbers
850  *      and multiplies by 1024.
851  */
852 static int
853 num_tok(void)
854 {
855         char   *s = next_tok(), c;
856         int     val = 0, base;
857
858         base = 10;
859         c = *s++;
860         if (c == '0') {
861                 base = 8;
862                 c = *s++;
863                 if (c == '\0') return 0; 
864                 else if (c == 'x' || c == 'X') {
865                         c = *s++;
866                         base = 16;
867                 }
868         }
869         do {
870                 switch (c) {
871                 case 'k':
872                 case 'K':
873                         if (val && base == 10 && *s == 0)
874                                 return (val * 1024);
875                         return (-1);
876                 default:
877                         return (-1);
878                 case '0':
879                 case '1':
880                 case '2':
881                 case '3':
882                 case '4':
883                 case '5':
884                 case '6':
885                 case '7':
886                         val = val * base + c - '0';
887                         break;
888
889                 case '8':
890                 case '9':
891                         if (base == 8)
892                                 return (-1);
893                         else
894                                 val = val * base + c - '0';
895                         break;
896                 case 'a':
897                 case 'b':
898                 case 'c':
899                 case 'd':
900                 case 'e':
901                 case 'f':
902                         if (base == 16)
903                                 val = val * base + c - 'a' + 10;
904                         else
905                                 return (-1);
906                         break;
907                 case 'A':
908                 case 'B':
909                 case 'C':
910                 case 'D':
911                 case 'E':
912                 case 'F':
913                         if (base == 16)
914                                 val = val * base + c - 'A' + 10;
915                         else
916                                 return (-1);
917                         break;
918                 }
919         } while ((c = *s++) != 0);
920         return (val);
921 }
922
923 static char   *_next_tok(void);
924
925 static char *
926 next_tok(void)
927 {
928         char   *s = _next_tok();
929 #if 0
930         printf("Tok = %s\n", s);
931 #endif
932         return (s);
933 }
934
935 /*
936  *      get one token. Handles string quoting etc.
937  */
938 static char *
939 _next_tok(void)
940 {
941         static char buf[1024];
942         char   *p = buf, instr = 0;
943         int     c;
944
945         if (pusht) {
946                 pusht = 0;
947                 return (buf);
948         }
949         for (;;) {
950                 c = get();
951                 switch (c) {
952                 default:
953                         *p++ = c;
954                         break;
955                 case '"':
956                         if (instr) {
957                                 *p++ = 0;
958                                 return (buf);
959                         }
960                         instr = 1;
961                         break;
962                 case '\n':
963                         if (instr) {
964                                 error("unterminated string");
965                                 break;
966                         }
967                 case ' ':
968                 case '\t':
969                         /* Eat whitespace unless in a string. */
970                         if (!instr) {
971                                 if (p != buf) {
972                                         *p++ = 0;
973                                         return (buf);
974                                 }
975                         } else
976                                 *p++ = c;
977                         break;
978                 case '-':
979                 case '?':
980                 case '*':
981                         /* Special characters that are tokens on their own. */
982                         if (instr)
983                                 *p++ = c;
984                         else {
985                                 if (p != buf)
986                                         pushc = c;
987                                 else
988                                         *p++ = c;
989                                 *p++ = 0;
990                                 return (buf);
991                         }
992                         break;
993                 case EOF:
994                         if (includes) {
995                                 fclose(in);
996                                 /* go back to previous config file */
997                                 includes--;
998                                 in = configfiles[includes].filep;
999                                 filename = configfiles[includes].filename;
1000                                 lineno = configfiles[includes].lineno;
1001                                 return _next_tok();     /* recursive */
1002                         }
1003                         if (p != buf) {
1004                                 *p++ = 0;
1005                                 return (buf);
1006                         }
1007                         strcpy(buf, "__EOF__");
1008                         return (buf);
1009                 }
1010         }
1011 }
1012
1013 /*
1014  *      get the rest of the line. If the
1015  *      last character scanned was a newline, then
1016  *      return an empty line. If this isn't checked, then
1017  *      a getline may incorrectly return the next line.
1018  */
1019 static char *
1020 getline(void)
1021 {
1022         char    buf[1024], *p = buf;
1023         int     c, i = 0;
1024
1025         if (last_char == '\n')
1026                 return (newstr(""));
1027         do {
1028                 c = get();
1029         } while (c == ' ' || c == '\t');
1030         for (; c != '\n' && c != EOF; c = get())
1031                 if (i++ < sizeof(buf) - 10)
1032                         *p++ = c;
1033         *p = 0;
1034         return (newstr(buf));
1035 }
1036
1037 /*
1038  *      Include configuration file
1039  */
1040 static void
1041 file_include(char *incl)
1042 {
1043         int     i, included;
1044         FILE    *fp;
1045
1046         /* check nesting overflow */
1047         if (includes >= MAXINCLUDES) {
1048                 if (debug_level >= 1) {
1049                         logmsg("%s: include nesting overflow "
1050                             "at line %d, near %s\n", filename, lineno, incl);
1051                 }
1052                 free(incl);
1053                 goto out;
1054         }
1055
1056         /* check recursive inclusion */
1057         for (i = 0, included = 0; i <= includes; i++) {
1058                 if (strcmp(incl, configfiles[i].filename) == 0) {
1059                         included = 1;
1060                         break;
1061                 }
1062         }
1063         if (included == 1) {
1064                 if (debug_level >= 1) {
1065                         logmsg("%s: can't include the same file twice "
1066                             "at line %d, near %s\n", filename, lineno, incl);
1067                 }
1068                 free(incl);
1069                 goto out;
1070         }
1071
1072         if (!(fp = fopen(incl, "r"))) {
1073                 if (debug_level >= 1) {
1074                         logmsg("%s: can't open include file "
1075                             "at line %d, near %s\n", filename, lineno, incl);
1076                 }
1077                 free(incl);
1078                 goto out;
1079         }
1080
1081         /* save line number of the current config file */
1082         configfiles[includes].lineno = lineno;
1083         lineno = 1;
1084
1085         /* now we start parsing new config file */
1086         includes++;
1087         in = configfiles[includes].filep = fp;
1088         filename = configfiles[includes].filename = incl;
1089 out:
1090         return;
1091 }