1416 lines
34 KiB
C
1416 lines
34 KiB
C
/* $Id: isdntools.c,v 1.29 2003/07/23 20:55:39 tobiasb Exp $
|
|
*
|
|
* ISDN accounting for isdn4linux. (Utilities)
|
|
*
|
|
* Copyright 1995, 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.
|
|
*
|
|
* $Log: isdntools.c,v $
|
|
* Revision 1.29 2003/07/23 20:55:39 tobiasb
|
|
* The modifications remove a bug which occurs when dealing with special
|
|
* numbers and the callerid.conf file. Regular numbers such as +4940555
|
|
* can be noted in the following way in a NUMBER line:
|
|
* NUMBER=+49-40-555, +49-69-555
|
|
*
|
|
* For special numbers prior to this modifications there are strong
|
|
* unmentioned limitations. Only one number per NUMBER line is allowed
|
|
* without any of the options shown above.
|
|
* Allowed: NUMBER=01802555
|
|
* Not allowed/not working: NUMBER=01802-555
|
|
* also not working: NUMBER=0180255, 0700555
|
|
*
|
|
* This modification brings the later two examples in function. About the
|
|
* background of the problem: isdnlog/isdnrep and other know a sort of
|
|
* telephone numbers called `special numbers', which are noted with S: and
|
|
* N: Tags in the rate-file. These numbers are per definition only available
|
|
* within the country. In order to emphasize this and for other more
|
|
* practical reasons, the normalized format for this numbers is not the
|
|
* usual +<countrycode><areacode><local number> but the national format
|
|
* like 01802555.
|
|
*
|
|
* While the logged numbers in /var/log/isdn.log or so follow this convention,
|
|
* such entries in callerid.conf got internally converted to the normalized
|
|
* format (+49180255 in case of the last mentioned number) so that the
|
|
* comparison executed by isdnlog or isdnrep did not show the expected
|
|
* result.
|
|
*
|
|
* The modification activates the advanced feature in the notation of normal
|
|
* numbers for special numbers.
|
|
*
|
|
* IMPORTANT NOTE: As the resulting library is located outside the isdnlog
|
|
* subdirectory, this changes may influence other parts of the isdn4k-utils.
|
|
*
|
|
* Revision 1.28 2001/08/18 11:59:01 paul
|
|
* Added missing endpwent() call that meant /etc/passwd was being kept open;
|
|
* reorganized num_match() a bit; made the arrays in expand_number() one byte
|
|
* bigger to prevent possible off-by-one buffer overflow.
|
|
*
|
|
* Revision 1.27 2000/09/05 08:05:03 paul
|
|
* Now isdnlog doesn't use any more ISDN_XX defines to determine the way it works.
|
|
* It now uses the value of "COUNTRYCODE = 999" to determine the country, and sets
|
|
* a variable mycountrynum to that value. That is then used in the code to set the
|
|
* way isdnlog works.
|
|
* It works for me, please check it! No configure.in / doc changes yet until
|
|
* it has been checked to work.
|
|
* So finally a version of isdnlog that can be compiled and distributed
|
|
* internationally.
|
|
*
|
|
* Revision 1.26 1999/08/20 19:43:46 akool
|
|
* removed avon-, vorwahl- and areacodes-support
|
|
*
|
|
* Revision 1.25 1999/06/11 15:46:54 akool
|
|
* not required references to libndbm removed
|
|
*
|
|
* Revision 1.24 1998/12/16 20:57:30 akool
|
|
* - first try to add the 1999 tarif of the German Telekom
|
|
* - fix the areacode 2.0 support
|
|
*
|
|
* Revision 1.23 1998/10/13 21:53:26 luethje
|
|
* isdnrep and lib: bugfixes
|
|
*
|
|
* Revision 1.22 1998/09/26 18:30:30 akool
|
|
* - quick and dirty Call-History in "-m" Mode (press "h" for more info) added
|
|
* - eat's one more socket, Stefan: sockets[3] now is STDIN, FIRST_DESCR=4 !!
|
|
* - Support for tesion)) Baden-Wuerttemberg Tarif
|
|
* - more Providers
|
|
* - Patches from Wilfried Teiken <wteiken@terminus.cl-ki.uni-osnabrueck.de>
|
|
* - better zone-info support in "tools/isdnconf.c"
|
|
* - buffer-overrun in "isdntools.c" fixed
|
|
* - big Austrian Patch from Michael Reinelt <reinelt@eunet.at>
|
|
* - added $(DESTDIR) in any "Makefile.in"
|
|
* - new Configure-Switches "ISDN_AT" and "ISDN_DE"
|
|
* - splitted "takt.c" and "tools.c" into
|
|
* "takt_at.c" / "takt_de.c" ...
|
|
* "tools_at.c" / "takt_de.c" ...
|
|
* - new feature
|
|
* CALLFILE = /var/log/caller.log
|
|
* CALLFMT = %b %e %T %N7 %N3 %N4 %N5 %N6
|
|
* in "isdn.conf"
|
|
* - ATTENTION:
|
|
* 1. "isdnrep" dies with an seg-fault, if not HTML-Mode (Stefan?)
|
|
* 2. "isdnlog/Makefile.in" now has hardcoded "ISDN_DE" in "DEFS"
|
|
* should be fixed soon
|
|
*
|
|
* Revision 1.21 1998/06/07 21:03:26 akool
|
|
* Renamed old to new zone-names (CityCall, RegioCall, GermanCall, GlobalCall)
|
|
*
|
|
* Revision 1.20 1998/05/11 19:43:49 luethje
|
|
* Some changes for "vorwahlen.dat"
|
|
*
|
|
* Revision 1.19 1998/05/10 22:12:01 luethje
|
|
* Added support for VORWAHLEN2.EXE
|
|
*
|
|
* Revision 1.18 1998/04/28 08:34:36 paul
|
|
* Fixed compiler warnings from egcs.
|
|
*
|
|
* Revision 1.17 1998/03/08 12:13:49 luethje
|
|
* Patches by Paul Slootman
|
|
*
|
|
* Revision 1.16 1997/06/22 22:57:08 luethje
|
|
* bugfixes
|
|
*
|
|
* Revision 1.15 1997/06/15 23:50:34 luethje
|
|
* some bugfixes
|
|
*
|
|
* Revision 1.14 1997/05/19 23:37:05 luethje
|
|
* bugfix for isdnconf
|
|
*
|
|
* Revision 1.13 1997/05/19 22:58:28 luethje
|
|
* - bugfix: it is possible to install isdnlog now
|
|
* - improved performance for read files for vbox files and mgetty files.
|
|
* - it is possible to decide via config if you want to use avon or
|
|
* areacode.
|
|
*
|
|
* Revision 1.12 1997/05/09 23:31:06 luethje
|
|
* isdnlog: new switch -O
|
|
* isdnrep: new format %S
|
|
* bugfix in handle_runfiles()
|
|
*
|
|
* Revision 1.11 1997/04/15 00:20:17 luethje
|
|
* replace variables: some bugfixes, README comleted
|
|
*
|
|
* Revision 1.10 1997/04/08 21:57:04 luethje
|
|
* Create the file isdn.conf
|
|
* some bug fixes for pid and lock file
|
|
* make the prefix of the code in `isdn.conf' variable
|
|
*
|
|
* Revision 1.9 1997/04/08 00:02:24 luethje
|
|
* Bugfix: isdnlog is running again ;-)
|
|
* isdnlog creates now a file like /var/lock/LCK..isdnctrl0
|
|
* README completed
|
|
* Added some values (countrycode, areacode, lock dir and lock file) to
|
|
* the global menu
|
|
*
|
|
* Revision 1.8 1997/04/03 22:39:13 luethje
|
|
* bug fixes: environ variables are working again, no seg. 11 :-)
|
|
* improved performance for reading the config files.
|
|
*
|
|
* Revision 1.7 1997/03/20 00:19:27 luethje
|
|
* inserted the line #include <errno.h> in avmb1/avmcapictrl.c and imon/imon.c,
|
|
* some bugfixes, new structure in isdnlog/isdnrep/isdnrep.c.
|
|
*
|
|
* Revision 1.6 1997/03/19 00:08:43 luethje
|
|
* README and function expand_number() completed.
|
|
*
|
|
* Revision 1.5 1997/03/18 23:01:50 luethje
|
|
* Function Compare_Sections() completed.
|
|
*
|
|
* Revision 1.4 1997/03/07 23:34:49 luethje
|
|
* README.conffile completed, paranoid_check() used by read_conffiles(),
|
|
* policy.h will be removed by "make distclean".
|
|
*
|
|
* Revision 1.3 1997/03/06 20:36:34 luethje
|
|
* Problem in create_runfie() fixed. New function paranoia_check() implemented.
|
|
*
|
|
* Revision 1.2 1997/03/03 22:05:39 luethje
|
|
* merging of the current version and my tree
|
|
*
|
|
* 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_
|
|
#define _GNU_SOURCE
|
|
|
|
/****************************************************************************/
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <pwd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include "libisdn.h"
|
|
|
|
/****************************************************************************/
|
|
|
|
#define GERMAN_CODE 49
|
|
|
|
/****************************************************************************/
|
|
|
|
typedef struct {
|
|
char code[15];
|
|
long int pointer;
|
|
} s_areacode;
|
|
|
|
/****************************************************************************/
|
|
|
|
static int (*print_msg)(const char *, ...) = printf;
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
#ifdef LIBAREA
|
|
static char *_get_areacode(char *code, int *Len, int flag);
|
|
#else
|
|
static char *_get_avon(char *code, int *Len, int flag);
|
|
#endif
|
|
#endif
|
|
static int create_runfile(const char *file, const char *format);
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
static long int area_read_value(FILE *fp, int size);
|
|
static int area_read_file(void);
|
|
static int area_get_index(char *code);
|
|
#endif
|
|
static char *expand_number_all (char *s, int add_prefix);
|
|
static char *expand_number_pure (char *s);
|
|
|
|
/****************************************************************************/
|
|
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
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", "Greece"},
|
|
{"+31", "Netherlands"},
|
|
{"+32", "Belgium"},
|
|
{"+33", "France"},
|
|
{"+34", "Spain"},
|
|
{"+39", "Italy"},
|
|
{"+41", "Switzerland"},
|
|
{"+43", "Austria"},
|
|
{"+44", "Great Britain"},
|
|
{"+45", "Denmark"},
|
|
{"+46", "Sweden"},
|
|
{"+47", "Norway"},
|
|
{"+49", "Germany"},
|
|
{"+352", "Luxemburg"},
|
|
{"+1", "United States"},
|
|
{"", ""},
|
|
};
|
|
|
|
static char *avonlib = NULL;
|
|
static char *codelib = NULL;
|
|
static s_areacode *codes = NULL;
|
|
static int codes_number = 0;
|
|
#endif
|
|
|
|
/****************************************************************************/
|
|
|
|
void set_print_fct_for_lib(int (*new_print_msg)(const char *, ...))
|
|
{
|
|
print_msg = new_print_msg;
|
|
set_print_fct_for_conffile(new_print_msg);
|
|
set_print_fct_for_libtools(new_print_msg);
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
set_print_fct_for_avon(new_print_msg);
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
int num_match(char* Pattern, char *number)
|
|
{
|
|
int RetCode = -1;
|
|
char **Ptr;
|
|
char **Array;
|
|
|
|
if (!strcmp(Pattern, number)) /* match */
|
|
return 0;
|
|
|
|
if (!strchr(Pattern,C_NUM_DELIM)) /* Pattern is a single number, not a list */
|
|
{
|
|
RetCode = match(expand_number(Pattern), number, 0);
|
|
if (RetCode != 0) /* try Pattern without additional prefix */
|
|
RetCode = match(expand_number_pure(Pattern), number, 0);
|
|
return RetCode;
|
|
}
|
|
|
|
Ptr = Array = String_to_Array(Pattern,C_NUM_DELIM);
|
|
|
|
while (*Ptr != NULL && RetCode != 0)
|
|
{
|
|
RetCode = match(expand_number(*Ptr), number, 0);
|
|
Ptr++;
|
|
}
|
|
|
|
if (RetCode != 0) /* second try in case of number list */
|
|
{
|
|
Ptr = Array;
|
|
while (*Ptr != NULL && RetCode != 0)
|
|
{
|
|
RetCode = match(expand_number_pure(*Ptr), number, 0);
|
|
Ptr++;
|
|
}
|
|
}
|
|
|
|
del_Array(Array);
|
|
|
|
return RetCode;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
/* Introducing expand_number_pure as a variant of expand_number without
|
|
* adding countrycode or countrycode and areacode to numbers. This is
|
|
* needed for isdnlog/isdnrep where national special numbers such as
|
|
* 01805 in Germany are intentionally stored as 01805 and not as +491805.
|
|
* The orginal expand_number which remains unchanged has no idea about
|
|
* special numbers and adds the countrycode to all numbers without, so
|
|
* that a correct entry from callerid.conf for a special number gets
|
|
* falsified and does not match as intended.
|
|
* The work is done by expand_number_all, which is the slighty extented
|
|
* former expand_number. The aliasing for expand_number and
|
|
* expand_number_all might be done in a more efficient way.
|
|
* Tobias Becker, 2003-02-11.
|
|
*/
|
|
|
|
static char *expand_number_all(char *s, int add_prefix)
|
|
{
|
|
int all_allowed = 0;
|
|
char *Ptr;
|
|
int Index = 0;
|
|
char Help[NUMBER_SIZE+1];
|
|
static char Num[NUMBER_SIZE+1];
|
|
|
|
|
|
Help[0] = '\0';
|
|
Ptr = s;
|
|
|
|
if (Ptr == NULL || Ptr[0] == '\0')
|
|
return "";
|
|
|
|
while(isblank(*Ptr))
|
|
Ptr++;
|
|
|
|
if (*Ptr == '+')
|
|
{
|
|
Strncpy(Help,countryprefix,NUMBER_SIZE);
|
|
Ptr++;
|
|
}
|
|
|
|
Index = strlen(Help);
|
|
|
|
while(*Ptr != '\0')
|
|
{
|
|
if (*Ptr == ',' || Index >= NUMBER_SIZE)
|
|
break;
|
|
|
|
if (isdigit(*Ptr) || *Ptr == '?' || *Ptr == '*'||
|
|
*Ptr == '[' || *Ptr == ']' || all_allowed )
|
|
{
|
|
if (*Ptr == '[')
|
|
all_allowed = 1;
|
|
|
|
if (*Ptr == ']')
|
|
all_allowed = 0;
|
|
|
|
Help[Index++] = *Ptr;
|
|
}
|
|
|
|
Ptr++;
|
|
}
|
|
|
|
Help[Index] = '\0';
|
|
|
|
if (Help[0] == '\0')
|
|
return s;
|
|
|
|
if (Help[0] == '*' || !strncmp(Help,countryprefix,strlen(countryprefix)) || !add_prefix)
|
|
{
|
|
strcpy(Num,Help);
|
|
}
|
|
else
|
|
if (!strncmp(Help,areaprefix,strlen(areaprefix)))
|
|
{
|
|
strcpy(Num,mycountry);
|
|
strcat(Num,Help+strlen(areaprefix));
|
|
}
|
|
else
|
|
{
|
|
strcpy(Num,mycountry);
|
|
strcat(Num,myarea/*+strlen(areaprefix)*/);
|
|
strcat(Num,Help);
|
|
}
|
|
|
|
return Num;
|
|
}
|
|
|
|
char *expand_number(char *s)
|
|
{
|
|
return expand_number_all(s, 1);
|
|
}
|
|
|
|
static char *expand_number_pure(char *s)
|
|
{
|
|
return expand_number_all(s, 0);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
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)
|
|
;
|
|
endpwent();
|
|
|
|
if (password == NULL)
|
|
return NULL;
|
|
|
|
strcpy(file,password->pw_dir);
|
|
strcat(file,strchr(s,C_SLASH));
|
|
}
|
|
|
|
return (file[0] == '\0'?s:file);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
char *confdir(void)
|
|
{
|
|
static char *confdirvar = NULL;
|
|
|
|
if (confdirvar == NULL && (confdirvar = getenv(CONFDIR_VAR)) == NULL)
|
|
confdirvar = I4LCONFDIR;
|
|
|
|
return(confdirvar);
|
|
} /* confdir */
|
|
|
|
/****************************************************************************/
|
|
|
|
int handle_runfiles(const char *_progname, char **_devices, int flag)
|
|
{
|
|
static char progname[SHORT_STRING_SIZE] = "";
|
|
static char **devices = NULL;
|
|
auto char **mydevices = NULL;
|
|
auto char string[PATH_MAX];
|
|
auto char string2[SHORT_STRING_SIZE];
|
|
auto char *Ptr = NULL;
|
|
auto int RetCode = -1;
|
|
auto FILE *fp;
|
|
|
|
|
|
if (progname[0] == '\0' || devices == NULL)
|
|
{
|
|
if (_progname == NULL || _devices == NULL)
|
|
return -1;
|
|
|
|
Ptr = strrchr(progname,C_SLASH);
|
|
strcpy(progname,Ptr?Ptr+1:_progname);
|
|
|
|
while (*_devices != NULL)
|
|
{
|
|
Ptr = strrchr(*_devices,C_SLASH);
|
|
append_element(&devices,Ptr?Ptr+1:*_devices);
|
|
_devices++;
|
|
}
|
|
}
|
|
|
|
if (flag == START_PROG)
|
|
{
|
|
sprintf(string,"%s%c%s.%s.pid",RUNDIR,C_SLASH,progname,devices[0]);
|
|
|
|
if ((RetCode = create_runfile(string,"%d\n")) != 0)
|
|
{
|
|
if (RetCode > 0)
|
|
{
|
|
print_msg("Another %s is running with pid %d!\n", progname, RetCode);
|
|
print_msg("If not delete the file `%s' and try it again!\n", string);
|
|
}
|
|
|
|
return RetCode;
|
|
}
|
|
|
|
mydevices = devices;
|
|
|
|
while (*mydevices != NULL)
|
|
{
|
|
sprintf(string,"%s%c%s%s",LOCKDIR,C_SLASH,LOCKFILE,*mydevices);
|
|
|
|
if ((RetCode = create_runfile(string,"%10d\n")) != 0)
|
|
{
|
|
if (RetCode > 0)
|
|
print_msg("Another process (pid=%d) is running on device %s!\n", RetCode, *mydevices);
|
|
|
|
return RetCode;
|
|
}
|
|
|
|
mydevices++;
|
|
}
|
|
|
|
RetCode = 0;
|
|
}
|
|
|
|
if (flag == STOP_PROG)
|
|
{
|
|
sprintf(string,"%s%c%s.%s.pid",RUNDIR,C_SLASH,progname,devices[0]);
|
|
|
|
if ((fp = fopen(string, "r")) != NULL)
|
|
{
|
|
if (fgets(string2,SHORT_STRING_SIZE,fp) != NULL)
|
|
{
|
|
if (atoi(string2) == (int)getpid())
|
|
{
|
|
if (unlink(string))
|
|
print_msg("Can not remove file %s (%s)!\n", string, strerror(errno));
|
|
else
|
|
print_msg("File %s removed!\n", string, strerror(errno));
|
|
}
|
|
else
|
|
print_msg("This is not my lock file `%s': Has PID %d!\n", string, atoi(string2));
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
while (*devices != NULL)
|
|
{
|
|
sprintf(string,"%s%c%s%s",LOCKDIR,C_SLASH,LOCKFILE,*devices);
|
|
|
|
if ((fp = fopen(string, "r")) != NULL)
|
|
{
|
|
if (fgets(string2,SHORT_STRING_SIZE,fp) != NULL)
|
|
{
|
|
if (atoi(string2) == (int)getpid())
|
|
{
|
|
if (unlink(string))
|
|
print_msg("Can not remove file %s (%s)!\n", string, strerror(errno));
|
|
else
|
|
print_msg("File %s removed!\n", string, strerror(errno));
|
|
}
|
|
else
|
|
print_msg("This is not my lock file `%s': Has PID %d!\n", string, atoi(string2));
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
devices++;
|
|
}
|
|
|
|
RetCode = 0;
|
|
}
|
|
|
|
return RetCode;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static int create_runfile(const char *file, const char *format)
|
|
{
|
|
auto char string[SHORT_STRING_SIZE];
|
|
auto int RetCode = -1;
|
|
auto int fd = -1;
|
|
auto FILE *fp;
|
|
|
|
if (file == NULL)
|
|
return -1;
|
|
|
|
if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0644)) >= 0)
|
|
{
|
|
sprintf(string, format, (int)getpid());
|
|
|
|
if (write(fd, string, strlen(string)) != strlen(string) )
|
|
{
|
|
print_msg("Can not write to PID file `%s'!\n", file);
|
|
RetCode = -1;
|
|
}
|
|
else
|
|
RetCode = 0;
|
|
|
|
close(fd);
|
|
}
|
|
else
|
|
{
|
|
if ((fp = fopen(file, "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(file))
|
|
return -1;
|
|
|
|
return create_runfile(file,format);
|
|
}
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
return RetCode;
|
|
} /* create_runfile */
|
|
|
|
|
|
/*****************************************************************************/
|
|
/*
|
|
* set_country_behaviour() - different countries have small differences in
|
|
* ISDN implementations. Use the COUNTRYCODE setting to select the behaviour
|
|
*/
|
|
|
|
static void set_country_behaviour(char *mycountry)
|
|
{
|
|
/* amazing, strtol will also accept "+0049" */
|
|
mycountrynum = strtol(mycountry, (char **)0, 10);
|
|
/*
|
|
* There's no real point in testing for a known country code.
|
|
* Setting an unknown countrycode to 49 (DE) is probably the worst
|
|
* thing you can do if you're not actually in Germany. You might
|
|
* give a warning, but do we really want that? So simply accept
|
|
* the given value - Paul Slootman 20010818
|
|
*/
|
|
#if 0
|
|
switch (mycountrynum) {
|
|
case CCODE_NL:
|
|
case CCODE_CH:
|
|
case CCODE_AT:
|
|
case CCODE_DE:
|
|
case CCODE_LU:
|
|
/* any more special cases ? */
|
|
/* these only need to have mycountrynum set correctly */
|
|
break;
|
|
default:
|
|
mycountrynum = 49; /* use Germany as default for now */
|
|
}
|
|
#endif /* 0 */
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/*
|
|
* Sets the country codes that are used for the lib. This function must
|
|
* be called by each program!
|
|
*/
|
|
|
|
#define _MAX_VARS 8
|
|
|
|
int Set_Codes(section* Section)
|
|
{
|
|
static char *ptr[_MAX_VARS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
|
|
int i;
|
|
int RetCode = 0;
|
|
entry *Entry;
|
|
char *ptr2;
|
|
char s[SHORT_STRING_SIZE];
|
|
section *SPtr;
|
|
|
|
for (i=0; i < _MAX_VARS; i++)
|
|
if (ptr[i] != NULL)
|
|
{
|
|
free(ptr[i]);
|
|
ptr[i] = NULL;
|
|
}
|
|
|
|
if ((SPtr = Get_Section(Section,CONF_SEC_GLOBAL)) == NULL)
|
|
return -1;
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
if ((Entry = Get_Entry(SPtr->entries,CONF_ENT_AREALIB)) != NULL &&
|
|
Entry->value != NULL )
|
|
ptr[0] = acFileName = strdup(Entry->value);
|
|
|
|
if ((Entry = Get_Entry(SPtr->entries,CONF_ENT_AVONLIB)) != NULL &&
|
|
Entry->value != NULL )
|
|
ptr[1] = avonlib = strdup(Entry->value);
|
|
else
|
|
{
|
|
sprintf(s, "%s%c%s", confdir(), C_SLASH, AVON);
|
|
ptr[1] = avonlib = strdup(s);
|
|
}
|
|
#endif
|
|
if ((Entry = Get_Entry(SPtr->entries,CONF_ENT_COUNTRY_PREFIX)) != NULL &&
|
|
Entry->value != NULL )
|
|
ptr[2] = countryprefix = strdup(Entry->value);
|
|
|
|
if ((Entry = Get_Entry(SPtr->entries,CONF_ENT_AREA_PREFIX)) != NULL &&
|
|
Entry->value != NULL )
|
|
ptr[3] = areaprefix = strdup(Entry->value);
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
if ((Entry = Get_Entry(SPtr->entries,CONF_ENT_CODELIB)) != NULL &&
|
|
Entry->value != NULL )
|
|
ptr[4] = codelib = strdup(Entry->value);
|
|
#endif
|
|
if ((Entry = Get_Entry(SPtr->entries,CONF_ENT_AREA)) != NULL &&
|
|
Entry->value != NULL )
|
|
{
|
|
ptr2 = Entry->value;
|
|
|
|
if (strncmp(Entry->value,areaprefix,strlen(areaprefix)))
|
|
ptr[5] = myarea = strdup(ptr2);
|
|
else
|
|
ptr[5] = myarea = strdup(ptr2+strlen(areaprefix));
|
|
|
|
if (ptr[5] != NULL)
|
|
RetCode++;
|
|
else
|
|
print_msg("Error: Variable `%s' are not set!\n",CONF_ENT_AREA);
|
|
}
|
|
|
|
if ((Entry = Get_Entry(SPtr->entries,CONF_ENT_COUNTRY)) != NULL &&
|
|
Entry->value != NULL )
|
|
{
|
|
ptr2 = Entry->value;
|
|
|
|
if (strncmp(Entry->value,countryprefix,strlen(countryprefix)))
|
|
{
|
|
sprintf(s,"%s%s",countryprefix,
|
|
Entry->value[0]=='+'?(Entry->value)+1:Entry->value);
|
|
ptr2 = s;
|
|
}
|
|
|
|
if ((ptr[6] = mycountry = strdup(ptr2)) != NULL) {
|
|
RetCode++;
|
|
set_country_behaviour(mycountry);
|
|
}
|
|
else
|
|
print_msg("Error: Variable `%s' are not set!\n",CONF_ENT_COUNTRY);
|
|
}
|
|
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
if ((Entry = Get_Entry(SPtr->entries,CONF_ENT_AREADIFF)) != NULL &&
|
|
Entry->value != NULL )
|
|
ptr[7] = areadifffile = strdup(Entry->value);
|
|
else
|
|
{
|
|
if ((areadifffile = (char*) calloc(strlen(confdir())+strlen(S_AREA_DIFF_FILE)+2,sizeof(char))) == NULL)
|
|
print_msg("Can not allocate memory!\n");
|
|
else
|
|
{
|
|
sprintf(areadifffile,"%s%c%s",confdir(),C_SLASH,S_AREA_DIFF_FILE);
|
|
|
|
if (access(areadifffile,R_OK))
|
|
{
|
|
free(areadifffile);
|
|
areadifffile = NULL;
|
|
}
|
|
else
|
|
ptr[7] = areadifffile;
|
|
}
|
|
}
|
|
#endif
|
|
SPtr = Section;
|
|
|
|
while ((SPtr = Get_Section(SPtr,CONF_SEC_VAR)) != NULL)
|
|
{
|
|
Entry = SPtr->entries;
|
|
|
|
while(Entry != NULL)
|
|
{
|
|
if (setenv(Entry->name, Entry->value, 1) != 0)
|
|
print_msg("Warning: Can not set environment variable `%s=%s'!\n", Entry->name, Entry->value);
|
|
|
|
Entry = Entry->next;
|
|
}
|
|
|
|
SPtr = SPtr->next;
|
|
}
|
|
|
|
return (RetCode==2?0:-1);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
char *get_areacode(char *code, int *Len, int flag)
|
|
{
|
|
auto char *Ptr;
|
|
auto int i = 0;
|
|
register int prefix = strlen(countryprefix);
|
|
|
|
|
|
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)+1)) == 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 0 /* DELETE_ME AK:18-Aug-99 */
|
|
#ifdef LIBAREA
|
|
if (codelib != NULL && !strcasecmp(codelib,"AREACODE"))
|
|
Ptr = _get_areacode(code,Len,flag);
|
|
#else
|
|
if (codelib != NULL && !strcasecmp(codelib,"AVON"))
|
|
Ptr = _get_avon(code,Len,flag);
|
|
#endif
|
|
else
|
|
#ifdef LIBAREA
|
|
Ptr = _get_areacode(code,Len,flag);
|
|
#else
|
|
Ptr = _get_avon(code,Len,flag);
|
|
#endif
|
|
#endif
|
|
|
|
if (Ptr != 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;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
#endif
|
|
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
#ifndef LIBAREA
|
|
static char *_get_avon(char *code, int *Len, int flag)
|
|
{
|
|
static int opened = 0;
|
|
static char s[BUFSIZ];
|
|
int prefix = strlen(countryprefix);
|
|
int ll=0;
|
|
int l;
|
|
|
|
|
|
l = strlen(code) - prefix;
|
|
|
|
s[0] = '\0';
|
|
|
|
if (Len != NULL)
|
|
*Len = -1;
|
|
|
|
if (!opened)
|
|
{
|
|
if (avonlib == NULL && !(flag & C_NO_ERROR))
|
|
print_msg("No path for AVON library defined!\n");
|
|
|
|
if (!access(avonlib, R_OK))
|
|
{
|
|
createDB(avonlib,0);
|
|
openDB(avonlib,O_WRONLY);
|
|
}
|
|
|
|
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
|
|
#endif
|
|
|
|
/****************************************************************************/
|
|
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
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(countryprefix);
|
|
|
|
|
|
if (warned)
|
|
return(NULL);
|
|
|
|
if ((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;
|
|
case acInvalidInput : err = "Input string is not a number or empty";
|
|
break;
|
|
default : err = "Unknown AreaCode error";
|
|
break;
|
|
} /* switch */
|
|
|
|
if (!(flag & C_NO_ERROR)) {
|
|
print_msg("!!! Problem with AreaCode: %s", err);
|
|
|
|
if (cc != acInvalidInput) {
|
|
print_msg(" - disabling AreaCode support!\n");
|
|
warned = 1;
|
|
}
|
|
else
|
|
print_msg("\n");
|
|
} /* if */
|
|
} /* else */
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************/
|
|
|
|
int read_conffiles(section **Section, char *groupfile)
|
|
{
|
|
static section *conf_dat = NULL;
|
|
static int read_again = 0;
|
|
auto char s[6][BUFSIZ];
|
|
auto char **vars = NULL;
|
|
auto char **files = NULL;
|
|
auto int fileflag[6];
|
|
auto int i = 0;
|
|
auto int RetCode = -1;
|
|
|
|
*Section = NULL;
|
|
|
|
if (!read_again)
|
|
{
|
|
sprintf(s[0], "%s%c%s", confdir(), C_SLASH, CONFFILE);
|
|
sprintf(s[1], "%s%c%s", confdir(), C_SLASH, CALLERIDFILE);
|
|
|
|
if (paranoia_check(s[0]))
|
|
return -1;
|
|
|
|
if (paranoia_check(s[1]))
|
|
return -1;
|
|
|
|
append_element(&files,s[0]);
|
|
fileflag[i++] = MERGE_FILE;
|
|
append_element(&files,s[1]);
|
|
fileflag[i++] = APPEND_FILE;
|
|
|
|
if (groupfile != NULL)
|
|
{
|
|
strcpy(s[2],groupfile);
|
|
append_element(&files,s[2]);
|
|
fileflag[i++] = MERGE_FILE;
|
|
}
|
|
|
|
strcpy(s[3],expand_file(USERCONFFILE));
|
|
append_element(&files,s[3]);
|
|
fileflag[i++] = MERGE_FILE;
|
|
}
|
|
|
|
sprintf(s[4],"%s|%s/%s|!%s",CONF_SEC_MSN,CONF_SEC_NUM,CONF_ENT_NUM,CONF_ENT_SI);
|
|
append_element(&vars,s[4]);
|
|
|
|
/*
|
|
sprintf(s[5],"%s|%s/%s",CONF_SEC_MSN,CONF_SEC_NUM,CONF_ENT_ALIAS);
|
|
append_element(&vars,s[5]);
|
|
*/
|
|
|
|
if ((RetCode = read_files(&conf_dat, files, fileflag, vars, C_OVERWRITE|C_NOT_UNIQUE|C_NO_WARN_FILE)) > 0)
|
|
{
|
|
*Section = conf_dat;
|
|
|
|
if (Set_Codes(conf_dat) != 0)
|
|
return -1;
|
|
}
|
|
else
|
|
*Section = conf_dat;
|
|
|
|
if (!read_again)
|
|
delete_element(&files,0);
|
|
|
|
delete_element(&vars,0);
|
|
|
|
read_again = 1;
|
|
return RetCode;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
int paranoia_check(char *cmd)
|
|
{
|
|
struct stat stbuf;
|
|
|
|
|
|
if (getuid() == 0)
|
|
{
|
|
if (stat(cmd, &stbuf))
|
|
{
|
|
if (errno == ENOENT)
|
|
return 0;
|
|
|
|
print_msg("stat() failed for file `%s', stay on the safe side!\n", cmd);
|
|
return -1;
|
|
}
|
|
|
|
if (stbuf.st_uid != 0)
|
|
{
|
|
print_msg("Owner of file `%s' is not root!\n", cmd);
|
|
return -1;
|
|
}
|
|
|
|
if ((stbuf.st_gid != 0 && (stbuf.st_mode & S_IWGRP)) ||
|
|
(stbuf.st_mode & S_IWOTH) )
|
|
{
|
|
print_msg("File `%s' is writable by group or world!\n", cmd);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
#if 0 /* DELETE_ME AK:18-Aug-99 */
|
|
static long int area_read_value(FILE *fp, int size)
|
|
{
|
|
long value = 0;
|
|
static int endian = -1;
|
|
|
|
if (size != 2 && size != 4 && size != 1)
|
|
{
|
|
print_msg("Can not read lenght %d, only 1, 2, 4\n");
|
|
return -1;
|
|
}
|
|
|
|
if (endian == -1)
|
|
{
|
|
if (htons(0x0101) == 0x0101)
|
|
endian = 0;
|
|
else
|
|
endian = 1;
|
|
}
|
|
|
|
if (fread(&value,size,1,fp) != 1)
|
|
{
|
|
print_msg("Can not read from file `%s': Too less data!\n", areadifffile);
|
|
return -1;
|
|
}
|
|
|
|
if (endian)
|
|
{
|
|
if (size == 2)
|
|
value = ntohs(value);
|
|
else
|
|
if (size == 4)
|
|
value = ntohl(value);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
const char* area_diff_string(char* number1, char* number2)
|
|
{
|
|
switch(area_diff(number1,number2))
|
|
{
|
|
case AREA_LOCAL : return "CityCall"; break;
|
|
case AREA_R50 : return "RegioCall"; break;
|
|
case AREA_FAR : return "GermanCall"; break;
|
|
case AREA_ABROAD: return "GlobalCall"; break;
|
|
default : break;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
int area_diff(char* _code, char *_diffcode)
|
|
{
|
|
FILE *fp = NULL;
|
|
char code[NUMBER_SIZE];
|
|
char diffcode[NUMBER_SIZE];
|
|
char value[15];
|
|
int index;
|
|
int number;
|
|
int i = 0;
|
|
|
|
|
|
if (codes == NULL)
|
|
if (area_read_file() == -1)
|
|
return AREA_ERROR;
|
|
|
|
if (_code == NULL)
|
|
{
|
|
Strncpy(code,mycountry,NUMBER_SIZE);
|
|
Strncat(code,myarea,NUMBER_SIZE);
|
|
}
|
|
else
|
|
Strncpy(code,expand_number(_code),NUMBER_SIZE);
|
|
|
|
if (strncmp(mycountry,code,strlen(mycountry)))
|
|
return AREA_UNKNOWN;
|
|
|
|
if (_diffcode == NULL)
|
|
return AREA_ERROR;
|
|
else
|
|
Strncpy(diffcode,expand_number(_diffcode),NUMBER_SIZE);
|
|
|
|
if ((index = area_get_index(code)) == -1)
|
|
return AREA_ERROR;
|
|
|
|
if ((fp = fopen(areadifffile,"r")) == NULL)
|
|
{
|
|
print_msg("Can not open file `%s': %s\n", areadifffile, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
fseek(fp,codes[index].pointer,SEEK_SET);
|
|
|
|
number = area_read_value(fp,2);
|
|
|
|
i = 0;
|
|
while(i++<number)
|
|
{
|
|
sprintf(value,"%s%d%ld",countryprefix,GERMAN_CODE,(area_read_value(fp,2)+32768)%65536);
|
|
if (!strncmp(value,diffcode,strlen(value)))
|
|
{
|
|
fclose(fp);
|
|
return AREA_LOCAL;
|
|
}
|
|
}
|
|
|
|
number = area_read_value(fp,2);
|
|
|
|
i = 0;
|
|
while(i++<number)
|
|
{
|
|
sprintf(value,"%s%d%ld",countryprefix,GERMAN_CODE,(area_read_value(fp,2)+32768)%65536);
|
|
if (!strncmp(value,diffcode,strlen(value)))
|
|
{
|
|
fclose(fp);
|
|
return AREA_R50;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
if (!strncmp(mycountry,diffcode,strlen(mycountry)))
|
|
{
|
|
i = 0;
|
|
|
|
do
|
|
{
|
|
if (areacodes[i][0][0] != '\0')
|
|
{
|
|
strcpy(value, expand_number((char*) areacodes[i][0]));
|
|
|
|
if (!strncmp(diffcode,value,strlen(value)))
|
|
return AREA_UNKNOWN;
|
|
}
|
|
}
|
|
while (areacodes[++i][0][0] != '\0');
|
|
|
|
return AREA_FAR;
|
|
}
|
|
else
|
|
return AREA_ABROAD;
|
|
|
|
return AREA_UNKNOWN;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static int area_get_index(char *code)
|
|
{
|
|
int index = -1;
|
|
|
|
if (codes == NULL)
|
|
return -1;
|
|
|
|
while(++index < codes_number)
|
|
if (!strcmp(codes[index].code,code))
|
|
break;
|
|
|
|
if (index == codes_number)
|
|
{
|
|
print_msg("Can not find area code `%s'!\n", code);
|
|
index = -1;
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static int area_read_file(void)
|
|
{
|
|
FILE *fp = NULL;
|
|
int i = 0;
|
|
|
|
|
|
if (areadifffile == NULL)
|
|
{
|
|
// print_msg("There is no file name for vorwahl database!\n");
|
|
return -1;
|
|
}
|
|
|
|
if ((fp = fopen(areadifffile,"r")) == NULL)
|
|
{
|
|
print_msg("Can not open file `%s': %s\n", areadifffile, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
if ((codes_number = area_read_value(fp,2)) < 0)
|
|
{
|
|
print_msg("Number of areacodes is wrong: %d\n", codes_number);
|
|
return -1;
|
|
}
|
|
|
|
if (codes != NULL)
|
|
free(codes);
|
|
|
|
if ((codes = (s_areacode*) calloc(codes_number,sizeof(s_areacode))) == NULL)
|
|
{
|
|
print_msg("%s\n", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
if (fseek(fp,3,SEEK_SET) != 0)
|
|
{
|
|
print_msg("Can not seek file `%s' to position %d: %s\n", areadifffile, 4*codes_number+3, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
while (i<codes_number)
|
|
codes[i++].pointer = area_read_value(fp,4) -1;
|
|
|
|
if (fseek(fp,4*codes_number+3,SEEK_SET) != 0)
|
|
{
|
|
print_msg("Can not seek file `%s' to position %d: %s\n", areadifffile, 4*codes_number+3, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
i = 0;
|
|
while (i<codes_number)
|
|
sprintf(codes[i++].code,"%s%d%ld",countryprefix,GERMAN_CODE,(area_read_value(fp,2)+32768)%65536);
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
#endif
|