Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[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.2 2003/06/17 04:29:59 dillon 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         /* save the initial state of resource pool */
297         bcopy(io_avail, io_init, bitstr_size(IOPORTS));
298         bcopy(mem_avail, mem_init, bitstr_size(MEMBLKS));
299         bcopy(pool_irq, irq_init, sizeof(pool_irq));
300 }
301
302 static void
303 parsefile(void)
304 {
305         int     i;
306         int     errors = 0;
307         struct allocblk *bp, *next;
308         char    *incl;
309
310         pushc = 0;
311         lineno = 1;
312         for (;;)
313                 switch (keyword(next_tok())) {
314                 case KWD_EOF:
315                         /* EOF */
316                         return;
317                 case KWD_IO:
318                         /* override reserved I/O blocks */
319                         bit_nclear(io_avail, 0, IOPORTS-1);
320                         for (bp = pool_ioblks; bp; bp = next) {
321                                 next = bp->next;
322                                 free(bp);
323                         }
324                         pool_ioblks = NULL;
325
326                         while ((bp = ioblk_tok(0)) != 0) {
327                                 if (bp->size == 0 || bp->addr == 0) {
328                                         free(bp);
329                                         continue;
330                                 }
331                                 bit_nset(io_avail, bp->addr,
332                                          bp->addr + bp->size - 1);
333                                 bp->next = pool_ioblks;
334                                 pool_ioblks = bp;
335                         }
336                         pusht = 1;
337                         break;
338                 case KWD_IRQ:
339                         /* override reserved irqs */
340                         bzero(pool_irq, sizeof(pool_irq));
341                         while ((i = irq_tok(0)) > 0)
342                                 pool_irq[i] = 1;
343                         pusht = 1;
344                         break;
345                 case KWD_MEMORY:
346                         /* override reserved memory blocks. */
347                         bit_nclear(mem_avail, 0, MEMBLKS-1);
348                         for (bp = pool_mem; bp; bp = next) {
349                                 next = bp->next;
350                                 free(bp);
351                         }
352                         pool_mem = NULL;
353
354                         while ((bp = memblk_tok(0)) != 0) {
355                                 if (bp->size == 0 || bp->addr == 0) {
356                                         free(bp);
357                                         continue;
358                                 }
359                                 bit_nset(mem_avail, MEM2BIT(bp->addr),
360                                     MEM2BIT(bp->addr + bp->size) - 1);
361                                 bp->next = pool_mem;
362                                 pool_mem = bp;
363                         }
364                         pusht = 1;
365                         break;
366                 case KWD_CARD:
367                         /* Card definition. */
368                         parse_card(DT_VERS);
369                         break;
370                 case KWD_FUNCTION:
371                         /* Function definition. */
372                         parse_card(DT_FUNC);
373                         break;
374                 case KWD_DEBUGLEVEL:
375                         i = debuglevel_tok(0);
376                         if (i > 0)
377                                 debug_level = i;
378                         break;
379                 case KWD_INCLUDE:
380                         incl = newstr(next_tok());
381                         file_include(incl);
382                         break;
383                 default:
384                         error("syntax error");
385                         pusht = 0;
386                         if (errors++ >= MAXERRORS) {
387                                 error("too many errors, giving up");
388                                 return;
389                         }
390                         break;
391                 }
392 }
393
394 /*
395  *      Parse a card definition.
396  */
397 static void
398 parse_card(int deftype)
399 {
400         char   *man, *vers, *tmp;
401         char   *add_info;
402         unsigned char index_type;
403         struct card *cp;
404         int     i, iosize;
405         struct card_config *confp, *lastp;
406         struct ether *ether;
407
408         confp = 0;
409         cp = xmalloc(sizeof(*cp));
410         cp->deftype = deftype;
411         switch (deftype) {
412         case DT_VERS:
413                 man = newstr(next_tok());
414                 vers = newstr(next_tok());
415                 add_info = newstr(next_tok());
416                 if (keyword(add_info)) {
417                         pusht = 1;
418                         free(add_info);
419                         cp->add_info1 = NULL;
420                         cp->add_info2 = NULL;
421                 } else {
422                         cp->add_info1 = add_info;
423                         add_info = newstr(next_tok());
424                         if (keyword(add_info)) {
425                                 pusht = 1;
426                                 free(add_info);
427                                 cp->add_info2 = NULL;
428                         } else {
429                                 cp->add_info2 = add_info;
430                         }
431                 }
432                 cp->manuf = man;
433                 cp->version = vers;
434                 cp->logstr = NULL;
435                 asprintf(&cp->logstr, "%s (%s)", man, vers);
436                 cp->func_id = 0;
437                 break;
438         case DT_FUNC:
439                 cp->manuf = NULL;
440                 cp->version = NULL;
441                 cp->logstr = NULL;
442                 cp->func_id = (u_char) func_tok();
443                 break;
444         default:
445                 fprintf(stderr, "parse_card: unknown deftype %d\n", deftype);
446                 exit(1);
447         }
448         cp->reset_time = 50;
449         cp->next = 0;
450         if (!last_card) {
451                 cards = last_card = cp;
452         } else {
453                 last_card->next = cp;
454                 last_card = cp;
455         }
456         for (;;) {
457                 switch (keyword(next_tok())) {
458                 case KWD_CONFIG:
459                         /* config */
460                         i = config_tok(&index_type);
461                         if (i == -1) {
462                                 error("illegal card config index");
463                                 break;
464                         }
465                         confp = xmalloc(sizeof(*confp));
466                         man = next_tok();
467                         confp->driver = new_driver(man);
468                         confp->irq = irq_tok(1);
469                         confp->flags = num_tok();
470                         if (confp->flags == -1) {
471                                 pusht = 1;
472                                 confp->flags = 0;
473                         }
474                         if (confp->irq < 0 || confp->irq > 15) {
475                                 error("illegal card IRQ value");
476                                 break;
477                         }
478                         confp->index = i & 0x3F;
479                         confp->index_type = index_type;
480
481                         /*
482                          * If no valid driver for this config, then do not save
483                          * this configuration entry.
484                          */
485                         if (confp->driver) {
486                                 if (cp->config == 0)
487                                         cp->config = confp;
488                                 else {
489                                         for (lastp = cp->config; lastp->next;
490                                             lastp = lastp->next);
491                                         lastp->next = confp;
492                                 }
493                         } else
494                                 free(confp);
495                         break;
496                 case KWD_RESET:
497                         /* reset */
498                         i = num_tok();
499                         if (i == -1) {
500                                 error("illegal card reset time");
501                                 break;
502                         }
503                         cp->reset_time = i;
504                         break;
505                 case KWD_ETHER:
506                         /* ether */
507                         ether = xmalloc(sizeof(*ether));
508                         ether->type = ETHTYPE_GENERIC;
509                         tmp = next_tok();
510                         if (strcmp("attr2", tmp) == 0)
511                                 ether->type = ETHTYPE_ATTR2;
512                         else {
513                                 pusht = 1;
514                                 ether->value = num_tok();
515                                 if (ether->value == -1) {
516                                         error("illegal ether address offset");
517                                         free(ether);
518                                         break;
519                                 }
520                         }
521                         ether->next = cp->ether;
522                         cp->ether = ether;
523                         break;
524                 case KWD_INSERT:
525                         /* insert */
526                         addcmd(&cp->insert);
527                         break;
528                 case KWD_REMOVE:
529                         /* remove */
530                         addcmd(&cp->remove);
531                         break;
532                 case KWD_IOSIZE:
533                         /* iosize */
534                         iosize = iosize_tok();
535                         if (!iosize) {
536                                 error("Illegal cardio arguments");
537                                 break;
538                         }
539                         if (!confp) {
540                                 error("iosize should be placed after config");
541                                 break;
542                         }
543                         cp->iosize = iosize;
544                         break;
545                 case KWD_LOGSTR:
546                         free(cp->logstr);
547                         cp->logstr = newstr(next_tok());
548                         break;
549                 default:
550                         pusht = 1;
551                         return;
552                 }
553         }
554 }
555
556 /*
557  *      Generate a new driver structure. If one exists, use
558  *      that one after confirming the correct class.
559  */
560 static struct driver *
561 new_driver(char *name)
562 {
563         struct driver *drvp;
564         char   *p;
565
566         for (drvp = drivers; drvp; drvp = drvp->next)
567                 if (strcmp(drvp->name, name) == 0)
568                         return (drvp);
569         drvp = xmalloc(sizeof(*drvp));
570         drvp->next = drivers;
571         drivers = drvp;
572         drvp->name = newstr(name);
573         drvp->kernel = newstr(name);
574         p = drvp->kernel;
575         while (*p++)
576                 if (*p >= '0' && *p <= '9') {
577                         drvp->unit = atoi(p);
578                         *p = 0;
579                         break;
580                 }
581 #ifdef  DEBUG
582         printf("Drv %s%d created\n", drvp->kernel, drvp->unit);
583 #endif
584         return (drvp);
585 }
586
587
588 /*
589  *      Parse one I/O block.
590  */
591 static struct allocblk *
592 ioblk_tok(int force)
593 {
594         struct allocblk *io;
595         int     i, j;
596
597         /* ignore the keyword to allow separete blocks in multiple lines */
598         if (keyword(next_tok()) != KWD_IO) {
599                 pusht = 1;
600         }
601
602         if ((i = num_tok()) >= 0) {
603                 if (strcmp("-", next_tok()) || (j = num_tok()) < 0 || j < i) {
604                         error("I/O block format error");
605                         return (0);
606                 }
607                 io = xmalloc(sizeof(*io));
608                 io->addr = i;
609                 io->size = j - i + 1;
610                 if (j > IOPORTS) {
611                         error("I/O port out of range");
612                         if (force) {
613                                 free(io);
614                                 io = 0;
615                         } else
616                                 io->addr = io->size = 0;
617                 }
618                 return (io);
619         }
620         if (force)
621                 error("illegal or missing I/O block spec");
622         return (0);
623 }
624
625 /*
626  *      Parse a memory block.
627  */
628 static struct allocblk *
629 memblk_tok(int force)
630 {
631         struct allocblk *mem;
632         int     i, j;
633
634         /* ignore the keyword to allow separete blocks in multiple lines */
635         if (keyword(next_tok()) != KWD_MEMORY) {
636                 pusht = 1;
637         }
638
639         if ((i = num_tok()) >= 0) {
640                 if ((j = num_tok()) < 0)
641                         error("illegal memory block");
642                 else {
643                         mem = xmalloc(sizeof(*mem));
644                         mem->addr = i & ~(MEMUNIT - 1);
645                         mem->size = (j + MEMUNIT - 1) & ~(MEMUNIT - 1);
646                         if (i < MEMSTART || (i + j) > MEMEND) {
647                                 error("memory address out of range");
648                                 if (force) {
649                                         free(mem);
650                                         mem = 0;
651                                 } else
652                                         mem->addr = mem->size = 0;
653                         }
654                         return (mem);
655                 }
656         }
657         if (force)
658                 error("illegal or missing memory block spec");
659         return (0);
660 }
661
662 /*
663  *      IRQ token. Must be number > 0 && < 16.
664  *      If force is set, IRQ must exist, and can also be '?'.
665  */
666 static int
667 irq_tok(int force)
668 {
669         int     i;
670
671         /* ignore the keyword to allow separete blocks in multiple lines */
672         if (keyword(next_tok()) != KWD_IRQ) {
673                 pusht = 1;
674         }
675
676         if (strcmp("?", next_tok()) == 0 && force)
677                 return (0);
678         pusht = 1;
679         i = num_tok();
680         if (i > 0 && i < 16)
681                 return (i);
682         if (force)
683                 error("illegal IRQ value");
684         return (-1);
685 }
686
687 /*
688  *      Config index token
689  */
690 static int
691 config_tok(unsigned char *index_type)
692 {
693         if (strcmp("default", next_tok()) == 0) {
694                 *index_type = DEFAULT_INDEX;
695                 return 0;
696         }
697         pusht = 1;
698         if (strcmp("auto", next_tok()) == 0) {
699                 *index_type = AUTO_INDEX;
700                 return 0;
701         }
702         pusht = 1;
703         *index_type = NORMAL_INDEX;
704         return num_tok();
705 }
706 /*
707  *      Function ID token
708  */
709 static int
710 func_tok(void)
711 {
712         if (strcmp("serial", next_tok()) == 0)  
713                 return 2;
714         pusht = 1;
715         if (strcmp("fixed_disk", next_tok()) == 0)      
716                 return 4;
717         pusht = 1;
718         return num_tok();
719 }
720
721
722 /*
723  *      debuglevel token. Must be between 0 and 9.
724  */
725 static int
726 debuglevel_tok(int force)
727 {
728         int     i;
729
730         i = num_tok();
731         if (i >= 0 && i <= 9)
732                 return (i);
733         return (-1);
734 }
735
736 /*
737  *      iosize token
738  *      iosize {<size>|auto}
739  */
740 static int
741 iosize_tok(void)
742 {
743         int iosize = 0;
744         if (strcmp("auto", next_tok()) == 0)
745                 iosize = -1;    /* wildcard */
746         else {
747                 pusht = 1;
748                 iosize = num_tok();
749                 if (iosize == -1)
750                         return 0;
751         }
752 #ifdef DEBUG
753         if (doverbose)
754                 printf("iosize: size=%x\n", iosize);
755 #endif
756         return iosize;
757 }
758
759
760 /*
761  *      search the table for a match.
762  */
763 static int
764 keyword(char *str)
765 {
766         char  **s;
767         int     i = 1;
768
769         for (s = keys; *s; s++, i++)
770                 if (strcmp(*s, str) == 0)
771                         return (i);
772
773         /* search keyword aliases too */
774         for (i = 0; key_aliases[i].key ; i++)
775                 if (strcmp(key_aliases[i].alias, str) == 0)
776                         return (key_aliases[i].key);
777
778         return (0);
779 }
780
781 /*
782  *      addcmd - Append the command line to the list of
783  *      commands.
784  */
785 static void
786 addcmd(struct cmd **cp)
787 {
788         struct cmd *ncp;
789         char   *s = getline();
790
791         if (*s) {
792                 ncp = xmalloc(sizeof(*ncp));
793                 ncp->line = s;
794                 while (*cp)
795                         cp = &(*cp)->next;
796                 *cp = ncp;
797         }
798
799 }
800
801 static void
802 error(char *msg)
803 {
804         pusht = 1;
805         logmsg("%s: %s at line %d, near %s\n",
806             filename, msg, lineno, next_tok());
807         pusht = 1;
808 }
809
810 static int     last_char;
811
812 static int
813 get(void)
814 {
815         int     c;
816
817         if (pushc)
818                 c = pushc;
819         else
820                 c = getc(in);
821         pushc = 0;
822         while (c == '\\') {
823                 c = getc(in);
824                 switch (c) {
825                 case '#':
826                         return (last_char = c);
827                 case '\n':
828                         lineno++;
829                         c = getc(in);
830                         continue;
831                 }
832                 pushc = c;
833                 return ('\\');
834         }
835         if (c == '\n')
836                 lineno++;
837         if (c == '#') 
838                 while (((c = get()) != '\n') && (c != EOF));
839         return (last_char = c);
840 }
841
842 /*
843  *      num_tok - expecting a number token. If not a number,
844  *      return -1.
845  *      Handles octal (who uses octal anymore?)
846  *              hex
847  *              decimal
848  *      Looks for a 'k' at the end of decimal numbers
849  *      and multiplies by 1024.
850  */
851 static int
852 num_tok(void)
853 {
854         char   *s = next_tok(), c;
855         int     val = 0, base;
856
857         base = 10;
858         c = *s++;
859         if (c == '0') {
860                 base = 8;
861                 c = *s++;
862                 if (c == '\0') return 0; 
863                 else if (c == 'x' || c == 'X') {
864                         c = *s++;
865                         base = 16;
866                 }
867         }
868         do {
869                 switch (c) {
870                 case 'k':
871                 case 'K':
872                         if (val && base == 10 && *s == 0)
873                                 return (val * 1024);
874                         return (-1);
875                 default:
876                         return (-1);
877                 case '0':
878                 case '1':
879                 case '2':
880                 case '3':
881                 case '4':
882                 case '5':
883                 case '6':
884                 case '7':
885                         val = val * base + c - '0';
886                         break;
887
888                 case '8':
889                 case '9':
890                         if (base == 8)
891                                 return (-1);
892                         else
893                                 val = val * base + c - '0';
894                         break;
895                 case 'a':
896                 case 'b':
897                 case 'c':
898                 case 'd':
899                 case 'e':
900                 case 'f':
901                         if (base == 16)
902                                 val = val * base + c - 'a' + 10;
903                         else
904                                 return (-1);
905                         break;
906                 case 'A':
907                 case 'B':
908                 case 'C':
909                 case 'D':
910                 case 'E':
911                 case 'F':
912                         if (base == 16)
913                                 val = val * base + c - 'A' + 10;
914                         else
915                                 return (-1);
916                         break;
917                 }
918         } while ((c = *s++) != 0);
919         return (val);
920 }
921
922 static char   *_next_tok(void);
923
924 static char *
925 next_tok(void)
926 {
927         char   *s = _next_tok();
928 #if 0
929         printf("Tok = %s\n", s);
930 #endif
931         return (s);
932 }
933
934 /*
935  *      get one token. Handles string quoting etc.
936  */
937 static char *
938 _next_tok(void)
939 {
940         static char buf[1024];
941         char   *p = buf, instr = 0;
942         int     c;
943
944         if (pusht) {
945                 pusht = 0;
946                 return (buf);
947         }
948         for (;;) {
949                 c = get();
950                 switch (c) {
951                 default:
952                         *p++ = c;
953                         break;
954                 case '"':
955                         if (instr) {
956                                 *p++ = 0;
957                                 return (buf);
958                         }
959                         instr = 1;
960                         break;
961                 case '\n':
962                         if (instr) {
963                                 error("unterminated string");
964                                 break;
965                         }
966                 case ' ':
967                 case '\t':
968                         /* Eat whitespace unless in a string. */
969                         if (!instr) {
970                                 if (p != buf) {
971                                         *p++ = 0;
972                                         return (buf);
973                                 }
974                         } else
975                                 *p++ = c;
976                         break;
977                 case '-':
978                 case '?':
979                 case '*':
980                         /* Special characters that are tokens on their own. */
981                         if (instr)
982                                 *p++ = c;
983                         else {
984                                 if (p != buf)
985                                         pushc = c;
986                                 else
987                                         *p++ = c;
988                                 *p++ = 0;
989                                 return (buf);
990                         }
991                         break;
992                 case EOF:
993                         if (includes) {
994                                 fclose(in);
995                                 /* go back to previous config file */
996                                 includes--;
997                                 in = configfiles[includes].filep;
998                                 filename = configfiles[includes].filename;
999                                 lineno = configfiles[includes].lineno;
1000                                 return _next_tok();     /* recursive */
1001                         }
1002                         if (p != buf) {
1003                                 *p++ = 0;
1004                                 return (buf);
1005                         }
1006                         strcpy(buf, "__EOF__");
1007                         return (buf);
1008                 }
1009         }
1010 }
1011
1012 /*
1013  *      get the rest of the line. If the
1014  *      last character scanned was a newline, then
1015  *      return an empty line. If this isn't checked, then
1016  *      a getline may incorrectly return the next line.
1017  */
1018 static char *
1019 getline(void)
1020 {
1021         char    buf[1024], *p = buf;
1022         int     c, i = 0;
1023
1024         if (last_char == '\n')
1025                 return (newstr(""));
1026         do {
1027                 c = get();
1028         } while (c == ' ' || c == '\t');
1029         for (; c != '\n' && c != EOF; c = get())
1030                 if (i++ < sizeof(buf) - 10)
1031                         *p++ = c;
1032         *p = 0;
1033         return (newstr(buf));
1034 }
1035
1036 /*
1037  *      Include configuration file
1038  */
1039 static void
1040 file_include(char *incl)
1041 {
1042         int     i, included;
1043         FILE    *fp;
1044
1045         /* check nesting overflow */
1046         if (includes >= MAXINCLUDES) {
1047                 if (debug_level >= 1) {
1048                         logmsg("%s: include nesting overflow "
1049                             "at line %d, near %s\n", filename, lineno, incl);
1050                 }
1051                 free(incl);
1052                 goto out;
1053         }
1054
1055         /* check recursive inclusion */
1056         for (i = 0, included = 0; i <= includes; i++) {
1057                 if (strcmp(incl, configfiles[i].filename) == 0) {
1058                         included = 1;
1059                         break;
1060                 }
1061         }
1062         if (included == 1) {
1063                 if (debug_level >= 1) {
1064                         logmsg("%s: can't include the same file twice "
1065                             "at line %d, near %s\n", filename, lineno, incl);
1066                 }
1067                 free(incl);
1068                 goto out;
1069         }
1070
1071         if (!(fp = fopen(incl, "r"))) {
1072                 if (debug_level >= 1) {
1073                         logmsg("%s: can't open include file "
1074                             "at line %d, near %s\n", filename, lineno, incl);
1075                 }
1076                 free(incl);
1077                 goto out;
1078         }
1079
1080         /* save line number of the current config file */
1081         configfiles[includes].lineno = lineno;
1082         lineno = 1;
1083
1084         /* now we start parsing new config file */
1085         includes++;
1086         in = configfiles[includes].filep = fp;
1087         filename = configfiles[includes].filename = incl;
1088 out:
1089         return;
1090 }