/* $Id: conffile.c,v 1.21 2000/07/19 19:45:43 akool Exp $ * * ISDN accounting for isdn4linux. * * Copyright 1996 by Stefan Luethje (luethje@sl-gw.lake.de) * * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: conffile.c,v $ * Revision 1.21 2000/07/19 19:45:43 akool * increased BUFSIZ * * Revision 1.20 1999/11/03 16:13:36 paul * Added { } to suppress egcs warnings. * * Revision 1.19 1998/05/20 12:22:15 paul * More paranoid about freeing pointers. * * Revision 1.18 1998/05/20 09:56:14 paul * Oops, the temp string _was_ necessary. Made it static so that returning a * pointer to it is not a problem. * * Revision 1.17 1998/05/20 09:25:01 paul * function Find_Section returned pointer to local automatic variable. Local * variable removed, as it was not necessary; now return parameter. * * Revision 1.16 1997/05/25 19:41:23 luethje * isdnlog: close all files and open again after kill -HUP * isdnrep: support vbox version 2.0 * isdnconf: changes by Roderich Schupp * conffile: ignore spaces at the end of a line * * Revision 1.15 1997/04/15 22:37:20 luethje * allows the character `"' in the program argument like the shell. * some bugfixes. * * Revision 1.14 1997/04/15 00:20:13 luethje * replace variables: some bugfixes, README comleted * * Revision 1.13 1997/04/10 23:41:26 luethje * some bug fixes * * Revision 1.11 1997/04/03 22:39:11 luethje * bug fixes: environ variables are working again, no seg. 11 :-) * improved performance for reading the config files. * * Revision 1.10 1997/03/24 03:56:30 fritz * Fixed 2 typos * * Revision 1.9 1997/03/23 23:12:10 luethje * improved performance * * Revision 1.8 1997/03/20 00:22:51 luethje * Only a test * */ #define _CONFFILE_C_ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "conffile.h" /****************************************************************************/ #define F_TAG 1 #define F_UNTAG 2 #define C_EXIST '!' /****************************************************************************/ static int (*print_msg)(const char *, ...) = printf; /****************************************************************************/ static int Write_Lines(section *Section, FILE *fp, const char *FileName, int Level); static section *Read_Lines(section *Section, FILE *fp, const char *FileName, int *Line, int Flags); static char *Find_Section(char* String); static int Find_Entry(const char *FileName, int Line, char* String, char** Variable, char** Value); static entry* Append_Entry(entry** Entry, char *Variable, char* Value, section *SubSection, int Flag); static void free_entry(entry *Ptr); static void free_cfile(cfile **cfiles); static const char *Pre_String(int Level); static int Compare_Sections(section* sec1, section *sec2, char **variables); static section *Insert_Section(section **main_sec, section **ins_sec, char **variables, int flags); static int Merge_Sections(section **main_sec, section **ins_sec, char **variables, int flags); static int Append_Sections(section **main_sec, section *app_sec); static int Find_Include(section **Section, char* String, const char *FileName, int Flags); static section* _Get_Section_From_Path(char **array, section* Section, section **RetSection, entry **RetEntry, int flags); static entry* _Get_Entry_From_Path(char **array, entry* Entry, section **RetSection, entry **RetEntry, int flags); static section* Get_Section_From_Path(section* NewSection, char *Path, entry **RetEntry); static char* Delete_Chars(char *String, char *Quote); static int Set_Ret_Code(char *Value, int Type, void **Pointer); static int del_untagged_items(section **sec); static char** Compare_Section_Get_Path(char **array, int *retsize, int *retdepth); /****************************************************************************/ void set_print_fct_for_conffile(int (*new_print_msg)(const char *, ...)) { print_msg = new_print_msg; } /****************************************************************************/ section *write_file(section *Section, const char *FileName, char *Program, char* Version) { FILE *fp; time_t t =time(NULL); if ((fp = fopen(FileName, "w")) == NULL) { print_msg("Can't write `%s' (%s)\n",FileName,strerror(errno)); return NULL; } fprintf(fp,"###############################################################################\n"); fprintf(fp,"#\n"); fprintf(fp,"# File %s generated by %s %s on %s",FileName,Program,Version,ctime(&t)); fprintf(fp,"#\n"); fprintf(fp,"###############################################################################\n"); Write_Lines(Section,fp,FileName,0); fclose(fp); return Section; } /****************************************************************************/ static int Write_Lines(section *Section, FILE *fp, const char *FileName, int Level) { entry *Ptr; while (Section != NULL) { fprintf(fp,"\n%s[%s]\n", Pre_String(Level), Section->name); Ptr = Section->entries; while (Ptr != NULL) { if (Ptr->name) { fprintf(fp,"%s%s %c ", Pre_String(Level), Ptr->name, C_EQUAL); if (Ptr->value != NULL) fprintf(fp,"%s\n",Quote_Chars(Ptr->value)); else if (Ptr->subsection != NULL) { fprintf(fp,"%c\n", C_BEGIN_SUBSECTION); Write_Lines(Ptr->subsection,fp,FileName,Level+1); fprintf(fp,"%s%c\n", Pre_String(Level), C_END_SUBSECTION); fflush(fp); } else print_msg("Warning in file `%s': There is no value for `%s'!\n", FileName, Ptr->name); } Ptr = Ptr->next; } Section = Section->next; } return 0; } /****************************************************************************/ static const char *Pre_String(int Level) { static int OldLevel = -1; static char PreString[SHORT_STRING_SIZE]; if (Level != OldLevel) { memset(PreString,' ',Level*2); PreString[Level*2] = '\0'; OldLevel = Level; } return PreString; } /****************************************************************************/ section *read_file(section *Section, const char *FileName, int Flags) { int Line = 0; FILE *fp = NULL; section *RetCode = NULL; if ((fp = fopen(FileName, "r")) == NULL) { if (!(Flags & C_NO_WARN_FILE)) print_msg("Can't open `%s' (%s)\n",FileName,strerror(errno)); return NULL; } RetCode = Read_Lines(Section, fp, FileName, &Line, Flags); fclose(fp); return RetCode; } /****************************************************************************/ static section *Read_Lines(section *Section, FILE *fp, const char *FileName, int *Line, int Flags) { static int InSubSection = 0; char String[8192]; char *Sectionname, *Variable, *Value; int Res; int InInclude = 0; section *Ptr = Section; if (Section != NULL) InInclude = 1; while (FGets(String, sizeof(String), fp, Line) != NULL) { if ((Sectionname = Find_Section(String)) != NULL) { if ((Ptr = Set_Section(&Section,Sectionname,C_OVERWRITE | C_WARN | Flags)) == NULL) { free_section(Section); return NULL; } } else if (Find_Include(&Section,String,FileName,Flags) == 0) { Ptr = Section; if (Ptr != NULL) while (Ptr->next != NULL) Ptr = Ptr->next; /* Ptr = NULL; */ } else if ((Res = Find_Entry(FileName,*Line,String,&Variable,&Value)) == 0) { if (Ptr == NULL) { print_msg("Error in file `%s', line %d: there is no section for variable `%s'!\n",FileName,*Line,Variable); } else { if (*Value == C_BEGIN_SUBSECTION && Not_Space(Value+1) == NULL) { InSubSection++; Set_SubSection(Ptr,Variable,Read_Lines(NULL,fp,FileName,Line,Flags),C_OVERWRITE | C_WARN); /* if (Set_SubSection(Ptr,Variable,Read_Lines(NULL,fp,FileName,Line,Flags),C_OVERWRITE | C_WARN) == NULL) { free_section(Section); return NULL; } */ } else if (Set_Entry(Ptr,NULL,Variable,Value,C_OVERWRITE | C_WARN) == NULL) { free_section(Section); return NULL; } } } else if (Res == -1 && *(Kill_Blanks(String)) == C_END_SUBSECTION) { InSubSection--; return Section; } else if (Res == -1) print_msg("Error in file `%s', line %d: there is no valid token!\n",FileName,*Line); } if (InInclude == 0 && InSubSection != 0) { print_msg("Error in file `%s': Missing a `%c'!\n",FileName,C_END_SUBSECTION); free_section(Section); return NULL; } return Section; } /****************************************************************************/ static char *Find_Section(char* String) { char *Ptr = NULL; static char Help[SHORT_STRING_SIZE]; strcpy(Help,String); String = Kill_Blanks(Help); if (*String == '\0' || *String != C_BEGIN_SECTION) return NULL; Ptr = String + strlen(String)-1; if (Ptr == strchr(String,C_END_SECTION)) { *Ptr = '\0'; Delete_Chars(String+1,S_ALL_QUOTE); return String+1; } return NULL; } /****************************************************************************/ static int Find_Entry(const char *FileName, int Line, char* String, char** Variable, char** Value) { char *Ptr = NULL; if (String == NULL || Variable == NULL || Value == NULL) return -1; *Variable = *Value = NULL; if ((Ptr = strchr(String,C_EQUAL)) == NULL) return -1; else { *Ptr++ ='\0'; Kill_Blanks(String); Delete_Chars(String,S_ALL_QUOTE); if (*String == '\0') { print_msg("Error in file `%s', line %d: There is no variable name!\n", FileName, Line); return -2; } else *Variable = String; } if ((Ptr = Not_Space(Ptr)) == NULL) { print_msg("Error in file `%s', line %d: There is no value for `%s'!\n", FileName, Line, *Variable); return -2; } *Value = Ptr; return 0; } /****************************************************************************/ static int Find_Include(section **Section, char* String, const char *FileName, int Flags) { char *sPtr; section *Ptr = NULL; char Help1[SHORT_STRING_SIZE]; char Help2[SHORT_STRING_SIZE] = ""; strcpy(Help1,String); Kill_Blanks(Help1); if (!strncasecmp(S_KEY_INCLUDE,Help1,strlen(S_KEY_INCLUDE)) && Help1[strlen(S_KEY_INCLUDE)] == C_BEGIN_INCLUDE && Help1[strlen(Help1)-1] == C_END_INCLUDE ) { Ptr = *Section; if (Ptr != NULL) while (Ptr->next != NULL) Ptr = Ptr->next; if (*(Help1+strlen(S_KEY_INCLUDE)+1) != C_SLASH) { if ((sPtr = strrchr(Help2,C_SLASH)) != NULL) { strcpy(Help2,FileName); sPtr[1] = '\0'; } } Help1[strlen(Help1)-1] = '\0'; strcat(Help2,Help1+strlen(S_KEY_INCLUDE)+1); if ((Ptr = read_file(Ptr,Help2,Flags & ~C_NO_WARN_FILE)) == NULL) return -1; else if (*Section == NULL) *Section = Ptr; return 0; } return -1; } /****************************************************************************/ section *Set_Section(section **Section, char *Sectionname, int Flag) { char _Sectionname[SHORT_STRING_SIZE]; section **Ptr = Section; if (Sectionname != NULL) { strcpy(_Sectionname,Sectionname); To_Upper(_Sectionname); } else return NULL; while ((*Ptr) != NULL) { if (!(Flag & C_NOT_UNIQUE) && !strcmp((*Ptr)->name,_Sectionname)) { if (Flag & C_OVERWRITE) { section *Ptr2 = (*Ptr)->next; (*Ptr)->next = NULL; free_section(*Ptr); *Ptr = Ptr2; if (Flag & C_WARN) print_msg("Will overwrite section `%s'!\n", _Sectionname); } else return NULL; } else Ptr = &((*Ptr)->next); } if ((*Ptr = (section*) calloc(1,sizeof(section))) == NULL) return NULL; if (((*Ptr)->name = strdup(_Sectionname)) == NULL) { free_section(*Ptr); *Ptr = NULL; return NULL; } return *Ptr; } /****************************************************************************/ section *Set_SubSection(section *Section, char *Variable, section *SubSection, int Flag) { char _Variable[SHORT_STRING_SIZE]; if (Variable != NULL) { strcpy(_Variable,Variable); To_Upper(_Variable); } else return NULL; if (Append_Entry(&(Section->entries),_Variable,NULL,SubSection,Flag) == NULL) return NULL; else return SubSection; } /****************************************************************************/ entry *Set_Entry(section *Section, char *Sectionname, char *Variable, char *Value, int Flag) { char _Variable[SHORT_STRING_SIZE]; section *Ptr; if (Variable != NULL) { strcpy(_Variable,Variable); To_Upper(_Variable); } else return NULL; if (Sectionname != NULL) { if ((Ptr = Get_Section(Section,Sectionname)) == NULL) return NULL; } else Ptr = Section; return Append_Entry(&(Ptr->entries),_Variable,Value,NULL,Flag); } /****************************************************************************/ entry* Get_Entry(entry* Entry, char *Variable) { while (Entry != NULL && strcasecmp(Entry->name,Variable)) Entry = Entry->next; return Entry; } /****************************************************************************/ section* Get_Section(section* Section, char *Sectionname) { while (Section != NULL && strcasecmp(Section->name,Sectionname)) Section = Section->next; return Section; } /****************************************************************************/ section* Get_SubSection(section* Section, char *Variable) { entry* Ptr; if ((Ptr = Get_Entry(Section->entries,Variable)) == NULL) return NULL; return Ptr->subsection; } /****************************************************************************/ static entry* Append_Entry(entry** Entry, char *Variable, char* Value, section *SubSection, int Flag) { if (Entry == NULL) return NULL; if ((Value != NULL && SubSection != NULL) || (Value == NULL && SubSection == NULL)) return NULL; while ((*Entry) != NULL) { if (!strcmp((*Entry)->name,Variable)) { if (Flag & C_OVERWRITE) { entry *Ptr = (*Entry)->next; (*Entry)->next = NULL; free_entry(*Entry); *Entry = Ptr; if (Flag & C_WARN) print_msg("Will overwrite entry `%s'!\n", Variable); } else if (Flag & C_APPEND && SubSection != NULL && (*Entry)->subsection != NULL) { section **Section = &((*Entry)->subsection); while(*Section != NULL) Section = &((*Section)->next); *Section = SubSection; return *Entry; } else return NULL; } else Entry = &((*Entry)->next); } if ((*Entry = (entry*) calloc(1,sizeof(entry))) == NULL) return NULL; if (((*Entry)->name = strdup(Variable)) == NULL) { free_entry(*Entry); *Entry = NULL; return NULL; } if (Value != NULL) { if (!(Flag & C_ALLOW_LAST_BLANKS)) { int len = strlen(Value)-1; while (len >= 0 && isspace(Value[len])) Value[len--] = '\0'; } if (((*Entry)->value = strdup(Value)) == NULL) { free_entry(*Entry); *Entry = NULL; return NULL; } } else /* SubSection != NULL */ (*Entry)->subsection = SubSection; return *Entry; } /****************************************************************************/ static void free_entry(entry *Ptr) { if (Ptr == NULL) return; free_entry(Ptr->next); free_section(Ptr->subsection); if (Ptr->name) { free(Ptr->name); Ptr->name = NULL; } if (Ptr->value) { free(Ptr->value); Ptr->value = NULL; } free(Ptr); } /****************************************************************************/ void free_section(section *Ptr) { if (Ptr == NULL) return; free_section(Ptr->next); free_entry(Ptr->entries); if (Ptr->name) { free(Ptr->name); Ptr->name = NULL; } free(Ptr); } /****************************************************************************/ section *Del_Section(section **Section, char *Sectionname) { section **RetCode = Section; section *Ptr; if (Section == NULL) return NULL; if (Sectionname != NULL) while ((*Section) != NULL && strcmp((*Section)->name,Sectionname)) Section = &((*Section)->next); if (*Section) { Ptr = *Section; if (Section == RetCode) RetCode = &((*Section)->next); *Section = (*Section)->next; Ptr->next = NULL; free_section(Ptr); } Section = RetCode; return *RetCode; } /****************************************************************************/ static section *Insert_Section(section **main_sec, section **ins_sec, char **variables, int flags) { section *Ptr = NULL; if (main_sec == NULL || ins_sec == NULL || *ins_sec == NULL) { print_msg("%s","One of the sections is emtpy!\n"); return NULL; } if ((*ins_sec)->next != NULL) { print_msg("%s","Can only insert one entry at time!\n"); return NULL; } while(*main_sec != NULL) { if (!Compare_Sections(*main_sec,*ins_sec,variables)) { if ((!(flags & C_NOT_UNIQUE) && variables == NULL) || (flags & C_OVERWRITE) ) { Ptr = *main_sec; *main_sec = *ins_sec; *ins_sec = NULL; (*main_sec)->next = Ptr->next; Ptr->next = NULL; free_section(Ptr); return *main_sec; } } main_sec = &((*main_sec)->next); } *main_sec = *ins_sec; *ins_sec = NULL; (*main_sec)->next = NULL; return *main_sec; } /****************************************************************************/ static int Compare_Sections(section* sec1, section *sec2, char **variables) { int i, Cnt1, Cnt2; int found1, found2, Cnt, depth, width, exist = 1; char **array; char **array2; section *RetSection = NULL; entry *RetEntry1 = NULL; entry *RetEntry2 = NULL; section *Next1 = NULL; section *Next2 = NULL; if (sec1 == NULL || sec2 == NULL) return -1; if (variables == NULL) { if (!strcmp(sec1->name,sec2->name)) return 0; } else { Next1 = sec1->next; sec1->next = NULL; Next2 = sec2->next; sec2->next = NULL; for (i=0; variables[i] != NULL; i++) { if ((array = String_to_Array(variables[i],C_SLASH)) == NULL) { sec1->next = Next1; sec2->next = Next2; return -1; } found1 = found2 = Cnt = 0; while ((array2 = Compare_Section_Get_Path(array,&width,&depth)) != NULL) { Cnt1 = Cnt2 = 0; while (_Get_Section_From_Path(array2,sec1,&RetSection,&RetEntry1,0) == sec1) { Cnt1++; while (_Get_Section_From_Path(array2,sec2,&RetSection,&RetEntry2,0) == sec2) { Cnt2++; if (RetEntry1 != NULL && RetEntry2 != NULL && !strcmp(RetEntry1->name, RetEntry2->name) && ((RetEntry1->value == NULL && RetEntry2->value == NULL) || !strcmp(RetEntry1->value,RetEntry2->value) ) ) found1++; } } if (exist && array2[depth-1][0] == C_EXIST && Cnt1 == 0 && Cnt2 == 0) found2++; if ((++Cnt)%width == 0) { if(found1 == 0) found2 = 0; else exist = 0; } if (array != NULL) { del_Array(array); array = NULL; } } if (width == found1 + found2) { sec1->next = Next1; sec2->next = Next2; return 0; } } } sec1->next = Next1; sec2->next = Next2; return -1; } /****************************************************************************/ static char** Compare_Section_Get_Path(char **array, int *retsize, int *retdepth) { int i,j; static int lsize; static int index; static char ***arrayptr = NULL; static char **retptr = NULL; static int *indexptr = NULL; if (array != NULL) { for (index=0; array[index] != NULL; index++); if ((indexptr = (int*) calloc(index,sizeof(int))) == NULL) { print_msg("%s","Can't allocate memory!\n"); return NULL; } if ((retptr = (char**) calloc(index+1,sizeof(char*))) == NULL) { print_msg("%s","Can't allocate memory!\n"); return NULL; } if ((arrayptr = (char***) calloc(index,sizeof(char**))) == NULL) { print_msg("%s","Can't allocate memory!\n"); return NULL; } for (i=0; array[i] != NULL; i++) if ((arrayptr[i] = String_to_Array(array[i],C_OR)) == NULL) { print_msg("%s","Can't allocate memory!\n"); return NULL; } for (lsize=0; arrayptr[index-1][lsize] != NULL; lsize++); } *retsize = lsize; *retdepth = index; if (arrayptr == NULL) return NULL; if (arrayptr[0][indexptr[0]] != NULL) { i = index-1; while(i >= 0) { if (i > 0 && arrayptr[i][indexptr[i]] == NULL) { indexptr[i] = 0; i--; } else { for (j = index-1; j >= 0; j--) retptr[j] = arrayptr[j][indexptr[j]]; indexptr[i]++; while (i >= 0) { if (i > 0 && arrayptr[i][indexptr[i]] == NULL) { indexptr[i] = 0; indexptr[i-1]++; } i--; } break; } } } else { for (i=0; i < index; i++) del_Array(arrayptr[i]); free(arrayptr); free(retptr); free(indexptr); arrayptr = NULL; retptr = NULL; indexptr = NULL; } return retptr; } /****************************************************************************/ static int Append_Sections(section **main_sec, section *app_sec) { while(*main_sec != NULL) main_sec = &((*main_sec)->next); *main_sec = app_sec; return 0; } /****************************************************************************/ static int Merge_Sections(section **main_sec, section **ins_sec, char **variables, int flags) { if (main_sec == NULL) { print_msg("%s","Main section is emtpy!\n"); return -1; } if (ins_sec == NULL) { print_msg("%s","Insert section is emtpy!\n"); return -1; } if (*ins_sec == NULL) { print_msg("%s","Insert section element is emtpy!\n"); return -1; } if((*ins_sec)->next != NULL) Merge_Sections(main_sec,&((*ins_sec)->next),variables,flags); Insert_Section(main_sec,ins_sec,variables,flags); if (*ins_sec != NULL) { free_section(*ins_sec); *ins_sec = NULL; } return 0; } /****************************************************************************/ static void free_cfile(cfile **cfiles) { cfile **cptr; if (cfiles != NULL) { cptr = cfiles; while (*cptr != NULL) { if ((*cptr)->name) free((*cptr)->name); free(*cptr); cptr++; } free(cfiles); } return; } /****************************************************************************/ /* Die Variable flags sollte _immer_ auf 'C_OVERWRITE|C_NOT_UNIQUE' gesetzt werden, anderes macht hier zur Zeit keinen Sinn. main_sec darf _NIE_ unintilisiert sein und muss beim ersten mal NULL enthlten!!!! */ int read_files(section **main_sec, char** files, int *fileflag, char **variables, int flags) { int newread = 0; static cfile **cfiles = NULL; static struct stat FileStat; section *ins_sec = NULL; int i; if (files != NULL) { newread = 1; free_cfile(cfiles); cfiles = NULL; for (i=0; files[i] != NULL; i++) { if ((cfiles = (cfile**) realloc(cfiles,sizeof(cfile*)*(i+2))) == NULL) { print_msg("%s","Can't allocate memory!\n"); return -1; } if ((cfiles[i] = (cfile*) calloc(1,sizeof(cfile))) == NULL) { print_msg("%s","Can't allocate memory!\n"); return -1; } cfiles[i+1] = NULL; if (stat(files[i],&FileStat) != 0 && !(flags & C_NO_WARN_FILE)) { print_msg("Can't open file `%s': %s!\n",files[i],strerror(errno)); return -1; } cfiles[i]->flag = fileflag[i]; cfiles[i]->name = strdup(files[i]); cfiles[i]->modtime = FileStat.st_mtime; } } else { if (cfiles == NULL) { print_msg("%s","There is no file!\n"); return -1; } else { for (i=0; cfiles[i] != NULL; i++) { if (stat(cfiles[i]->name,&FileStat) != 0) { if (!(flags & C_NO_WARN_FILE)) { print_msg("Can't open file `%s': %s!\n",cfiles[i]->name,strerror(errno)); return -1; } } else { if (cfiles[i]->modtime != FileStat.st_mtime) { cfiles[i]->modtime = FileStat.st_mtime; newread = 1; break; } } } } } if (newread) { free_section(*main_sec); *main_sec = NULL; for (i=0; cfiles[i] != NULL; i++) { if (*main_sec == NULL) { *main_sec = read_file(NULL,cfiles[i]->name,flags); } else { if ((ins_sec = read_file(NULL,cfiles[i]->name,flags)) != NULL) switch(cfiles[i]->flag) { case APPEND_FILE: Append_Sections(main_sec,ins_sec); break; case MERGE_FILE : default : Merge_Sections(main_sec,&ins_sec,variables,flags); break; } } } } return ((*main_sec != NULL && newread)?1:(*main_sec == NULL?-1:0)); } /****************************************************************************/ int Filter_Sections(section **sec, char** path) { int i; char **array; section *secptr; section *retsec = NULL; entry *retent = NULL; if (path == NULL || path[0] == NULL) return -1; if (sec == NULL) { print_msg("%s","Section is emtpy!\n"); return -1; } for (i=0; path[i] != NULL; i++) { if ((array = String_to_Array(path[i],C_SLASH)) == NULL) return -1; secptr = *sec; while ((secptr = _Get_Section_From_Path(array,secptr,&retsec,&retent,F_TAG)) != NULL); del_Array(array); } return del_untagged_items(sec); } /****************************************************************************/ static int del_untagged_items(section **sec) { int del = 0; entry **ent; entry *Ptr; section *Ptr2; if (*sec == NULL) return -1; while (*sec != NULL) { if ((*sec)->flag != F_TAGGED) { Ptr2 = *sec; *sec = (*sec)->next; Ptr2->next = NULL; free_section(Ptr2); } else { (*sec)->flag = F_NOT_TAGGED; ent = &((*sec)->entries); while(*ent != NULL) { del = 0; if ((*ent)->flag == F_TAGGED && (*ent)->subsection != NULL) { del_untagged_items(&((*ent)->subsection)); if ((*ent)->subsection == NULL) del = 1; } if ((*ent)->flag != F_TAGGED || del == 1) { Ptr = *ent; *ent = (*ent)->next; Ptr->next = NULL; free_entry(Ptr); } else { (*ent)->flag = F_NOT_TAGGED; ent = &((*ent)->next); } } if ((*sec)->entries == NULL) { Ptr2 = *sec; *sec = (*sec)->next; Ptr2->next = NULL; free_section(Ptr2); } else sec = &((*sec)->next); } } return 0; } /****************************************************************************/ static section* Get_Section_From_Path(section* NewSection, char *Path, entry **Entry) { static section *RootSection = NULL; static section *RetSection = NULL; static entry *RetEntry = NULL; static char **array = NULL; if (Path != NULL && NewSection != NULL) { RootSection = NewSection; RetSection = NULL; RetEntry = NULL; if (array != NULL) del_Array(array); if ((array = String_to_Array(Path,C_SLASH)) == NULL) return NULL; if (array[0] == NULL) return NULL; } else if (Path == NULL && NewSection == NULL && (RootSection == NULL || array == NULL) ) return NULL; else if (Path != NULL || NewSection != NULL) return NULL; if ((RootSection = _Get_Section_From_Path(array,RootSection,&RetSection,&RetEntry,0)) == NULL) RetSection = NULL; if (Entry != NULL) *Entry = RetEntry; return RetSection; } /****************************************************************************/ static entry* _Get_Entry_From_Path(char **array, entry* Entry, section **RetSection, entry **RetEntry, int flags) { int index; int found = 0; int found_first = 0; char **array2 = NULL; char *Ptr; if (array != NULL && array[0] == NULL) return NULL; if ((array2 = String_to_Array(array[0],C_OR)) == NULL) return NULL; while(found == 0 && Entry != NULL) { index = 0; if (Entry->name != NULL) { while(array2[index] != NULL && found == 0) { Ptr = (array2[index][0] == C_EXIST?array2[index]+1:array2[index]); if (match(Ptr,Entry->name,F_IGNORE_CASE) == 0) { if (array[1] == NULL) { if (Entry->value != NULL && *RetEntry != Entry && (*RetEntry == NULL || found_first != 0) ) { found = 1; if (flags == F_TAG) Entry->flag = F_TAGGED; *RetEntry = Entry; } else if (*RetEntry == Entry) found_first = 1; } else { if (_Get_Section_From_Path(array+1,Entry->subsection,RetSection,RetEntry,flags) != NULL) { found = 1; if (flags == F_TAG) Entry->flag = F_TAGGED; if (array[2] == NULL) *RetEntry = Entry; } } } index++; } } if (found == 0) Entry = Entry->next; } if (found == 0 && found_first != 0) *RetEntry = NULL; del_Array(array2); return Entry; } /****************************************************************************/ static section* _Get_Section_From_Path(char **array, section* Section, section **RetSection, entry **RetEntry, int flags) { int index; int found = 0; int found_first = 0; char **array2 = NULL; char *Ptr; if (array != NULL && array[0] == NULL) return NULL; if ((array2 = String_to_Array(array[0],C_OR)) == NULL) return NULL; while(found == 0 && Section != NULL) { index = 0; if (Section->name != NULL) { while(array2[index] != NULL && found == 0) { Ptr = (array2[index][0] == C_EXIST?array2[index]+1:array2[index]); if (match(Ptr,Section->name,F_IGNORE_CASE) == 0) { if (array[1] == NULL) { if (*RetSection != Section && (*RetSection == NULL || found_first != 0)) { found = 1; if (flags == F_TAG) Section->flag = F_TAGGED; *RetSection = Section; } else if (*RetSection == Section) found_first = 1; } else { if (_Get_Entry_From_Path(array+1,Section->entries,RetSection,RetEntry,flags) != NULL) { found = 1; if (flags == F_TAG) Section->flag = F_TAGGED; if (array[2] == NULL) *RetSection = Section; } } } index++; } } if (found == 0) Section = Section->next; } if (found == 0 && found_first != 0) *RetSection = NULL; del_Array(array2); return Section; } /****************************************************************************/ section* Get_Section_Match(section* Section, char *Path, char* Value, int (*_match)(char*, char*), entry **RetEntry) { entry *Entry; while ((Section = Get_Section_From_Path(Section,Path,&Entry)) != NULL) { if (RetEntry != NULL) *RetEntry = NULL; if (Entry->subsection != NULL) { if (Value == NULL) { if (RetEntry != NULL) *RetEntry = Entry; return Entry->subsection; } /* Die naechsten Zeilen sind fuer Syntax-DAU's auskommentiert: NUMBER={ [blabla] } fuehrt zum Abbruch! else return NULL; */ } else { if (Value == NULL) return NULL; else { if ((_match == NULL && !strcmp(Entry->value,Value)) || !_match(Entry->value,Value) ) { if (RetEntry != NULL) *RetEntry = Entry; return Section; } } } Section = NULL; Path = NULL; } return NULL; } /****************************************************************************/ char *Get_Value(section *Section, char *Path) { entry *Entry; while ((Section = Get_Section_From_Path(Section,Path,&Entry)) != NULL) { if (Entry->value != NULL) return Entry->value; Section = NULL; Path = NULL; } return NULL; } /****************************************************************************/ static int Set_Ret_Code(char *Value, int Type, void **Pointer) { int RetCode = -1; if (Pointer == NULL || Value == NULL) return -1; switch (Type) { case R_TYPE_LONG : case R_TYPE_INT : if (is_integer(Value,(long int*) Pointer)) RetCode = 0; else *((long int*)Pointer) = 0; break; case R_TYPE_DOUBLE: if (is_double(Value,(double*) Pointer)) RetCode = 0; else *((double*)Pointer) = 0.0; break; case R_TYPE_CHAR : *((char*)Pointer) = Value[0]; if (strlen(Value) == 1) RetCode = 0; break; case R_TYPE_STRING: *((char**)Pointer) = Value; RetCode = strlen(Value); break; default : break; } return RetCode; } /****************************************************************************/ int _Get_Type_Value(section *Section, char *Path, int Type, void **Pointer) { register int RetCode = -1; auto char *Ptr; while (RetCode == -1 && (Ptr = Get_Value(Section,Path)) != NULL) { RetCode = Set_Ret_Code(Ptr,Type,Pointer); Section = NULL; } return RetCode; } /****************************************************************************/ int _Get_Type_Match(section *Section, char *Path, char* Pattern, int (*_match)(char*, char*), int Type, void **Pointer) { entry *Entry; if (Get_Section_Match(Section,Path,Pattern,_match,&Entry) == NULL || Entry != NULL || Entry->name == NULL ) return -1; return Set_Ret_Code(Entry->name,Type,Pointer); } /****************************************************************************/ static char* Delete_Chars(char *String, char *Quote) { char *Ptr = String; if (Ptr == NULL) return NULL; while ((Ptr = Strpbrk(Ptr,Quote)) != NULL) { print_msg("Invalid character (`%s') in string `%s'. Character ignored!\n",Quote,String); do *Ptr = *(Ptr + 1); while(*Ptr++ != '\0'); } return String; } /****************************************************************************/ int Replace_Variables(section *Section) { entry *Entry; char *Ptr = NULL; while(Section != NULL) { Entry = Section->entries; while(Entry != NULL) { if (Entry->value != NULL) { if ((Ptr = Replace_Variable(Entry->value)) != NULL) { if ((Ptr = strdup(Ptr)) == NULL) { print_msg("%s","Can't allocate memory!\n"); return -1; } free(Entry->value); Entry->value = Ptr; } } else if (Entry->subsection != NULL) if (Replace_Variables(Entry->subsection) != 0) return -1; Entry = Entry->next; } Section = Section->next; } return 0; } /****************************************************************************/