diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 00000000..a3d53cbe --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,91 @@ +## +## Makefile for library for isdn4linux +## + +## +## 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. + +ifndef ROOTDIR +export ROOTDIR=$(shell pwd) +PREFIXDIR =. +else +PREFIXDIR =$(ROOTDIR) +endif + +###################################################################### +# USER CONFIGURATION AREA +###################################################################### + +ifndef _CC +export _CC = gcc -Wall -pipe -O6 +endif +CC = $(_CC) + +export AVON = avon + +###################################################################### +# DON'T EDIT BELOW THIS LINE +###################################################################### + +ifdef LIBAREA +LIBDIR = areacode +LIB_AREA = $(LIBDIR)/areacode.o +CFLAGS += -DLIBAREA +else +LIBDIR = avon +LIB_AREA = $(LIBDIR)/createDB.o +CFLAGS += -DAVON=\"$(AVON)\" +endif + +SUBDIRS = $(LIBDIR) + +CFLAGS += -I$(PREFIXDIR) + +all: libs libisdn.a + +libs: + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done + +depend dep: .depend + +.depend: + $(CPP) -M $(CFLAGS) *.c >.depend + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i depend; done + +clean: + -rm -f *.o *.a + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i clean; done + +distclean: clean + -rm -f .depend + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i distclean; done + +install: depend all + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i depend; done + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i all; done + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i install; done + +deinstall: distclean + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i deinstall; done + + +libisdn.a: conffile.o isdntools.o libtools.o $(LIB_AREA) + ar rs libisdn.a isdntools.o conffile.o libtools.o $(LIB_AREA) + +ifeq (.depend,$(wildcard .depend)) +include .depend +#HEADERS := $(HEADERS) .depend +endif + diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 00000000..32473bc7 --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,68 @@ +# +# This Makefile is used for compatibility to the +# isdn4k-utils package. In order to superseede +# the original Makefile, it is called GNUmakefile. +# + +ifeq (../.config,$(wildcard ../.config)) + include ../.config + BUILDOPTS := + ifeq ($(CONFIG_LIB_AREACODE),y) + BUILDOPTS += SUBDIRS= LIBAREA=1 + endif + # + # Install as root with numeric Id's, since these are the + # only ones that _really_ exist on _every_ system. + # + INSTALLOPTS += INSTALL= install -o 0 -g 0 -m 644 +endif + +all: .depend + $(MAKE) -f Makefile $(BUILDOPTS) all + +.depend: + $(MAKE) -f Makefile depend + +config: + @cp Makefile.in GNUmakefile + @rm -f areacode; ln -s ../areacode . + @echo '/*' > policy.h + @echo ' * Automatically generated by config: DO NOT EDIT' >> policy.h + @echo ' */' >> policy.h + @echo '#ifndef _POLICY_H_' >> policy.h + @echo '#define _POLICY_H_' >> policy.h + @echo '#include "../scripts/autoconf.h"' >> policy.h + @echo '#define I4LCONFDIR CONFIG_I4LCONFDIR' >> policy.h + @echo '#define CONFFILE CONFIG_CONFFILE' >> policy.h + @echo '#define USERCONFFILE CONFIG_USERCONFFILE' >> policy.h + @echo '#define RUNDIR CONFIG_RUNDIR' >> policy.h + @echo '#define S_COUNTRY_PRFIX CONFIG_COUNTRY_PREFIX' >> policy.h + @echo '#define S_AREA_PREFIX CONFIG_AREA_PREFIX' >> policy.h + @echo '#endif' >> policy.h + +clean: + $(MAKE) -f Makefile clean + +distclean: + $(MAKE) -f Makefile distclean + rm -f GNUmakefile policy.h areacode + +# +# Currently isdnlib.a is used in place. +# When using avon, I4LCONFDIR points to avon data. +# +# TODO: build a shared version and install it. +# +install-avon: + $(MAKE) -f Makefile I4LCONFDIR=$(LIB_AVON_DATA) install + +uninstall-avon: + $(MAKE) -f Makefile I4LCONFDIR=$(LIB_AVON_DATA) deinstall + +ifeq ($(CONFIG_LIB_AREACODE),y) +install: +uninstall: +else +install: install-avon +uninstall: uninstall-avon +endif diff --git a/lib/conffile.c b/lib/conffile.c new file mode 100644 index 00000000..2687a02f --- /dev/null +++ b/lib/conffile.c @@ -0,0 +1,1326 @@ +/* + * 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. + * + */ + +#define _CONFFILE_C_ + +#include +#include +#include +#include +#include +#include +#include + +#include "conffile.h" + +/****************************************************************************/ + +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 Find_Include(section **Section, char* String, int Flags); +static section* _Get_Section_From_Path(char **array, section* Section, section **RetSection, entry **RetEntry); +static entry* _Get_Entry_From_Path(char **array, entry* Entry, section **RetSection, entry **RetEntry); +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); + +/****************************************************************************/ + +void set_print_fkt_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 NULL; +} + +/****************************************************************************/ + +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; + 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) +{ + char String[BUFSIZ]; + char *Sectionname, *Variable, *Value; + int Res; + section *Ptr = Section; + + + 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,Flags) == 0) + { + 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) + { + 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) + return Section; + else + if (Res == -1) + print_msg("Error in file `%s', line %d: there is no valid token!\n",FileName,*Line); + } + + 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, int Flags) +{ + section *Ptr = NULL; + char Help1[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 ) + { + Help1[strlen(Help1)-1] = '\0'; + if ((Ptr = read_file(*Section,Help1+strlen(S_KEY_INCLUDE)+1,Flags)) == NULL) + return -1; + else + *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 && strcmp(Entry->name,Variable)) + Entry = Entry->next; + + return Entry; +} + +/****************************************************************************/ + +section* Get_Section(section* Section, char *Sectionname) +{ + while (Section != NULL && strcmp(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 (((*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 ((*ins_sec)->next != NULL) + { + print_msg("%s","Can only insert one entry at time!\n"); + return NULL; + } + + if (main_sec == NULL) + { + print_msg("%s","Main section is emtpy!\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; + entry *Entry1 = NULL; + entry *Entry2 = NULL; + + + if (sec1 == NULL || sec2 == NULL) + return -1; + + if (variables == NULL) + { + if (!strcmp(sec1->name,sec2->name)) + return 0; + } + else + { + for (i=0; variables[i] != NULL && variables[i][0] != NULL && variables[i][1] != NULL; i++) + { + if (!strcmp(sec1->name,sec2->name) && + !strcmp(sec1->name,variables[i][0]) && + (Entry1 = Get_Entry(sec1->entries,variables[i][1])) != NULL && + Entry1->value != NULL && + (Entry2 = Get_Entry(sec2->entries,variables[i][1])) != NULL && + Entry2->value != NULL && !strcmp(Entry1->value,Entry2->value) ) + return 0; + } + } + + return -1; +} + +/****************************************************************************/ + +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; +} + +/****************************************************************************/ + +/* filenum gibt an, aus wievielen Dateien gelesen werden soll. Die Dateinamen + sind dann in files zu finden. Wenn filnum == -1, dann muss der letzte Eintrag + von files[x] == NULL sein. + variable wird benoetigt, um eine Section eindeutig zu identifizieren zu + koennen. Da viele Sections in der Regel den gleichen Namen verwenden + (z. B. [NUMBER], [MSN]), muessen die einzelnen Eintraege ja eindeutig + erkannt werden koennen, wie es ein Key bei einer Datenbank kann. Dieses + kann dann ueber die Eintraege gemacht werden koennen (z.B. NUMBER=0815). + Wenn man in variables nun z.B. "NUMBER" uebergibt, wird sichergestellt, + das nur einmal ein Eintrag NUMBER=1234 unter allen Sectionen [NUMBER] + existiert. Dieses wird benoetigt, wenn es mehrere Config-Dateien gibt, die + durchsucht/eingelesen werden muessen. Z.B. /etc/isdn/isdn.conf, ~/.isdn. + In dieser Reihenfolge sollte auch die Variable files belegt sein (von + globalen runter zu lokalen Configdateien. + 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!!!! +*/ + +section *read_files(section **main_sec, char** files, 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 NULL; + } + + if ((cfiles[i] = (cfile*) calloc(1,sizeof(cfile))) == NULL) + { + print_msg("%s","Can not allocate memory!\n"); + return NULL; + } + + 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 NULL; + } + + 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 NULL; + } + 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 NULL; + } + } + 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) + Merge_Sections(main_sec,&ins_sec,variables,flags); + } + } + } + + return *main_sec; +} + +/****************************************************************************/ + +#if 0 +/* Filtert aus den gesamten Sectionen die heraus, die in secnames + enthalten sind. Wenn also nur die Sectionen [MSN] und [NUMBER] benoetigt + werden, dann werden diese hier uebergeben("MSN","NUMBER"), und secnum + auf 2 gesetzt. secnum hat die gleich Bedeutung wie filenum in + read_files(). +*/ + +int Filter_Sections(section **sec, char** secnames) +{ + int i; + int del; + section *Ptr; + + + if (sec == NULL) + { + print_msg("%s","Section is emtpy!\n"); + return -1; + } + + while(*sec != NULL) + { + del = 1; + + for (i=0; secnames[i] != NULL && *sec != NULL; i++) + { + if (!strcmp(secnames[i],(*sec)->name)) + del = 0; + } + + if (del == 1) + { + Ptr = *sec; + *sec = (*sec)->next; + Ptr->next = NULL; + free_section(Ptr); + } + + if (*sec != NULL && del == 0) + sec = &((*sec)->next); + } + + return 0; +} +#endif + +/****************************************************************************/ + +#if 0 /* AK:24-Feb-97 */ +int Filter_Sections(section **sec, char** path) +{ + int j,i = 0; + int del; + section *Ptr; + section *retsec; + entry *retent; + char **array; + char **array2; + + + if (path == NULL || path[0] == NULL) + return -1; + + if (sec == NULL) + { + print_msg("%s","Section is emtpy!\n"); + return -1; + } + + while(*sec != NULL) + { + del = 1; + + for (i=0; path[i] != NULL && *sec != NULL && del == 1; i++) + { + if (_Get_Section_From_Path(sec,path[i],&retsec,&retent) == sec) + { + if ((array = String_to_Array(path,C_SLASH)) == NULL) + return NULL; + + j=0; + while(array[j] != NULL); + + del_Array(array); + + del = 0; + } + } + + if (del == 1) + { + Ptr = *sec; + *sec = (*sec)->next; + Ptr->next = NULL; + free_section(Ptr); + } + + if (*sec != NULL && del == 0) + sec = &((*sec)->next); + } + + return 0; +} +#endif + +/****************************************************************************/ + +/* Nur die erlaubten Entries sind in entnames enthalten */ +/* Filter aus _allen_ Sections die Eintraege heraus, die in entnames + enthalten sind. So kann man in alles Sections z.B. nur die Entries + NUMBER=blabla und ALIAS=blabla behalten ("NUMBER","ALIAS") + uebergeben. entnum hat die gleiche Bedeutung wie filenum in + read_files(). +*/ + +int Filter_Entries(section **sec, char ** entnames) +{ + int i; + int del; + entry **ent; + entry *Ptr; + section *Ptr2; + + if (*sec == NULL) + return -1; + + while (*sec != NULL) + { + ent = &((*sec)->entries); + + while(*ent != NULL) + { + del = 1; + + for (i=0; entnames[i] != NULL && *ent != NULL; i++) + { + if ((*ent)->name != NULL && !strcmp(entnames[i],(*ent)->name)) + del = 0; + } + + if (del == 1) + { + Ptr = *ent; + *ent = (*ent)->next; + Ptr->next = NULL; + free_entry(Ptr); + } + + if (*ent != NULL && del == 0) + 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)) == 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 index; + int found = 0; + int found_first = 0; + char **array2 = NULL; + + + if (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) + { + if (match(array2[index],Entry->name,F_IGNORE_CASE) == 0) + { + if (array[1] == NULL) + { + if (Entry->value != NULL && *RetEntry != Entry && + (*RetEntry == NULL || found_first != 0) ) + { + found = 1; + *RetEntry = Entry; + } + else + if (*RetEntry == Entry) + found_first = 1; + } + else + { + if (_Get_Section_From_Path(array+1,Entry->subsection,RetSection,RetEntry) != NULL) + { + found = 1; + + 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 index; + int found = 0; + int found_first = 0; + char **array2 = NULL; + + + if (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) + { + if (match(array2[index],Section->name,F_IGNORE_CASE) == 0) + { + if (array[1] == NULL) + { + if (*RetSection != Section && (*RetSection == NULL || found_first != 0)) + { + found = 1; + *RetSection = Section; + } + else + if (*RetSection == Section) + found_first = 1; + } + else + { + if (_Get_Entry_From_Path(array+1,Section->entries,RetSection,RetEntry) != NULL) + { + found = 1; + + 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 = Entry; + + if (Entry->subsection != NULL) + { + if (Value == NULL) + 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) ) + 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); + + 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; +} + +/****************************************************************************/ + diff --git a/lib/conffile.h b/lib/conffile.h new file mode 100644 index 00000000..eb7e7f7b --- /dev/null +++ b/lib/conffile.h @@ -0,0 +1,126 @@ + +/* $Id: conffile.h,v 1.1 1997/03/03 04:23:14 fritz Exp $ + * + * ISDN accounting for isdn4linux. + * + * Copyright 1995, 1996 by Andreas Kool (akool@Kool.f.EUnet.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. + * + */ + +#ifndef _CONFFILE_H_ +#define _CONFFILE_H_ + +/****************************************************************************/ + +#include "libtools.h" + +/****************************************************************************/ + +#define C_OVERWRITE 1 +#define C_WARN 2 +#define C_NOT_UNIQUE 4 +#define C_APPEND 8 +#define C_NO_WARN_FILE 16 + +/****************************************************************************/ + +#define C_EQUAL '=' +#define C_BEGIN_SECTION '[' +#define C_END_SECTION ']' +#define C_BEGIN_SUBSECTION '{' +#define C_END_SUBSECTION '}' +#define C_BEGIN_INCLUDE '(' +#define C_END_INCLUDE ')' + +#define S_KEY_INCLUDE "INCLUDE" + +/****************************************************************************/ + +#define S_ALL_QUOTE "*?|&/" + +/****************************************************************************/ + +#define C_OR '|' +#define C_AND '&' + +/****************************************************************************/ + +#define R_TYPE_INT 0 +#define R_TYPE_LONG 1 +#define R_TYPE_DOUBLE 2 +#define R_TYPE_CHAR 3 +#define R_TYPE_STRING 4 + +/****************************************************************************/ + +#define Get_Type_Match(a,b,c,d,e,f) _Get_Type_Match(a,b,c,d,e,(void**)f) +#define Get_Type_Value(a,b,c,d) _Get_Type_Value(a,b,c,(void**)d) + +/****************************************************************************/ + +struct _section; + +typedef struct _entry { + char *name; + char *value; + struct _section *subsection; + struct _entry *next; +} entry; + +typedef struct _section { + char *name; + entry *entries; + struct _section *next; +} section; + +typedef struct _cfiles { + char* name; + int modtime; +} cfile; + +/****************************************************************************/ + +#ifdef _BASE_CONFFILE_C_ +# define _EXTERN +#else +# define _EXTERN extern +#endif + +_EXTERN section *read_file(section *Section, const char *FileName, int Flags); +_EXTERN section *write_file(section *Section, const char *FileName, char *Program, char* Version); +_EXTERN section* Get_SubSection(section* Section, char *Variable); +_EXTERN section* Get_Section(section* Section, char *Sectionname); +_EXTERN entry* Get_Entry(entry* Entry, char *Variable); +_EXTERN entry *Set_Entry(section *Section, char *Sectionname, char *Variable, char *Value, int Flag); +_EXTERN section *Set_Section(section **Section, char *Sectionname, int Flag); +_EXTERN section *Del_Section(section **Section, char *Sectionname); +_EXTERN section *Set_SubSection(section *Section, char *Variable, section *SubSection, int Flag); +_EXTERN void set_print_fkt_for_conffile(int (*new_print_msg)(const char *, ...)); +_EXTERN void free_section(section *Ptr); +_EXTERN section *read_files(section **main_sec, char** files, char ***variables, int flags); +_EXTERN int Filter_Sections(section **sec, char** secnames); +_EXTERN int Filter_Entries(section **sec, char ** entnames); +_EXTERN section* Get_Section_Match(section* Section, char *Path, char* Value, int (*_match)(char*, char*), entry **RetEntry); +_EXTERN char *Get_Value(section *Section, char *Path); +_EXTERN int _Get_Type_Match(section *Section, char *Path, char* Pattern, int (*_match)(char*, char*), int Type, void **Pointer); +_EXTERN int _Get_Type_Value(section *Section, char *Path, int Type, void **Pointer); + +#undef _EXTERN + +/****************************************************************************/ + +#endif /* _CONFFILE_H_ */ diff --git a/lib/isdntools.c b/lib/isdntools.c new file mode 100644 index 00000000..72f1d8eb --- /dev/null +++ b/lib/isdntools.c @@ -0,0 +1,621 @@ +/* $Id: isdntools.c,v 1.1 1997/03/03 04:23:15 fritz Exp $ + * + * ISDN accounting for isdn4linux. (Utilities) + * + * Copyright 1995, 1997 by Andreas Kool (akool@Kool.f.EUnet.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: isdntools.c,v $ + * Revision 1.1 1997/03/03 04:23:15 fritz + * Added files in lib + * + * Revision 2.6.26 1997/01/19 22:23:43 akool + * Weitere well-known number's hinzugefuegt + * + * Revision 2.6.24 1997/01/15 19:13:43 akool + * neue AreaCode Lib 0.99 integriert + * + * Revision 2.6.20 1997/01/05 20:06:43 akool + * atom() erkennt nun "non isdnlog" "/tmp/isdnctrl0" Output's + * + * Revision 2.6.19 1997/01/05 19:39:43 akool + * AREACODE Support added + * + * Revision 2.40 1996/06/16 10:06:43 akool + * double2byte(), time2str() added + * + * Revision 2.3.26 1996/05/05 12:09:16 akool + * known.interface added + * + * Revision 2.3.15 1996/04/22 21:10:16 akool + * + * Revision 2.3.4 1996/04/05 11:12:16 sl + * confdir() + * + * Revision 2.2.5 1996/03/25 19:41:16 akool + * 1TR6 causes implemented + * + * Revision 2.23 1996/03/14 20:29:16 akool + * Neue Routine i2a() + * + * Revision 2.17 1996/02/25 19:14:16 akool + * Soft-Error in atom() abgefangen + * + * Revision 2.06 1996/02/07 18:49:16 akool + * AVON-Handling implementiert + * + * Revision 2.01 1996/01/20 12:11:16 akool + * Um Einlesen der neuen isdnlog.conf Felder erweitert + * discardconfig() implementiert + * + * Revision 2.00 1996/01/10 20:11:16 akool + * + */ + +/****************************************************************************/ + + +#define PUBLIC /**/ +#define _ISDNTOOLS_C_ + +/****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libisdn.h" + +/****************************************************************************/ + +static int (*print_msg)(const char *, ...) = printf; +static char *_get_areacode(char *code, int *Len, int flag); + +/****************************************************************************/ + +static char areacodes[][2][30] = { + {"+49130", "Toll-free"}, + {"+491802", "Service 180-2 (0,12/Anruf)"}, + {"+491803", "Service 180-3 (DM 0,24/Anruf)"}, + {"+491805", "Service 180-5 (DM 0,48/Anruf)"}, + {"+491901", "Service 190 (DM 1,20/Minute)"}, + {"+491902", "Service 190 (DM 1,20/Minute)"}, + {"+491903", "Service 190 (DM 1,20/Minute)"}, + {"+491904", "Service 190 (DM 0,80/Minute)"}, + {"+491905", "Service 190 (DM 1,20/Minute)"}, + {"+491906", "Service 190 (DM 0,80/Minute)"}, + {"+491907", "Service 190 (DM 2,40/Minute)"}, + {"+491908", "Service 190 (DM 3,60/Minute)"}, + {"+491909", "Service 190 (DM 2,40/Minute)"}, + {"+49161", "Mobilfunknetz C"}, + {"+49171", "Mobilfunknetz D1"}, + {"+49172", "Mobilfunknetz D2"}, + {"+49177", "Mobilfunknetz E-Plus"}, + {"+491188", "Auskunft Inland"}, + {"+491910", "T-Online"}, + {"", ""}, +}; + +static char countrycodes[][2][30] = { + {"+30", "Greek"}, + {"+31", "Nethland"}, + {"+32", "Belgium"}, + {"+33", "France"}, + {"+34", "Spain"}, + {"+39", "Italy"}, + {"+41", "Swiss"}, + {"+43", "Austria"}, + {"+44", "Great Britain"}, + {"+45", "Danmark"}, + {"+46", "Sweden"}, + {"+47", "Norway"}, + {"+49", "Germany"}, + {"+352", "Luxembourg"}, + {"+1", "United States"}, + {"", ""}, +}; + +char *avonlib; + +/****************************************************************************/ + +void set_print_fkt_for_lib(int (*new_print_msg)(const char *, ...)) +{ + print_msg = new_print_msg; + set_print_fkt_for_conffile(new_print_msg); + set_print_fkt_for_libtools(new_print_msg); +#ifndef LIBAREA + set_print_fkt_for_avon(new_print_msg); +#endif +} + +/****************************************************************************/ + +int num_match(char* Pattern, char *number) +{ + int RetCode = -1; + char **Ptr; + char **Array; + + if (!strcmp(Pattern, number)) + RetCode = 0; + else + if (strchr(Pattern,C_NUM_DELIM)) + { + Ptr = Array = String_to_Array(Pattern,C_NUM_DELIM); + + while (*Ptr != NULL && RetCode != 0) + { + RetCode = match(expand_number(*Ptr), number, 0); + Ptr++; + } + + del_Array(Array); + } + else + RetCode = match(expand_number(Pattern), number, 0); + + return RetCode; +} + +/****************************************************************************/ + +char *expand_number(char *s) +{ + char *Ptr; + int Index; + char Help[SHORT_STRING_SIZE]; + static char Num[SHORT_STRING_SIZE]; + + + Help[0] = '\0'; + Ptr = s; + + if (Ptr == NULL || Ptr[0] == '\0') + return ""; + + while(isblank(*Ptr)) + Ptr++; + + if (*Ptr == '+') + { + strcpy(Help,S_COUNTRY_PREFIX); + Ptr++; + } + + while(*Ptr != '\0') + { + switch (*Ptr) + { + case '\t': + case ' ': + case '-': + case '/': + break; + default : Index = strlen(Help); + Help[Index] = *Ptr; + Help[Index+1] = '\0'; + break; + } + + Ptr++; + } + + if (Help[0] == '*' || !strncmp(Help,S_COUNTRY_PREFIX,strlen(S_COUNTRY_PREFIX))) + { + strcpy(Num,Help); + } + else + if (!strncmp(Help,S_AREA_PREFIX,strlen(S_AREA_PREFIX))) + { + strcpy(Num,mycountry); + strcat(Num,Help+strlen(S_AREA_PREFIX)); + } + else + { + strcpy(Num,mycountry); + strcat(Num,myarea/*+strlen(S_AREA_PREFIX)*/); + strcat(Num,Help); + } + + return Num; +} + +/****************************************************************************/ + +char *expand_file(char *s) +{ + char *Ptr; + uid_t id = -1; + char Help[PATH_MAX]; + static char file[PATH_MAX]; + struct passwd *password; + + + Help[0] = '\0'; + file[0] = '\0'; + + if (s == NULL) + return NULL; + + if (s[0] == '~') + { + if (s[1] == C_SLASH) + { + /* Ghandi, vielleicht kommt hier auch getuid() hin */ + id = geteuid(); + } + else + { + strcpy(Help,s+1); + if ((Ptr = strchr(Help,C_SLASH)) != NULL) + *Ptr = '\0'; + else + return NULL; + } + + setpwent(); + while((password = getpwent()) != NULL && + strcmp(password->pw_name,Help) && + password->pw_uid != id ); + + if (password == NULL) + return NULL; + + strcpy(file,password->pw_dir); + strcat(file,strchr(s,C_SLASH)); + } + + return file; +} + +/****************************************************************************/ + +char *confdir(void) +{ + static char *confdirvar = NULL; + + if (confdirvar == NULL && (confdirvar = getenv(CONFDIR_VAR)) == NULL) + confdirvar = I4LCONFDIR; + + return(confdirvar); +} /* confdir */ + +/****************************************************************************/ + +int delete_runfile(const char *progname) +{ + char *Ptr = NULL; + char runfile[PATH_MAX]; + + if (progname != NULL) + return -1; + + Ptr = strrchr(progname,C_SLASH); + sprintf(runfile,"%s%c%s.pid",RUNDIR,C_SLASH,Ptr?Ptr+1:progname); + + return unlink(runfile); +} /* delete_runfile */ + +/****************************************************************************/ + +int create_runfile(const char *progname) +{ + char *Ptr = NULL; + char runfile[PATH_MAX]; + char string[SHORT_STRING_SIZE]; + int RetCode = -1; + FILE *fp; + + if (progname == NULL) + return -1; + + Ptr = strrchr(progname,C_SLASH); + sprintf(runfile,"%s%c%s.pid",RUNDIR,C_SLASH,Ptr?Ptr+1:progname); + + if (access(runfile,W_OK) != 0 && errno == ENOENT) + { + if ((fp = fopen(runfile, "w")) == NULL) + return -1; + + fprintf(fp, "%d\n", (int)getpid()); + fclose(fp); + chmod(runfile, 0644); + + RetCode = 0; + } + else + { + if ((fp = fopen(runfile, "r")) == NULL) + return -1; + + if (fgets(string,SHORT_STRING_SIZE,fp) != NULL) + RetCode = atoi(string); + else + /* Datei ist leer. */ + RetCode = -1; + + if ( RetCode == -1 || (int)getpid() == RetCode || + ((int) getpid() != RetCode && kill(RetCode,0) != 0 && errno == ESRCH) ) + /* Wenn der alte Prozess nicht mehr existiert! */ + { + + fclose(fp); + if (unlink(runfile)) + return -1; + + return create_runfile(progname); + } + + fclose(fp); + } + + return RetCode; +} /* create_runfile */ + +/****************************************************************************/ + +/* Setzt die Laendercodes, die fuer die Lib gebraucht werden. Diese Funktion + muss von jedem Programm aufgerufen werden!!! +*/ + +#define _MAX_VARS 3 + +int Set_Codes(section* Section) +{ + static char *ptr[_MAX_VARS] = {NULL,NULL,NULL}; + int i; + int RetCode = 0; + entry *Entry; + char *ptr2; + char s[SHORT_STRING_SIZE]; + + for (i=0; i < _MAX_VARS; i++) + if (ptr[i] != NULL) + free(ptr[i]); + + if ((Section = Get_Section(Section,CONF_SEC_GLOBAL)) == NULL) + return -1; + +#ifdef LIBAREA + if ((Entry = Get_Entry(Section->entries,CONF_ENT_AREALIB)) != NULL && + Entry->value != NULL ) + ptr[0] = acFileName = strdup(Entry->value); +#else + if ((Entry = Get_Entry(Section->entries,CONF_ENT_AVONLIB)) != NULL && + Entry->value != NULL ) + ptr[0] = avonlib = strdup(Entry->value); + else + { + sprintf(s, "%s%c%s", CONFIG_AVON_DATA, C_SLASH, AVON); + ptr[0] = avonlib = strdup(s); + } +#endif + + if ((Entry = Get_Entry(Section->entries,CONF_ENT_AREA)) != NULL && + Entry->value != NULL ) + { + ptr2 = Entry->value; + + if (strncmp(Entry->value,S_AREA_PREFIX,strlen(S_AREA_PREFIX))) + ptr[1] = myarea = strdup(ptr2); + else + ptr[1] = myarea = strdup(ptr2+strlen(S_AREA_PREFIX)); + + if (ptr[1] != NULL) + RetCode++; + } + + if ((Entry = Get_Entry(Section->entries,CONF_ENT_COUNTRY)) != NULL && + Entry->value != NULL ) + { + ptr2 = Entry->value; + + if (strncmp(Entry->value,S_COUNTRY_PREFIX,strlen(S_COUNTRY_PREFIX))) + { + sprintf(s,"%s%s",S_COUNTRY_PREFIX, + Entry->value[0]=='+'?(Entry->value)+1:Entry->value); + ptr2 = s; + } + + if ((ptr[2] = mycountry = strdup(ptr2)) != NULL) + RetCode++; + } + + return (RetCode==2?0:-1); +} + +/****************************************************************************/ + +char *get_areacode(char *code, int *Len, int flag) +{ + auto char *Ptr; + auto int i = 0; + register int prefix = strlen(S_COUNTRY_PREFIX); + + + if (Len != NULL) + *Len = -1; + + if (code == NULL || code[0] =='\0') + return NULL; + + if (!(flag & C_NO_EXPAND)) + { + char *ptr = expand_number(code); + + if ((code = alloca(strlen(ptr))) == NULL) + print_msg("Can not allocate memory!\n"); + + strcpy(code,ptr); + } + + while (areacodes[i][0][0] != '\0') + { + if (!memcmp(areacodes[i][0]+1,code+prefix,strlen(areacodes[i][0]+1))) + { + if (Len != NULL) + *Len = strlen(areacodes[i][0]) - 1 /* das "+" */ + prefix; + + return areacodes[i][1]; + } + + i++; + } + + if ((Ptr = _get_areacode(code,Len,flag)) != NULL) + return Ptr; + + i=0; + + while (countrycodes[i][0][0] != '\0') + { + if (!memcmp(countrycodes[i][0]+1,code+prefix,strlen(countrycodes[i][0]+1))) + { + if (Len != NULL) + *Len = strlen(countrycodes[i][0]) - 1 /* das "+" */ + prefix; + + return countrycodes[i][1]; + } + + i++; + } + + if (!(flag & C_NO_WARN)) + print_msg("Unknown areacode `%s'!\n", code); + + return NULL; +} + +/****************************************************************************/ + +#ifndef LIBAREA +static char *_get_areacode(char *code, int *Len, int flag) +{ + static int opened = 0; + static char s[BUFSIZ]; + int prefix = strlen(S_COUNTRY_PREFIX); + int ll=0; + int l; + + + l = strlen(code) - prefix; + + s[0] = '\0'; + + if (Len != NULL) + *Len = -1; + + if (!opened) + { + auto char s[BUFSIZ]; + + + if (avonlib == NULL && !(flag & C_NO_ERROR)) + print_msg("No path for AVON library defined!\n"); + + if (!access(avonlib, R_OK)) + { + if (createDB(avonlib, 0) && !openDB(avonlib)) + readAVON(avonlib); + else + (void)openDB(avonlib); + } + + opened = 1; + + if (dbm == NULL && !(flag & C_NO_ERROR)) + print_msg("!!! Problem with AVON database! - disabling AVON support!\n"); + } + + if (dbm != NULL && l > 3) + { + key.dptr = code+prefix; + + do + { + ll++; + key.dsize = l--; + data = dbm_fetch(dbm, key); + + if (data.dptr != NULL) + { + if (Len != NULL) + *Len = ll; + + strcpy(s,data.dptr); + } + } + while(l > 1); + } + + return (s[0]?s:NULL); +} +#endif + +/****************************************************************************/ + +#ifdef LIBAREA +static char *_get_areacode(char *code, int *Len, int flag) +{ + auto int cc = 0; + auto char *err; + static acInfo ac; + static int warned = 0; + int prefix = strlen(S_COUNTRY_PREFIX); + + if (!warned && (cc = GetAreaCodeInfo(&ac, code + prefix)) == acOk) + { + if (ac.AreaCodeLen > 0) + { + if (Len != NULL) + *Len = ac.AreaCodeLen + prefix; + + return ac.Info; + } + } + else + { + switch (cc) { + case acFileError : err = "Cannot open/read file"; + break; + case acInvalidFile : err = "The file exists but is no area code data file"; + break; + case acWrongVersion : err = "Wrong version of data file"; + break; + default : err = "Unknown AreaCode error"; + break; + } /* switch */ + + if (!(flag & C_NO_ERROR)) + print_msg("!!! Problem with AreaCode: %s - disabling AreaCode support!\n", err); + + warned = 1; + } + + return NULL; +} +#endif + +/****************************************************************************/ + diff --git a/lib/libisdn.h b/lib/libisdn.h new file mode 100644 index 00000000..e2517ea2 --- /dev/null +++ b/lib/libisdn.h @@ -0,0 +1,136 @@ + +/* $Id: libisdn.h,v 1.1 1997/03/03 04:23:16 fritz Exp $ + * + * ISDN accounting for isdn4linux. + * + * Copyright 1997 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. + * + */ + +#ifndef _LIB_H_ +#define _LIB_H_ + +#include + +#include "policy.h" +#include "conffile.h" + +#ifdef LIBAREA +# include "areacode/areacode.h" +#else +# include "avon/createDB.h" +#endif + +/****************************************************************************/ + +extern char *basename __P((__const char *__name)); + +/****************************************************************************/ + +#define CONFDIR_VAR "ISDN" +#define C_SLASH '/' +/* #define C_SLASH '\\' */ + +#ifndef TMPDIR +# define TMPDIR P_tmpdir +#endif + +#ifndef I4LCONFDIR +# define I4LCONFDIR "/etc/isdn" +#endif + +#ifndef RUNDIR +# define RUNDIR "/var/run" +#endif + +#ifndef CONFFILE +# define CONFFILE "isdn.conf" +#endif + +#ifndef USERCONFFILE +# define USERCONFFILE "~/.isdn" +#endif + +#ifndef S_COUNTRY_PREFIX +# define S_COUNTRY_PREFIX "+" /* "00" */ +#endif + +#ifndef S_AREA_PREFIX +# define S_AREA_PREFIX "0" +#endif + +#ifndef AVON +# define AVON "avon" +#endif + +/****************************************************************************/ + +#define CONF_SEC_GLOBAL "GLOBAL" +#define CONF_ENT_COUNTRY "COUNTRYCODE" +#define CONF_ENT_AREA "AREACODE" +#define CONF_ENT_AREALIB "AREALIB" +#define CONF_ENT_AVONLIB "AVON" + +/****************************************************************************/ + +#define C_NUM_DELIM ',' + +/****************************************************************************/ + +#define SHORT_STRING_SIZE 256 +#define LONG_STRING_SIZE 1024 +#define BUF_SIZE 4096 + +/****************************************************************************/ + +#define F_IGNORE_CASE 1024 + +/****************************************************************************/ + +#define C_NO_ERROR 1 +#define C_NO_WARN 2 +#define C_NO_EXPAND 4 + +/****************************************************************************/ + +#ifdef _ISDNTOOLS_C_ +#define _EXTERN +#define SET_NULL = "" +#else +#define _EXTERN extern +#define SET_NULL +#endif + +_EXTERN char *mycountry SET_NULL; +_EXTERN char *myarea SET_NULL; + +_EXTERN void set_print_fkt_for_lib(int (*new_print_msg)(const char *, ...)); +_EXTERN int num_match(char *Pattern, char *number); +_EXTERN char *expand_number(char *s); +_EXTERN char *expand_file(char *s); +_EXTERN char *confdir(void); +_EXTERN int create_runfile(const char* progname); +_EXTERN int delete_runfile(const char* progname); +_EXTERN int Set_Codes(section* Section); +_EXTERN char *get_areacode(char *code, int *Len, int flag); + +#undef SET_NULL +#undef _EXTERN + +/****************************************************************************/ + +#endif diff --git a/lib/libtools.c b/lib/libtools.c new file mode 100644 index 00000000..f940feb3 --- /dev/null +++ b/lib/libtools.c @@ -0,0 +1,489 @@ +/* + * 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. + * + */ + +#define _LIB_TOOLS_C_ + +/****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "libtools.h" + +/****************************************************************************/ + +static int (*print_msg)(const char *, ...) = printf; + +/****************************************************************************/ + +void set_print_fkt_for_libtools(int (*new_print_msg)(const char *, ...)) +{ + print_msg = new_print_msg; +} + +/****************************************************************************/ + +char *Not_Space(char *String) +{ + while (isspace(*String)) String++; + + if (*String == '\0') + String = NULL; + + return String; +} + +/****************************************************************************/ + +char *To_Upper (char *String) +{ + char *Ptr = String; + + while (*Ptr != '\0') + { + *Ptr = toupper(*Ptr); + Ptr++; + } + + return String; +} + +/****************************************************************************/ + +char *Kill_Blanks(char *String) +{ + int Cnt1 = 0, Cnt2 = 0; + + + while (String[Cnt1] != '\0') + { + if (!isspace(String[Cnt1])) + String[Cnt2++] = String[Cnt1]; + + Cnt1++; + } + + String[Cnt2] = '\0'; + + return String; +} + +/****************************************************************************/ + +char *FGets(char *String, int StringLen, FILE *fp, int *Line) +{ + int Len; + char *RetCode = NULL; + char *Ptr = NULL; + char *Help = NULL; + + + if ((Help = (char*) alloca(StringLen*sizeof(char))) == NULL) + return NULL; + + *String ='\0'; + + while ((RetCode = fgets(Help, StringLen - strlen(String), fp)) != NULL) + { + (*Line)++; + + if ((Len = strlen(Help)) > 0 && Help[Len-1] == '\n' ) + Help[Len-1] = '\0'; + + if ((Ptr = Check_Quote(Help,S_COMMENT,QUOTE_DELETE)) != NULL) + *Ptr = '\0'; + + strcat(String,Help); + + if ((Len = strlen(String)) > 0 && String[Len-1] == '\\' ) + String[Len-1] = '\0'; + else + break; + } + + Ptr = String; + while (isspace(*Ptr)) Ptr++; + + if (*Ptr =='\0' && RetCode != NULL) + RetCode = FGets(String,StringLen,fp,Line); + else + { + strcpy(Help,Ptr); + strcpy(String,Help); + } + + return RetCode; +} + +/****************************************************************************/ + +char *Check_Quote(char *String, char *Quote, int Flag) +{ + char *Ptr = String; + char *Ptr2; + + if (Ptr == NULL) + return NULL; + + while ((Ptr = Strpbrk(Ptr,Quote)) != NULL) + { + if (Ptr != String && *(Ptr - 1) == '\\') + { + if (Flag == QUOTE_IGNORE) + { + Ptr++; + } + else + if (Flag == QUOTE_DELETE) + { + Ptr2 = Ptr - 1; + + do + *Ptr2 = *(Ptr2 + 1); + while(*Ptr2++ != '\0'); + } + else + return NULL; + } + else + break; + } + + return Ptr; +} + +/****************************************************************************/ + +const char* Quote_Chars(char *string) +{ + int i; + int Index = 0; + static char *Ptr = NULL; + char *Help = NULL; + + if (Ptr != NULL) + free(Ptr); + + Ptr = strdup(string); + + if (string == NULL) + { + print_msg("%s!\n","Got a NULL string!\n"); + return ""; + } + + while((Help = Strpbrk(Ptr+Index,S_COMMENT)) != NULL) + { + Index = Help - Ptr; + + if ((Ptr = (char*) realloc(Ptr,(strlen(Ptr)+2)*sizeof(char))) == NULL) + { + print_msg("%s!\n","Can not alllocate memory!\n"); + return ""; + } + + for (i = strlen(Ptr); i >= Index; i--) + Ptr[i+1] = Ptr[i]; + + Ptr[Index] = '\\'; + + Index += 2; + } + + return Ptr; +} + +/****************************************************************************/ + +/* Als Workaround fuer strpbrk(): seltsame Abstuerze ;-( */ + +char *Strpbrk( const char* Str, const char* Accept ) +{ + int i; + int len; + int first = -1; + int helpfirst = -1; + int pos = -1; + + char *RetCode = NULL; + + + if (Str == NULL || Accept == NULL) + return NULL; + + len = strlen(Accept); + + for (i = 0; i < len; i++) + { + if ((RetCode = strchr(Str,Accept[i])) != NULL) + { + if ((helpfirst = RetCode - Str) < first || first == -1) + { + pos = i; + first = helpfirst; + } + } + } + + if (pos == -1) + return NULL; + else + RetCode = (char*) (Str + first); + + /* Alte Zeile + while (*Accept != '\0' && (RetCode = strchr(Str,*Accept++)) == NULL); + */ + + return RetCode; +} + +/****************************************************************************/ + +char **String_to_Array(char* String, char Trenn) +{ + char *Ptr = String; + char **RetCode = NULL; + char *Ptr1 = NULL; + char *Ptr2 = NULL; + int Cnt = 2; + + if (*String == '\0') + return NULL; + + while((Ptr = strchr(Ptr,Trenn)) != NULL) + { + Cnt++; + Ptr++; + } + + RetCode = (char**) calloc(Cnt,sizeof(char*)); + Ptr = strdup(String); + + if (RetCode == NULL || Ptr == NULL) + return NULL; + + Cnt = 0; + Ptr1 = Ptr; + + do + { + Ptr2 = strchr(Ptr1,Trenn); + + if (Ptr2) + *Ptr2++ = '\0'; + + RetCode[Cnt] = (char*) calloc(strlen(Ptr1)+1,sizeof(char)); + + if (RetCode == NULL) + return RetCode; + + strcpy(RetCode[Cnt++],Ptr1); + Ptr1 = Ptr2; + } + while (Ptr1 != NULL); + + free(Ptr); + return RetCode; +} + +/****************************************************************************/ + +void del_Array(char **Ptr) +{ + int Cnt = 0; + + if (Ptr) + { + while (Ptr[Cnt]) + free(Ptr[Cnt++]); + + free (Ptr); + } +} + +/****************************************************************************/ + +int _append_element(void ***elem, void *ins) +{ + int num = 2; + void **Ptr = *elem; + + + if (Ptr != NULL) + while(*Ptr != NULL) + num++,Ptr++; + + if ((*elem = (void**) realloc(*elem,sizeof(void*)*num)) == NULL) + { + print_msg("Can not alloc memory!\n"); + return -1; + } + + (*elem)[num-2] = ins; + (*elem)[num-1] = NULL; + return 0; +} + +/****************************************************************************/ + +int _delete_element(void ***elem, int deep) +{ + void **Ptr = *elem; + + if (deep < 0) + return -1; + + if (Ptr == NULL) + return 0; + + if (deep != 0) + while(*Ptr != NULL) + delete_element(Ptr++,deep-1); + + free(*elem); + *elem = NULL; + + return 0; +} + +/****************************************************************************/ + +int match(register char *p, register char *s, int flags) +{ + char *ptr1; + char *ptr2; + + if ((flags & F_IGNORE_CASE) || (flags & F_NO_HOLE_WORD)) + { + if ((flags & F_IGNORE_CASE) && !(flags & F_NO_HOLE_WORD) && + !strcasecmp(p,s) ) + return 0; + + if ((ptr1 = (char*) alloca((strlen(p)+3)*sizeof(char))) == NULL) + return -1; + + if ((ptr2 = (char*) alloca((strlen(s)+3)*sizeof(char))) == NULL) + return -1; + + strcpy(ptr1,p); + strcpy(ptr2,s); + + if (flags & F_IGNORE_CASE) + { + To_Upper(ptr1); + To_Upper(ptr2); + } + + if (flags & F_NO_HOLE_WORD) + { + char string[SHORT_STRING_SIZE]; + + sprintf(string,"*%s*",ptr1); + strcpy(ptr1,string); + } + + flags &= ~F_IGNORE_CASE; + flags &= ~F_NO_HOLE_WORD; + + p = ptr1; + s = ptr2; + } + else + if (!strcmp(p,s)) + return 0; + + return fnmatch(p,s,flags); +/* + register int sc, pcc; + + + if (!*s || !*p) + return(-1); + + while ((pcc = *p++ & QCMASK)) { + sc = *s++ & QMASK; + + switch (pcc) { + case '[' : if (!(p = cclass(p, sc))) + return(-1); + break; + + case '?' : if (!sc) + return(-1); + break; + + case '*' : s--; + do { + if (!*p || !match(p, s)) + return(0); + } while (*s++); + return(-1); + + default : if (sc != (pcc &~QUOTE)) + return(-1); + } + } + + return(*s); +*/ +} /* match */ + +/****************************************************************************/ + +int is_double (char *string, double *value) +{ + double dummy2 = 0; + char* dummy; + + if (*string == '\0') + return 1; + + dummy = (char*) alloca((strlen(string)+1)*sizeof(char)); + + if (value == NULL) + *value = dummy2; + + return (sscanf(string,"%lf%s",value,dummy) == 1); +} + +/****************************************************************************/ + +int is_integer (char *string, long int *value) +{ + long int dummy2 = 0; + char* dummy; + + if (*string == '\0') + return 1; + + dummy = (char*) alloca((strlen(string)+1)*sizeof(char)); + + if (value == NULL) + *value = dummy2; + + return (sscanf(string,"%ld%s",value,dummy) == 1); +} + +/****************************************************************************/ + diff --git a/lib/libtools.h b/lib/libtools.h new file mode 100644 index 00000000..9d04a6a8 --- /dev/null +++ b/lib/libtools.h @@ -0,0 +1,111 @@ + +/* $Id: libtools.h,v 1.1 1997/03/03 04:23:17 fritz Exp $ + * + * ISDN accounting for isdn4linux. + * + * Copyright 1997 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. + * + */ + +#ifndef _LIB_TOOLS_H_ +#define _LIB_TOOLS_H_ + +#include + +/****************************************************************************/ + +extern char *basename __P((__const char *__name)); + +/****************************************************************************/ + +#define CONFDIR_VAR "ISDN" +#define C_SLASH '/' +/* #define C_SLASH '\\' */ + +#ifndef TMPDIR +# define TMPDIR P_tmpdir +#endif + +#ifndef I4LCONFDIR +# define I4LCONFDIR "/etc/isdn" +#endif + +#ifndef RUNDIR +# define RUNDIR "/var/run" +#endif + +#ifndef CONFFILE +# define CONFFILE "isdn.conf" +#endif + +#ifndef USERCONFFILE +# define USERCONFFILE "~/.isdn" +#endif + +/****************************************************************************/ + +#define SHORT_STRING_SIZE 256 +#define LONG_STRING_SIZE 1024 +#define BUF_SIZE 4096 + +/****************************************************************************/ + +#define C_COMMENT '#' +#define S_COMMENT "#" + +#define QUOTE_IGNORE 0 +#define QUOTE_DELETE 1 + +/****************************************************************************/ + +#define F_IGNORE_CASE 1024 +#define F_NO_HOLE_WORD 2048 + +/****************************************************************************/ + +#define append_element(a,b) _append_element((void***) a,(void**) b) +#define delete_element(a,b) _delete_element((void***) a, b) + +/****************************************************************************/ + +#ifdef _LIB_TOOLS_C_ +#define _EXTERN +#else +#define _EXTERN extern +#endif + +_EXTERN void set_print_fkt_for_libtools(int (*new_print_msg)(const char *, ...)); +_EXTERN char *Not_Space(char *String); +_EXTERN char *To_Upper (char *String); +_EXTERN char *Kill_Blanks(char *String); +_EXTERN char *FGets(char *String, int StringLen, FILE *fp, int *Line); +_EXTERN char *Check_Quote(char *String, char *Quote, int Flag); +_EXTERN const char* Quote_Chars(char *string); +_EXTERN char *Strpbrk( const char* Str, const char* Accept ); +_EXTERN char **String_to_Array(char* String, char Trenn); +_EXTERN void del_Array(char **Ptr); +_EXTERN int _append_element(void ***elem, void *ins); +_EXTERN int _delete_element(void ***elem, int deep); +_EXTERN int match(register char *p, register char *s, int flags); +_EXTERN int is_double (char *string, double *value); +_EXTERN int is_integer (char *string, long int *value); + +#undef _EXTERN + +/****************************************************************************/ + +#endif