chiark / gitweb /
wip compile
[inn-innduct.git] / lib / conffile.c
1 /*  $Id: conffile.c 6733 2004-05-16 23:01:23Z rra $
2 **
3 **  Routines for reading in incoming.conf-style config files.
4 */
5
6 #include "config.h"
7 #include "clibrary.h"
8 #include "conffile.h"
9 #include "libinn.h"
10
11 static int getconfline(CONFFILE *F, char *buffer, int length) {
12   if (F->f) {
13     fgets(buffer, length, F->f);
14     if (ferror(F->f)) {
15       return 1;
16     }
17   } else if (F->array) {
18     strlcpy(buffer, F->array[F->lineno], F->sbuf);
19   }
20   F->lineno++;
21   if (strlen (F->buf) >= F->sbuf - 1) {
22     return 1; /* Line too long */
23   } else {
24     return 0;
25   }
26 }
27
28 static int cfeof(CONFFILE *F) {
29   if (F->f) {
30     return feof(F->f);
31   } else if (F->array) {
32     return (F->lineno == F->array_len);
33   } else {
34     return 1;
35   }
36 }
37
38 static char *CONFgetword(CONFFILE *F)
39 {
40   char *p;
41   char *s;
42   char *t;
43   char *word;
44   bool flag, comment;
45
46   if (!F) return (NULL);        /* No conf file */
47   if (!F->buf || !F->buf[0]) {
48     if (cfeof (F)) return (NULL);
49     if (!F->buf) {
50       F->sbuf = BIG_BUFFER;
51       F->buf = xmalloc(F->sbuf);
52     }
53     if (getconfline(F, F->buf, F->sbuf) != 0)
54       return (NULL); /* Line too long */
55   }
56   do {
57      /* Ignore blank and comment lines. */
58      if ((p = strchr(F->buf, '\n')) != NULL)
59        *p = '\0';
60      for (p = F->buf; *p == ' ' || *p == '\t' ; p++);
61      flag = true;
62      if ((*p == '\0' || *p == '#') && !cfeof(F)) {
63        flag = false;
64        if (getconfline(F, F->buf, F->sbuf))
65          return (NULL); /* Line too long */
66        continue;
67      }
68      break;
69   } while (!cfeof(F) || !flag);
70
71   comment = false;
72   if (*p == '"') { /* double quoted string ? */
73     p++;
74     do {
75       for (t = p; (*t != '"' || (*t == '"' && *(t - 1) == '\\')) &&
76              *t != '\0'; t++);
77       if (*t == '\0') {
78         if (strlen(F->buf) >= F->sbuf - 2)
79           return (NULL); /* Line too long */
80         *t++ = '\n';
81         *t = '\0';
82         if (getconfline(F, t, F->sbuf - strlen(F->buf)))
83           return (NULL); /* Line too long */
84         if ((s = strchr(t, '\n')) != NULL)
85           *s = '\0';
86       }
87       else 
88         break;
89     } while (!cfeof(F));
90     if (*t != '"')
91       return (NULL);
92     *t++ = '\0';
93   }
94   else {
95     for (t = p; *t != ' ' && *t != '\t' && *t != '\0'; t++)
96       if (*t == '#' && (t == p || *(t - 1) != '\\')) {
97         comment = true;
98         break;
99       }
100     if (*t != '\0')
101       *t++ = '\0';
102   }
103   if (*p == '\0' && cfeof(F)) return (NULL);
104   word = xstrdup (p);
105   p = F->buf;
106   if (!comment)
107     for (; *t != '\0'; t++)
108       *p++ = *t;
109   *p = '\0';
110
111   return (word);
112 }
113
114 CONFFILE *CONFfopen(char *filename)
115 {
116   FILE *f;
117   CONFFILE *ret;
118
119   f = fopen(filename, "r");
120   if (!f)
121     return(0);
122   ret = xmalloc(sizeof(CONFFILE));
123   if (!ret) {
124     fclose(f);
125     return(0);
126   }
127   ret->filename = xstrdup(filename);
128   ret->buf = 0;
129   ret->sbuf = 0;
130   ret->lineno = 0;
131   ret->f = f;
132   ret->array = NULL;
133   return(ret);
134 }
135
136 void CONFfclose(CONFFILE *f)
137 {
138   if (!f) return;               /* No conf file */
139   fclose(f->f);
140   if (f->buf)
141     free(f->buf);
142   if (f->filename)
143     free(f->filename);
144   free(f);
145 }
146
147 CONFTOKEN *CONFgettoken(CONFTOKEN *toklist, CONFFILE *file)
148 {
149   char *word;
150   static CONFTOKEN ret = {CONFstring, 0};
151   int i;
152
153   if (ret.name) {
154     free(ret.name);
155     ret.name = 0;
156   }
157   word = CONFgetword(file);
158   if (!word)
159     return(0);
160   if (toklist) {
161     for (i = 0; toklist[i].type; i++) {
162        if (strcmp(word, toklist[i].name) == 0) {
163          free(word);
164          return(&toklist[i]);
165        }
166     }
167   }
168   ret.name = word;
169   return(&ret);
170 }