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;
78 * Open the file. The error message should be a little
81 if ((fp = fopen(file, "r")) == NULL) {
84 radlog(L_CONS|L_ERR, "Couldn't open %s for reading: %s",
85 file, strerror(errno));
92 * Read the entire file into memory for speed.
94 while(fgets(buffer, sizeof(buffer), fp) != NULL) {
96 if (!feof(fp) && (strchr(buffer, '\n') == NULL)) {
98 radlog(L_ERR, "%s[%d]: line too long", file, lineno);
102 if (buffer[0] == '#' || buffer[0] == '\n') continue;
105 * If the line contains nothing but whitespace,
109 while (isspace((int) *ptr)) ptr++;
110 if (*ptr == '\0') continue;
113 if(mode == FIND_MODE_NAME) {
115 * Find the entry starting with the users name
117 if (isspace((int) buffer[0])) {
118 if (parsecode != T_EOL) {
120 "%s[%d]: Unexpected trailing comma for entry %s",
121 file, lineno, entry);
129 getword(&ptr, entry, sizeof(entry));
132 * Include another file if we see
135 if (strcasecmp(entry, "$include") == 0) {
136 while(isspace((int) *ptr))
140 * If it's an absolute pathname,
141 * then use it verbatim.
143 * If not, then make the $include
144 * files *relative* to the current
147 if (FR_DIR_IS_RELATIVE(ptr)) {
150 strlcpy(newfile, file,
152 p = strrchr(newfile, FR_DIR_SEP);
154 p = newfile + strlen(newfile);
158 sizeof(newfile) - 1 - (p - buffer));
160 getword(&ptr, newfile,
165 if (pairlist_read(newfile, &t, 0) != 0) {
168 "%s[%d]: Could not open included file %s: %s",
169 file, lineno, newfile, strerror(errno));
176 * t may be NULL, it may have one
177 * entry, or it may be a linked list
178 * of entries. Go to the end of the
182 last = &((*last)->next);
187 * Parse the check values
192 parsecode = userparse(ptr, &check_tmp);
193 if (parsecode == T_OP_INVALID) {
196 "%s[%d]: Parse error (check) for entry %s: %s",
197 file, lineno, entry, fr_strerror());
200 } else if (parsecode == T_COMMA) {
202 "%s[%d]: Unexpected trailing comma in check item list for entry %s",
203 file, lineno, entry);
207 mode = FIND_MODE_REPLY;
211 if(*buffer == ' ' || *buffer == '\t') {
212 if (parsecode != T_COMMA) {
214 "%s[%d]: Syntax error: Previous line is missing a trailing comma for entry %s",
215 file, lineno, entry);
221 * Parse the reply values
223 parsecode = userparse(buffer, &reply_tmp);
224 /* valid tokens are 1 or greater */
228 "%s[%d]: Parse error (reply) for entry %s: %s",
229 file, lineno, entry, fr_strerror());
238 entry_len = strlen(entry) + 1;
241 * Done with this entry...
243 q = rad_malloc(sizeof(*t) + entry_len);
246 memset(t, 0, sizeof(*t));
247 t->check = check_tmp;
248 t->reply = reply_tmp;
249 t->lineno = old_lineno;
254 memcpy(q, entry, entry_len);
260 mode = FIND_MODE_NAME;
267 * Make sure that we also read the last line of the file!
269 if (mode == FIND_MODE_REPLY) {
284 static void debug_pair_list(PAIR_LIST *pl)
289 printf("Pair list: %s\n", pl->name);
290 printf("** Check:\n");
291 for(vp = pl->check; vp; vp = vp->next) {
293 fprint_attr_val(stdout, vp);
296 printf("** Reply:\n");
297 for(vp = pl->reply; vp; vp = vp->next) {
299 fprint_attr_val(stdout, vp);