2 * files.c Read config files into memory.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000,2006 The FreeRADIUS server project
21 * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
22 * Copyright 2000 Alan DeKok <aland@ox.org>
25 #include <freeradius-devel/ident.h>
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/rad_assert.h>
39 void pairlist_free(PAIR_LIST **pl)
43 for (p = *pl; p; p = next) {
44 /* name is allocated contiguous with p */
45 if (p->check) pairfree(&p->check);
46 if (p->reply) pairfree(&p->reply);
54 #define FIND_MODE_NAME 0
55 #define FIND_MODE_REPLY 1
58 * Read the users, huntgroups or hints file.
61 int pairlist_read(const char *file, PAIR_LIST **list, int complain)
64 int mode = FIND_MODE_NAME;
68 VALUE_PAIR *check_tmp;
69 VALUE_PAIR *reply_tmp;
70 PAIR_LIST *pl = NULL, *t;
71 PAIR_LIST **last = &pl;
77 DEBUG2("reading pairlist file %s", file);
80 * Open the file. The error message should be a little
83 if ((fp = fopen(file, "r")) == NULL) {
86 radlog(L_ERR, "Couldn't open %s for reading: %s",
87 file, strerror(errno));
94 * Read the entire file into memory for speed.
96 while(fgets(buffer, sizeof(buffer), fp) != NULL) {
98 if (!feof(fp) && (strchr(buffer, '\n') == NULL)) {
100 radlog(L_ERR, "%s[%d]: line too long", file, lineno);
104 if (buffer[0] == '#' || buffer[0] == '\n') continue;
107 * If the line contains nothing but whitespace,
111 while (isspace((int) *ptr)) ptr++;
112 if (*ptr == '\0') continue;
115 if(mode == FIND_MODE_NAME) {
117 * Find the entry starting with the users name
119 if (isspace((int) buffer[0])) {
120 if (parsecode != T_EOL) {
122 "%s[%d]: Unexpected trailing comma for entry %s",
123 file, lineno, entry);
131 getword(&ptr, entry, sizeof(entry));
134 * Include another file if we see
137 if (strcasecmp(entry, "$INCLUDE") == 0) {
138 while(isspace((int) *ptr))
142 * If it's an absolute pathname,
143 * then use it verbatim.
145 * If not, then make the $include
146 * files *relative* to the current
149 if (FR_DIR_IS_RELATIVE(ptr)) {
152 strlcpy(newfile, file,
154 p = strrchr(newfile, FR_DIR_SEP);
156 p = newfile + strlen(newfile);
160 sizeof(newfile) - 1 - (p - newfile));
162 getword(&ptr, newfile,
168 if (pairlist_read(newfile, &t, 0) != 0) {
171 "%s[%d]: Could not open included file %s: %s",
172 file, lineno, newfile, strerror(errno));
179 * t may be NULL, it may have one
180 * entry, or it may be a linked list
181 * of entries. Go to the end of the
185 last = &((*last)->next);
190 * Parse the check values
195 parsecode = userparse(ptr, &check_tmp);
196 if (parsecode == T_OP_INVALID) {
199 "%s[%d]: Parse error (check) for entry %s: %s",
200 file, lineno, entry, fr_strerror());
203 } else if (parsecode == T_COMMA) {
205 "%s[%d]: Unexpected trailing comma in check item list for entry %s",
206 file, lineno, entry);
210 mode = FIND_MODE_REPLY;
214 if(*buffer == ' ' || *buffer == '\t') {
215 if (parsecode != T_COMMA) {
217 "%s[%d]: Syntax error: Previous line is missing a trailing comma for entry %s",
218 file, lineno, entry);
224 * Parse the reply values
226 parsecode = userparse(buffer, &reply_tmp);
227 /* valid tokens are 1 or greater */
231 "%s[%d]: Parse error (reply) for entry %s: %s",
232 file, lineno, entry, fr_strerror());
241 entry_len = strlen(entry) + 1;
244 * Done with this entry...
246 q = rad_malloc(sizeof(*t) + entry_len);
249 memset(t, 0, sizeof(*t));
250 t->check = check_tmp;
251 t->reply = reply_tmp;
252 t->lineno = old_lineno;
257 memcpy(q, entry, entry_len);
263 mode = FIND_MODE_NAME;
270 * Make sure that we also read the last line of the file!
272 if (mode == FIND_MODE_REPLY) {
287 static void debug_pair_list(PAIR_LIST *pl)
292 printf("Pair list: %s\n", pl->name);
293 printf("** Check:\n");
294 for(vp = pl->check; vp; vp = vp->next) {
296 fprint_attr_val(stdout, vp);
299 printf("** Reply:\n");
300 for(vp = pl->reply; vp; vp = vp->next) {
302 fprint_attr_val(stdout, vp);