📄 files.c
字号:
/* * files.c Read config files into memory. * * Version: $Id: files.c,v 1.107 2008/01/06 01:53:58 nbk Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2000,2006 The FreeRADIUS server project * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl> * Copyright 2000 Alan DeKok <aland@ox.org> */#include <freeradius-devel/ident.h>RCSID("$Id: files.c,v 1.107 2008/01/06 01:53:58 nbk Exp $")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/rad_assert.h>#include <sys/stat.h>#include <ctype.h>#include <fcntl.h>/* * Free a PAIR_LIST */void pairlist_free(PAIR_LIST **pl){ PAIR_LIST *p, *next; for (p = *pl; p; p = next) { /* name is allocated contiguous with p */ if (p->check) pairfree(&p->check); if (p->reply) pairfree(&p->reply); next = p->next; free(p); } *pl = NULL;}#define FIND_MODE_NAME 0#define FIND_MODE_REPLY 1/* * Read the users, huntgroups or hints file. * Return a PAIR_LIST. */int pairlist_read(const char *file, PAIR_LIST **list, int complain){ FILE *fp; int mode = FIND_MODE_NAME; char entry[256]; char buffer[8192]; const char *ptr; VALUE_PAIR *check_tmp; VALUE_PAIR *reply_tmp; PAIR_LIST *pl = NULL, *t; PAIR_LIST **last = &pl; int lineno = 0; int old_lineno = 0; FR_TOKEN parsecode; char newfile[8192]; /* * Open the file. The error message should be a little * more useful... */ if ((fp = fopen(file, "r")) == NULL) { if (!complain) return -1; radlog(L_CONS|L_ERR, "Couldn't open %s for reading: %s", file, strerror(errno)); return -1; } parsecode = T_EOL; /* * Read the entire file into memory for speed. */ while(fgets(buffer, sizeof(buffer), fp) != NULL) { lineno++; if (!feof(fp) && (strchr(buffer, '\n') == NULL)) { fclose(fp); radlog(L_ERR, "%s[%d]: line too long", file, lineno); pairlist_free(&pl); return -1; } if (buffer[0] == '#' || buffer[0] == '\n') continue; /* * If the line contains nothing but whitespace, * ignore it. */ ptr = buffer; while (isspace((int) *ptr)) ptr++; if (*ptr == '\0') continue;parse_again: if(mode == FIND_MODE_NAME) { /* * Find the entry starting with the users name */ if (isspace((int) buffer[0])) { if (parsecode != T_EOL) { radlog(L_ERR|L_CONS, "%s[%d]: Unexpected trailing comma for entry %s", file, lineno, entry); fclose(fp); return -1; } continue; } ptr = buffer; getword(&ptr, entry, sizeof(entry)); /* * Include another file if we see * $INCLUDE filename */ if (strcasecmp(entry, "$include") == 0) { while(isspace((int) *ptr)) ptr++; /* * If it's an absolute pathname, * then use it verbatim. * * If not, then make the $include * files *relative* to the current * file. */ if (FR_DIR_IS_RELATIVE(ptr)) { char *p; strlcpy(newfile, file, sizeof(newfile)); p = strrchr(newfile, FR_DIR_SEP); if (!p) { p = newfile + strlen(newfile); *p = FR_DIR_SEP; } getword(&ptr, p + 1, sizeof(newfile) - 1 - (p - buffer)); } else { getword(&ptr, newfile, sizeof(newfile)); } t = NULL; if (pairlist_read(newfile, &t, 0) != 0) { pairlist_free(&pl); radlog(L_ERR|L_CONS, "%s[%d]: Could not open included file %s: %s", file, lineno, newfile, strerror(errno)); fclose(fp); return -1; } *last = t; /* * t may be NULL, it may have one * entry, or it may be a linked list * of entries. Go to the end of the * list. */ while (*last) last = &((*last)->next); continue; } /* * Parse the check values */ check_tmp = NULL; reply_tmp = NULL; old_lineno = lineno; parsecode = userparse(ptr, &check_tmp); if (parsecode == T_OP_INVALID) { pairlist_free(&pl); radlog(L_ERR|L_CONS, "%s[%d]: Parse error (check) for entry %s: %s", file, lineno, entry, librad_errstr); fclose(fp); return -1; } else if (parsecode == T_COMMA) { radlog(L_ERR|L_CONS, "%s[%d]: Unexpected trailing comma in check item list for entry %s", file, lineno, entry); fclose(fp); return -1; } mode = FIND_MODE_REPLY; parsecode = T_COMMA; } else { if(*buffer == ' ' || *buffer == '\t') { if (parsecode != T_COMMA) { radlog(L_ERR|L_CONS, "%s[%d]: Syntax error: Previous line is missing a trailing comma for entry %s", file, lineno, entry); fclose(fp); return -1; } /* * Parse the reply values */ parsecode = userparse(buffer, &reply_tmp); /* valid tokens are 1 or greater */ if (parsecode < 1) { pairlist_free(&pl); radlog(L_ERR|L_CONS, "%s[%d]: Parse error (reply) for entry %s: %s", file, lineno, entry, librad_errstr); fclose(fp); return -1; } } else { size_t entry_len; char *q; entry_len = strlen(entry) + 1; /* * Done with this entry... */ q = rad_malloc(sizeof(*t) + entry_len); t = (PAIR_LIST *) q; memset(t, 0, sizeof(*t)); t->check = check_tmp; t->reply = reply_tmp; t->lineno = old_lineno; check_tmp = NULL; reply_tmp = NULL; q += sizeof(*t); memcpy(q, entry, entry_len); t->name = q; *last = t; last = &(t->next); mode = FIND_MODE_NAME; if (buffer[0] != 0) goto parse_again; } } } /* * Make sure that we also read the last line of the file! */ if (mode == FIND_MODE_REPLY) { buffer[0] = 0; goto parse_again; } fclose(fp); *list = pl; return 0;}/* * Debug code. */#if 0static void debug_pair_list(PAIR_LIST *pl){ VALUE_PAIR *vp; while(pl) { printf("Pair list: %s\n", pl->name); printf("** Check:\n"); for(vp = pl->check; vp; vp = vp->next) { printf(" "); fprint_attr_val(stdout, vp); printf("\n"); } printf("** Reply:\n"); for(vp = pl->reply; vp; vp = vp->next) { printf(" "); fprint_attr_val(stdout, vp); printf("\n"); } pl = pl->next; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -