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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/autoconf.h>
36 #ifdef HAVE_GDBM_NDBM_H
37 #include <gdbm/ndbm.h>
40 #ifdef HAVE_GDBMNDBM_H
41 #include <gdbm-ndbm.h>
48 #include <freeradius-devel/radiusd.h>
50 #include <freeradius-devel/conf.h>
51 #include <freeradius-devel/radpaths.h>
52 #include <freeradius-devel/missing.h>
54 #define MAX_BUFF_SIZE 1024
56 #define DOUT1 if( librad_debug > 0 ) printf
57 #define DOUT2 if( librad_debug > 5 ) printf
59 typedef enum sm_parse_state_t {
70 const char * progname;
72 unsigned long st_errors = 0,
82 int dumplist(VALUE_PAIR *vp) {
86 printf("VP: name: %s\nattribute: %d\ntype: %d\nlvalue: %lu"
87 "\noperator %d\naddport: %d\nValue: %s\n",
88 vp -> name, vp -> attribute, vp -> type, vp -> lvalue,
89 vp -> operator, vp -> addport, (char*)vp -> strvalue);
100 int oflags = O_RDWR | O_CREAT;
104 static int open_storage(const char * fname) {
106 if ( (pdb = dbm_open(fname, oflags, 0600 )) == NULL ) {
107 perror("Couldn't open database");
113 static void close_storage(void){
117 static int addlinetocontent(VALUE_PAIR *vp) {
119 int outlen = sizeof(content) - concntr - 1;
122 if ( outlen < 4 ) return -1;
123 if ( vp == NULL ) { /* add empty line */
124 content[concntr++] = '\n';
125 content[concntr] = '\0';
127 while ( vp != NULL ){
128 lendiv = vp_prints(&content[concntr],outlen,vp);
133 strcat(content,", ");
134 concntr += lendiv + 2;
144 if ( concntr > 2 ) { /* remove trailing ',' */
145 content[--concntr] = '\0';
146 content[concntr - 1] = '\n';
153 static int storecontent (const char * username) {
158 if ( pdb == NULL || concntr < 3 ) return 1;
160 DOUT2("store:\n%s\ncontent:\n%s",username,content);
163 d.dsize = concntr + 1;
166 k.dsize = strlen(username) + 1;
168 res = dbm_store(pdb, k, d, DBM_INSERT);
169 if ( res == 1 ) dbm_store(pdb, k, d, DBM_REPLACE);
171 perror("Couldn't insert record");
181 static int getuname(char **p,char *u,int n) {
184 for(i=0 ; ( i < n-1 ) && ( **p ) && (! isspace((int) **p) ) ; (*p)++ )
187 return ( i == 0) ? 1:0;
190 static int sm_parse_file(FILE*fp,const char* fname) {
192 VALUE_PAIR *vp = NULL;
193 sm_parse_state_t parse_state = SMP_USER;
194 unsigned long lino = 0;
196 char buff[MAX_BUFF_SIZE];
200 while( parse_state != SMP_INVALID && fgets(buff, sizeof(buff), fp) != NULL ) {
204 if ( strchr(buff, '\n') == NULL) {
205 fprintf(stderr,"%s: %s[%lu]:Warning: line too long or not closed by \\n character. Skiped\n",progname,fname,lino);
207 st_skiped++; /* _LINE_ skiped */
211 DOUT2("Parseline: %s",buff);
212 for ( p = buff; isspace((int) *p); p++);
214 if ( *p == '#' || *p == 0 ) continue;
217 if ( *p == ';' ) *p = '\n';
220 /* try to decide is this line new user or new pattern */
221 if ( parse_state == SMP_PATTERN_OR_USER ) {
222 if ( isspace((int) buff[0]) ) parse_state = SMP_PATTERN;
224 parse_state = SMP_USER;
225 storecontent(username);
230 if ( parse_state == SMP_USER ) {
231 tok = getuname(&p,username,sizeof(username));
233 /* check: is it include. not implemented */
236 fprintf(stderr ,"%s: %s[%lu]: error while expecting user name\n",progname,fname,lino);
237 parse_state = SMP_INVALID;
240 parse_state = SMP_PATTERN;
241 DOUT1("Found user: %s\n",username);
245 if ( parse_state == SMP_PATTERN || parse_state == SMP_ACTION ) {
247 /* check for empty line */
248 while( *p && isspace((int) *p) ) p++;
250 if ( *p && ( *p != ';' ) ) tok = userparse(p,&vp);
251 else tok = T_EOL; /* ';' - signs empty line */
254 case T_EOL: /* add to content */
255 addlinetocontent(vp);
257 if ( parse_state == SMP_PATTERN )
258 parse_state = SMP_ACTION;
259 else parse_state = SMP_PATTERN_OR_USER;
261 case T_COMMA: break; /* parse next line */
262 default: /* error: we do not expect anything else */
263 fprintf(stderr ,"%s: %s[%lu]: sintax error\n",progname,fname,lino);
264 librad_perror("Error");
265 parse_state = SMP_INVALID;
270 if ( feof(fp) ) switch (parse_state ) {
271 case SMP_USER: /* file is empty, last line is comment */
273 case SMP_PATTERN: /* only username ?*/
274 fprintf(stderr ,"%s: %s[%lu]: EOF while pattern line are expecting\n",progname,fname,lino);
276 parse_state = SMP_INVALID;
278 case SMP_ACTION: /* looking for reply line */
279 fprintf(stderr ,"%s: %s[%lu]: EOF while reply line are expecting\n",progname,fname,lino);
281 parse_state = SMP_INVALID;
283 case SMP_PATTERN_OR_USER:
284 storecontent(username);
288 } else if ( parse_state != SMP_INVALID ) { /* file read error */
289 fprintf(stderr ,"%s: error file reading from file\n",progname);
293 return (parse_state == SMP_INVALID)?-1:0;
297 static void sm_usage(void) {
298 fprintf(stderr, "Usage: %s [-c] [-d raddb] [-i inputfile] [-o outputfile] [-x] [-v] [-q] [username1 [username2] ...]\n\n",progname);
300 fprintf(stderr, "-c create new database.\n");
301 fprintf(stderr, "-x debug mode.\n");
302 fprintf(stderr, "-q do not print statistic\n");
303 fprintf(stderr, "-v print version\n");
304 fprintf(stderr, "-r remove user(s) from database\n");
308 int main(int n,char **argv) {
310 const char *fname = NULL;
311 const char *ofile = NULL;
315 const char *sm_radius_dir = NULL;
321 while ((ch = getopt(n, argv, "d:i:xo:qvc")) != -1)
324 sm_radius_dir = optarg;
338 printf("%s: $Id$ \n",progname);
341 oflags = O_CREAT | O_TRUNC | O_RDWR;
343 default: sm_usage();exit(1);
349 if ( sm_radius_dir == NULL ) sm_radius_dir = RADDBDIR;
351 DOUT1("Use dictionary in: %s\n",sm_radius_dir);
352 if (dict_init(sm_radius_dir, RADIUS_DICTIONARY) < 0 ) {
353 librad_perror("parser: init dictionary:");
357 if ( fname == NULL || fname[0] == '-') {
360 } else if ( ( fp = fopen(fname, "r") ) == NULL ) {
361 fprintf( stderr,"%s: Couldn't open source file\n", progname);
365 if ( ofile == NULL ) ofile = "sandy_db" ;
366 if ( open_storage(ofile) ) {
370 sm_parse_file(fp,fname);
375 fprintf(stderr,"\nRecord loaded: %lu\nLines parsed: %lu\nRecord skiped: %lu\nWarnings: %lu\nErrors: %lu\n"
376 ,st_loaded,st_lines,st_skiped,st_warns,st_errors);