1598 lines
34 KiB
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;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|