isdn4k-utils/lib/conffile.c

1598 lines
34 KiB
C

/* $Id: conffile.c,v 1.16 1997/05/25 19:41:23 luethje 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.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 <roderich@syntec.m.EUnet.de>
* 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#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[BUFSIZ];
char *Sectionname, *Variable, *Value;
int Res;
int InInclude = 0;
section *Ptr = Section;
if (Section != NULL)
InInclude = 1;
while (FGets(String, BUFSIZ, 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;
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);
free(Ptr->name);
free(Ptr->value);
free(Ptr);
}
/****************************************************************************/
void free_section(section *Ptr)
{
if (Ptr == NULL)
return;
free_section(Ptr->next);
free_entry(Ptr->entries);
free(Ptr->name);
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 not allocate memory!\n");
return NULL;
}
if ((retptr = (char**) calloc(index+1,sizeof(char*))) == NULL)
{
print_msg("%s","Can not allocate memory!\n");
return NULL;
}
if ((arrayptr = (char***) calloc(index,sizeof(char**))) == NULL)
{
print_msg("%s","Can not 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 not 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)
{
free((*cptr)->name);
free(*cptr);
cptr++;
}
free(cfiles);
cfiles = NULL;
}
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 not allocate memory!\n");
return -1;
}
if ((cfiles[i] = (cfile*) calloc(1,sizeof(cfile))) == NULL)
{
print_msg("%s","Can not allocate memory!\n");
return -1;
}
cfiles[i+1] = NULL;
if (stat(files[i],&FileStat) != 0 && !(flags & C_NO_WARN_FILE))
{
print_msg("Can not 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 not 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 not 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;
}
/****************************************************************************/