2 * rlm_dbm_parser.c : Create dbm file from plain text
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 2001 Koulik Andrei, Sandy Service
25 "$Id$ sandy module project\n Copyright 2001 Sandy Service\nCopyright 2001 Koulik Andrei";
27 #include <freeradius-devel/radiusd.h>
34 #ifdef HAVE_GDBM_NDBM_H
35 #include <gdbm/ndbm.h>
38 #ifdef HAVE_GDBMNDBM_H
39 #include <gdbm-ndbm.h>
44 #include <freeradius-devel/conf.h>
45 #include <freeradius-devel/radpaths.h>
47 #define MAX_BUFF_SIZE 1024
49 #define DOUT1 if( librad_debug > 0 ) printf
50 #define DOUT2 if( librad_debug > 5 ) printf
52 typedef enum sm_parse_state_t {
63 const char * progname;
65 unsigned long st_errors = 0,
75 int dumplist(VALUE_PAIR *vp)
79 vp_prints(buffer, sizeof(buffer), vp);
81 printf("\t%s\n", buffer);
92 int oflags = O_RDWR | O_CREAT;
96 static int open_storage(const char * fname) {
98 if ( (pdb = dbm_open(fname, oflags, 0600 )) == NULL ) {
99 perror("Couldn't open database");
105 static void close_storage(void){
109 static int addlinetocontent(VALUE_PAIR *vp) {
111 int outlen = sizeof(content) - concntr - 1;
114 if ( outlen < 4 ) return -1;
115 if ( vp == NULL ) { /* add empty line */
116 content[concntr++] = '\n';
117 content[concntr] = '\0';
119 while ( vp != NULL ){
120 lendiv = vp_prints(&content[concntr],outlen,vp);
125 strcat(content,", ");
126 concntr += lendiv + 2;
136 if ( concntr > 2 ) { /* remove trailing ',' */
137 content[--concntr] = '\0';
138 content[concntr - 1] = '\n';
145 static int storecontent (const char * username) {
150 if ( pdb == NULL || concntr < 2 ) return 1;
152 DOUT2("store:\n%s\ncontent:\n%s",username,content);
155 d.dsize = concntr + 1;
158 k.dsize = strlen(username) + 1;
160 res = dbm_store(pdb, k, d, DBM_INSERT);
161 if ( res == 1 ) dbm_store(pdb, k, d, DBM_REPLACE);
163 perror("Couldn't insert record");
173 static int getuname(char **p,char *u,int n) {
176 for(i=0 ; ( i < n-1 ) && ( **p ) && (! isspace((int) **p) ) ; (*p)++ )
179 return ( i == 0) ? 1:0;
182 static int sm_parse_file(FILE*fp,const char* fname) {
184 VALUE_PAIR *vp = NULL;
185 sm_parse_state_t parse_state = SMP_USER;
186 unsigned long lino = 0;
188 char buff[MAX_BUFF_SIZE];
192 while( parse_state != SMP_INVALID && fgets(buff, sizeof(buff), fp) != NULL ) {
196 if ( strchr(buff, '\n') == NULL) {
197 fprintf(stderr,"%s: %s[%lu]:Warning: line too long or not closed by \\n character. Skiped\n",progname,fname,lino);
199 st_skiped++; /* _LINE_ skiped */
203 DOUT2("Parseline: %s",buff);
204 for ( p = buff; isspace((int) *p); p++);
206 if ( *p == '#' || *p == 0 ) continue;
209 if ( *p == ';' ) *p = '\n';
212 /* try to decide is this line new user or new pattern */
213 if ( parse_state == SMP_PATTERN_OR_USER ) {
214 if ( isspace((int) buff[0]) ) parse_state = SMP_PATTERN;
216 parse_state = SMP_USER;
217 storecontent(username);
222 if ( parse_state == SMP_USER ) {
223 tok = getuname(&p,username,sizeof(username));
225 /* check: is it include. not implemented */
228 fprintf(stderr ,"%s: %s[%lu]: error while expecting user name\n",progname,fname,lino);
229 parse_state = SMP_INVALID;
232 parse_state = SMP_PATTERN;
233 DOUT1("Found user: %s\n",username);
237 if ( parse_state == SMP_PATTERN || parse_state == SMP_ACTION ) {
239 /* check for empty line */
240 while( *p && isspace((int) *p) ) p++;
242 if ( *p && ( *p != ';' ) ) tok = userparse(p,&vp);
243 else tok = T_EOL; /* ';' - signs empty line */
246 case T_EOL: /* add to content */
247 addlinetocontent(vp);
249 if ( parse_state == SMP_PATTERN )
250 parse_state = SMP_ACTION;
251 else parse_state = SMP_PATTERN_OR_USER;
253 case T_COMMA: break; /* parse next line */
254 default: /* error: we do not expect anything else */
255 fprintf(stderr ,"%s: %s[%lu]: sintax error\n",progname,fname,lino);
256 librad_perror("Error");
257 parse_state = SMP_INVALID;
262 if ( feof(fp) ) switch (parse_state ) {
263 case SMP_USER: /* file is empty, last line is comment */
265 case SMP_PATTERN: /* only username ?*/
266 fprintf(stderr ,"%s: %s[%lu]: EOF while pattern line are expecting\n",progname,fname,lino);
268 parse_state = SMP_INVALID;
270 case SMP_ACTION: /* looking for reply line */
271 fprintf(stderr ,"%s: %s[%lu]: EOF while reply line are expecting\n",progname,fname,lino);
273 parse_state = SMP_INVALID;
275 case SMP_PATTERN_OR_USER:
276 storecontent(username);
280 } else if ( parse_state != SMP_INVALID ) { /* file read error */
281 fprintf(stderr ,"%s: error file reading from file\n",progname);
285 return (parse_state == SMP_INVALID)?-1:0;
289 static void sm_usage(void) {
290 fprintf(stderr, "Usage: %s [-c] [-d raddb] [-i inputfile] [-o outputfile] [-x] [-v] [-q] [username1 [username2] ...]\n\n",progname);
292 fprintf(stderr, "-c create new database.\n");
293 fprintf(stderr, "-x debug mode.\n");
294 fprintf(stderr, "-q do not print statistic\n");
295 fprintf(stderr, "-v print version\n");
296 fprintf(stderr, "-r remove user(s) from database\n");
300 int main(int n,char **argv) {
302 const char *fname = NULL;
303 const char *ofile = NULL;
307 const char *sm_radius_dir = NULL;
313 while ((ch = getopt(n, argv, "d:i:xo:qvc")) != -1)
316 sm_radius_dir = optarg;
330 printf("%s: $Id$ \n",progname);
333 oflags = O_CREAT | O_TRUNC | O_RDWR;
335 default: sm_usage();exit(1);
341 if ( sm_radius_dir == NULL ) sm_radius_dir = RADDBDIR;
343 DOUT1("Use dictionary in: %s\n",sm_radius_dir);
344 if (dict_init(sm_radius_dir, RADIUS_DICTIONARY) < 0 ) {
345 librad_perror("parser: init dictionary:");
349 if ( fname == NULL || fname[0] == '-') {
352 } else if ( ( fp = fopen(fname, "r") ) == NULL ) {
353 fprintf( stderr,"%s: Couldn't open source file\n", progname);
357 if ( ofile == NULL ) ofile = "sandy_db" ;
358 if ( open_storage(ofile) ) {
362 sm_parse_file(fp,fname);
367 fprintf(stderr,"\nRecord loaded: %lu\nLines parsed: %lu\nRecord skiped: %lu\nWarnings: %lu\nErrors: %lu\n"
368 ,st_loaded,st_lines,st_skiped,st_warns,st_errors);