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