From 76047132695790942c6c2ec0349115018031ca21 Mon Sep 17 00:00:00 2001 From: tobiasb Date: Wed, 23 Feb 2005 14:33:37 +0000 Subject: [PATCH] New feature: provider skipping. Certain providers can be completely ignored (skipped) when loading the rate-file. The selection is done by Q: tags in rate.conf or by skipProv= in the parameter file. The syntax is explained in the new manual page rate.conf(5). Absurd settings for provider skipping may cause trouble. The version number will change to 4.70 in a few days after an update of the rate-de.dat. --- isdnlog/ChangeLog | 11 + isdnlog/Makefile.in | 35 ++- isdnlog/configure | 9 +- isdnlog/configure.in | 6 +- isdnlog/isdnlog/ChangeLog | 10 + isdnlog/isdnlog/isdnlog.8.in | 16 +- isdnlog/isdnlog/isdnlog.c | 47 +++- isdnlog/tools/.cvsignore | 2 + isdnlog/tools/ChangeLog | 13 + isdnlog/tools/rate-files.man | 3 +- isdnlog/tools/rate.c | 165 ++++++++---- isdnlog/tools/rate.conf.5.in | 199 +++++++++++++++ isdnlog/tools/rate_skip.c | 470 +++++++++++++++++++++++++++++++++++ isdnlog/tools/rate_skip.h | 46 ++++ isdnlog/tools/tools.h | 13 +- 15 files changed, 982 insertions(+), 63 deletions(-) create mode 100644 isdnlog/tools/rate.conf.5.in create mode 100644 isdnlog/tools/rate_skip.c create mode 100644 isdnlog/tools/rate_skip.h diff --git a/isdnlog/ChangeLog b/isdnlog/ChangeLog index 5ee495a1..43d0042a 100644 --- a/isdnlog/ChangeLog +++ b/isdnlog/ChangeLog @@ -1,3 +1,14 @@ +2005-02-23 Tobias Becker + * Makefile.in: Added file tools/rate_skip.o to object file lists. + Added install instruction for new manual page rate.conf(5). + + * configure.in: Added tools/rate.conf.5.in to list for text + substitution. New variables MANDATE_RATE_CONF and VERSION_ISDNLOG + for text replacement in manual pages. VERSION_ISDNLOG is set to + VERSION from Makefile.in by grep. + * configure: Same changes as for configure.in, generated by a + patched autconf 2.53, which had been used for former revisions. + 2004-12-10 Tobias Becker * Makefile.in (NATION): Export this variable to child processes, like make in subdirectories. diff --git a/isdnlog/Makefile.in b/isdnlog/Makefile.in index d057a9ff..972d6fdf 100644 --- a/isdnlog/Makefile.in +++ b/isdnlog/Makefile.in @@ -1,4 +1,4 @@ -## $Id: Makefile.in,v 1.217 2004/12/10 18:26:10 tobiasb Exp $ +## $Id: Makefile.in,v 1.218 2005/02/23 14:33:38 tobiasb Exp $ ## ## ISDN accounting for isdn4linux. ## @@ -19,6 +19,15 @@ ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## ## $Log: Makefile.in,v $ +## Revision 1.218 2005/02/23 14:33:38 tobiasb +## New feature: provider skipping. +## Certain providers can be completely ignored (skipped) when loading the +## rate-file. The selection is done by Q: tags in rate.conf or by skipProv= +## in the parameter file. The syntax is explained in the new manual page +## rate.conf(5). Absurd settings for provider skipping may cause trouble. +## The version number will change to 4.70 in a few days after an update +## of the rate-de.dat. +## ## Revision 1.217 2004/12/10 18:26:10 tobiasb ## Let "make all" in the isdnlog directory create the necessary zone files. ## @@ -1694,6 +1703,8 @@ SERVICEFILE = /etc/services # DON'T EDIT BELOW THIS LINE ###################################################################### +# next line must match basic regexp "^VERSION \+= \+" and contain only +# the isdnlog version number after it. VERSION = 4.69 # fallback to I4L-Version as set at configure time @@ -1706,7 +1717,7 @@ endif MANPAGES = isdnlog/callerid.conf.5 isdnlog/isdn.conf.5 \ isdnlog/isdnformat.5 isdnlog/isdnlog.5 isdnlog/isdnlog.8 \ isdnlog/isdnlog.users.5 isdnrep/isdnrep.1 isdnconf/isdnconf.1 \ - tools/isdnrate.1 tools/rate-files.5 \ + tools/isdnrate.1 tools/rate-files.5 tools/rate.conf.5 \ isdnrep/isdnbill.1 MANPAGES += samples/isdn.conf \ samples/isdn.conf.at samples/isdn.conf.de samples/isdn.conf.lu \ @@ -1798,7 +1809,8 @@ ISDNLOG_OBJS = isdnlog/isdnlog.o isdnlog/processor.o isdnlog/functions.o \ connect/connect.o connect/socket.o tools/tools.o \ connect/conv_address.o isdnlog/user_access.o \ tools/isdnconf.o tools/telnum.o tools/dest.o \ - tools/rate.o tools/zone.o tools/holiday.o tools/zone/upack.o \ + tools/rate.o tools/rate_skip.o \ + tools/zone.o tools/holiday.o tools/zone/upack.o \ isdnlog/asn1.o isdnlog/asn1_generic.o isdnlog/asn1_aoc.o \ isdnlog/asn1_address.o isdnlog/asn1_diversion.o \ isdnlog/asn1_basic_service.o isdnlog/asn1_comp.o \ @@ -1828,24 +1840,28 @@ endif ISDNREP_OBJS = isdnrep/rep_main.o tools/tools.o tools/isdnconf.o \ isdnlog/messages.o isdnrep/isdnrep.o isdnrep/opt_time.o \ - tools/rate.o tools/zone.o tools/holiday.o tools/dest.o \ - tools/telnum.o tools/zone/upack.o \ + tools/rate.o tools/rate_skip.o \ + tools/zone.o tools/holiday.o tools/dest.o \ + tools/telnum.o tools/zone/upack.o \ $(LIBISDNDIR)/libisdn.a $(CDBEXTRALIBS) ISDNBILL_OBJS = isdnrep/isdnbill.o tools/tools.o tools/isdnconf.o \ isdnlog/messages.o \ - tools/rate.o tools/zone.o tools/holiday.o tools/dest.o \ + tools/rate.o tools/rate_skip.o \ + tools/zone.o tools/holiday.o tools/dest.o \ tools/telnum.o tools/zone/upack.o \ $(LIBISDNDIR)/libisdn.a $(CDBEXTRALIBS) +# Are these all necessary? I believe they are not. (tobiasb, 2005-02-05) ISDNCONF_OBJS= isdnconf/isdnconf.o tools/tools.o tools/isdnconf.o \ - tools/rate.o tools/zone.o tools/holiday.o \ + tools/rate.o tools/rate_skip.o \ + tools/zone.o tools/holiday.o \ tools/telnum.o tools/dest.o tools/zone/upack.o \ $(LIBISDNDIR)/libisdn.a $(CDBEXTRALIBS) ISDNRATE_OBJS= tools/isdnrate.o tools/isdnconf.o tools/tools.o \ - tools/rate.o tools/zone.o tools/dest.o \ - tools/holiday.o \ + tools/rate.o tools/rate_skip.o \ + tools/zone.o tools/dest.o tools/holiday.o \ tools/telnum.o tools/zone/upack.o \ $(LIBISDNDIR)/libisdn.a $(CDBEXTRALIBS) @@ -2030,6 +2046,7 @@ install-data: $(INSTALL_DATA) isdnlog/isdnformat.5 $(DESTDIR)$(MAN5DIR)/isdnformat$(MAN5EXT) $(INSTALL_DATA) tools/isdnrate.1 $(DESTDIR)$(MAN1DIR)/isdnrate$(MAN1EXT) $(INSTALL_DATA) tools/rate-files.5 $(DESTDIR)$(MAN5DIR)/rate-files$(MAN5EXT) + $(INSTALL_DATA) tools/rate.conf.5 $(DESTDIR)$(MAN5DIR)/rate.conf$(MAN5EXT) $(INSTALL_DATA) country-de.dat $(DESTDIR)$(DATADIR)/country.dat $(INSTALL_DATA) rate-$(NATION).dat $(DESTDIR)$(DATADIR) $(INSTALL_DATA) holiday-$(NATION).dat $(DESTDIR)$(DATADIR) diff --git a/isdnlog/configure b/isdnlog/configure index 9efcdfd2..c36c73cc 100755 --- a/isdnlog/configure +++ b/isdnlog/configure @@ -1250,6 +1250,7 @@ DATADIR=`eval echo $datadir` DOCDIR=`eval echo $DOCDIR` MANDATE_CALLERID=`grep CHECKIN isdnlog/callerid.conf.5.in | awk '{print $4}'` MANDATE_ISDN_CONF=`grep CHECKIN isdnlog/isdn.conf.5.in | awk '{print $4}'` +MANDATE_RATE_CONF=`grep CHECKIN tools/rate.conf.5.in | awk '{print $4}'` MANDATE_ISDNFORMAT=`grep CHECKIN isdnlog/isdnformat.5.in | awk '{print $4}'` MANDATE_ISDNLOG5=`grep CHECKIN isdnlog/isdnlog.5.in | awk '{print $4}'` MANDATE_ISDNLOG8=`grep CHECKIN isdnlog/isdnlog.8.in | awk '{print $4}'` @@ -1257,6 +1258,7 @@ MANDATE_ISDNLOG_USERS=`grep CHECKIN isdnlog/isdnlog.users.5.in | awk '{print $4} MANDATE_ISDNREP=`grep CHECKIN isdnrep/isdnrep.1.in | awk '{print $4}'` MANDATE_ISDNBILL=`grep CHECKIN isdnrep/isdnbill.1.in | awk '{print $4}'` MANDATE_ISDNCONF=`grep CHECKIN isdnconf/isdnconf.1.in | awk '{print $4}'` +ISDNLOG_VERSION=`grep "^VERSION \+= \+" Makefile.in | awk '{print $3}'` if test "$CONFIG_LIB_AREACODE" = "y" ; then ALIB=area @@ -4337,7 +4339,9 @@ esac -ac_config_files="$ac_config_files Makefile isdnlog/callerid.conf.5 isdnlog/isdn.conf.5 isdnlog/isdnformat.5 isdnlog/isdnlog.5 isdnlog/isdnlog.8 isdnlog/isdnlog.users.5 isdnrep/isdnrep.1 isdnrep/isdnbill.1 isdnconf/isdnconf.1 samples/isdn.conf samples/isdn.conf.at samples/isdn.conf.de samples/isdn.conf.lu samples/isdn.conf.nl samples/isdn.conf.no samples/isdn.conf.pl" + + +ac_config_files="$ac_config_files Makefile isdnlog/callerid.conf.5 isdnlog/isdn.conf.5 tools/rate.conf.5 isdnlog/isdnformat.5 isdnlog/isdnlog.5 isdnlog/isdnlog.8 isdnlog/isdnlog.users.5 isdnrep/isdnrep.1 isdnrep/isdnbill.1 isdnconf/isdnconf.1 samples/isdn.conf samples/isdn.conf.at samples/isdn.conf.de samples/isdn.conf.lu samples/isdn.conf.nl samples/isdn.conf.no samples/isdn.conf.pl" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -4812,6 +4816,7 @@ do "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "isdnlog/callerid.conf.5" ) CONFIG_FILES="$CONFIG_FILES isdnlog/callerid.conf.5" ;; "isdnlog/isdn.conf.5" ) CONFIG_FILES="$CONFIG_FILES isdnlog/isdn.conf.5" ;; + "tools/rate.conf.5" ) CONFIG_FILES="$CONFIG_FILES tools/rate.conf.5" ;; "isdnlog/isdnformat.5" ) CONFIG_FILES="$CONFIG_FILES isdnlog/isdnformat.5" ;; "isdnlog/isdnlog.5" ) CONFIG_FILES="$CONFIG_FILES isdnlog/isdnlog.5" ;; "isdnlog/isdnlog.8" ) CONFIG_FILES="$CONFIG_FILES isdnlog/isdnlog.8" ;; @@ -4948,6 +4953,7 @@ s,@AREAPREFIX@,$AREAPREFIX,;t t s,@NATION@,$NATION,;t t s,@NATION_MACRO@,$NATION_MACRO,;t t s,@I4LVERSION@,$I4LVERSION,;t t +s,@ISDNLOG_VERSION@,$ISDNLOG_VERSION,;t t s,@DATADIR@,$DATADIR,;t t s,@DOCDIR@,$DOCDIR,;t t s,@RELOADCMD@,$RELOADCMD,;t t @@ -4955,6 +4961,7 @@ s,@STOPCMD@,$STOPCMD,;t t s,@REBOOTCMD@,$REBOOTCMD,;t t s,@MANDATE_CALLERID@,$MANDATE_CALLERID,;t t s,@MANDATE_ISDN_CONF@,$MANDATE_ISDN_CONF,;t t +s,@MANDATE_RATE_CONF@,$MANDATE_RATE_CONF,;t t s,@MANDATE_ISDNFORMAT@,$MANDATE_ISDNFORMAT,;t t s,@MANDATE_ISDNLOG5@,$MANDATE_ISDNLOG5,;t t s,@MANDATE_ISDNLOG8@,$MANDATE_ISDNLOG8,;t t diff --git a/isdnlog/configure.in b/isdnlog/configure.in index 5a5e1be0..eb7ed2f6 100644 --- a/isdnlog/configure.in +++ b/isdnlog/configure.in @@ -63,6 +63,7 @@ DATADIR=`eval echo $datadir` DOCDIR=`eval echo $DOCDIR` MANDATE_CALLERID=`grep CHECKIN isdnlog/callerid.conf.5.in | awk '{print $4}'` MANDATE_ISDN_CONF=`grep CHECKIN isdnlog/isdn.conf.5.in | awk '{print $4}'` +MANDATE_RATE_CONF=`grep CHECKIN tools/rate.conf.5.in | awk '{print $4}'` MANDATE_ISDNFORMAT=`grep CHECKIN isdnlog/isdnformat.5.in | awk '{print $4}'` MANDATE_ISDNLOG5=`grep CHECKIN isdnlog/isdnlog.5.in | awk '{print $4}'` MANDATE_ISDNLOG8=`grep CHECKIN isdnlog/isdnlog.8.in | awk '{print $4}'` @@ -70,6 +71,7 @@ MANDATE_ISDNLOG_USERS=`grep CHECKIN isdnlog/isdnlog.users.5.in | awk '{print $4} MANDATE_ISDNREP=`grep CHECKIN isdnrep/isdnrep.1.in | awk '{print $4}'` MANDATE_ISDNBILL=`grep CHECKIN isdnrep/isdnbill.1.in | awk '{print $4}'` MANDATE_ISDNCONF=`grep CHECKIN isdnconf/isdnconf.1.in | awk '{print $4}'` +ISDNLOG_VERSION=`grep "^VERSION \+= \+" Makefile.in | awk '{print $3}'` if test "$CONFIG_LIB_AREACODE" = "y" ; then ALIB=area @@ -240,6 +242,7 @@ AC_SUBST(AREAPREFIX) AC_SUBST(NATION) AC_SUBST(NATION_MACRO) AC_SUBST(I4LVERSION) +AC_SUBST(ISDNLOG_VERSION) AC_SUBST(DATADIR) AC_SUBST(DOCDIR) AC_SUBST(RELOADCMD) @@ -247,6 +250,7 @@ AC_SUBST(STOPCMD) AC_SUBST(REBOOTCMD) AC_SUBST(MANDATE_CALLERID) AC_SUBST(MANDATE_ISDN_CONF) +AC_SUBST(MANDATE_RATE_CONF) AC_SUBST(MANDATE_ISDNFORMAT) AC_SUBST(MANDATE_ISDNLOG5) AC_SUBST(MANDATE_ISDNLOG8) @@ -255,4 +259,4 @@ AC_SUBST(MANDATE_ISDNREP) AC_SUBST(MANDATE_ISDNBILL) AC_SUBST(MANDATE_ISDNCONF) AC_SUBST(CDBEXTRALIBS) -AC_OUTPUT(Makefile isdnlog/callerid.conf.5 isdnlog/isdn.conf.5 isdnlog/isdnformat.5 isdnlog/isdnlog.5 isdnlog/isdnlog.8 isdnlog/isdnlog.users.5 isdnrep/isdnrep.1 isdnrep/isdnbill.1 isdnconf/isdnconf.1 samples/isdn.conf samples/isdn.conf.at samples/isdn.conf.de samples/isdn.conf.lu samples/isdn.conf.nl samples/isdn.conf.no samples/isdn.conf.pl) +AC_OUTPUT(Makefile isdnlog/callerid.conf.5 isdnlog/isdn.conf.5 tools/rate.conf.5 isdnlog/isdnformat.5 isdnlog/isdnlog.5 isdnlog/isdnlog.8 isdnlog/isdnlog.users.5 isdnrep/isdnrep.1 isdnrep/isdnbill.1 isdnconf/isdnconf.1 samples/isdn.conf samples/isdn.conf.at samples/isdn.conf.de samples/isdn.conf.lu samples/isdn.conf.nl samples/isdn.conf.no samples/isdn.conf.pl) diff --git a/isdnlog/isdnlog/ChangeLog b/isdnlog/isdnlog/ChangeLog index 36b142dc..203e7f28 100644 --- a/isdnlog/isdnlog/ChangeLog +++ b/isdnlog/isdnlog/ChangeLog @@ -1,3 +1,13 @@ +2005-02-23 Tobias Becker + + * isdnlog.c (read_param_file): Store value for skipProv from + parameter file to param_skipprov, a new variable at file scope. + * isdnlog.c (main): Call add_skipped_provider with param_skipprov + before initRate. Added debug info about list of skipped providers, + output is classified as PRT_DEBUG_GENERAL which seems to be almost + unused so far. After initRate and debug output, the list of + skipped providers is freed. + 2005-01-02 Tobias Becker * processor.c (buildnumber): Repeat test for special number and diff --git a/isdnlog/isdnlog/isdnlog.8.in b/isdnlog/isdnlog/isdnlog.8.in index 0f13afa8..169729df 100644 --- a/isdnlog/isdnlog/isdnlog.8.in +++ b/isdnlog/isdnlog/isdnlog.8.in @@ -1,5 +1,5 @@ -.\" $Id: isdnlog.8.in,v 1.16 2004/12/16 22:40:30 tobiasb Exp $ -.\" CHECKIN $Date: 2004/12/16 22:40:30 $ +.\" $Id: isdnlog.8.in,v 1.17 2005/02/23 14:33:39 tobiasb Exp $ +.\" CHECKIN $Date: 2005/02/23 14:33:39 $ .TH isdnlog 8 "@MANDATE_ISDNLOG8@" "ISDN 4 Linux @I4LVERSION@" "Linux System Administration" .PD 0 .SH NAME @@ -33,6 +33,7 @@ show version information and exit. .BI \-f FILE read options from the config file .IR FILE . +This file is also called the parameter file of isdnlog. The first line should be "[options]". You may use blank lines and comments (starting with a #). All config files for isdnlog have the format described in isdn.conf(5). @@ -73,6 +74,13 @@ Values are e.g. "010" for DE, "10" for AT, "16:17" for NL, "9" for FR. Set the preselected (i.e the provider choosen, if no prefix is dialed) provider to value. Value should be without \fIvbn\fR. +.TP +.BI skipProv= skiplist +(There is no commandline option for this.) +Ignore certain providers from the rate-file. The format of +.I skiplist +is the same as for Q: tags in rate.conf and described in rate.conf(5). + .TP .B \-0\fIx:y\fB trim="value[:value]" Suppress leading digits. If isdnlog is connected through a PABX, it is @@ -579,7 +587,9 @@ start=yes # enable starting programs .SH SEE ALSO .B isdnconf(1) isdn.conf(5) callerid.conf(5) .br -.B isdnlog(5) isdnrep(1) rate-files(5) isdnrate(1) +.B rate-files(5) rate.conf(5) +.br +.B isdnlog(5) isdnrep(1) isdnrate(1) .SH AUTHOR This manual page was written by Andreas Jellinghaus , diff --git a/isdnlog/isdnlog/isdnlog.c b/isdnlog/isdnlog/isdnlog.c index 74216f43..6d5d2b9c 100644 --- a/isdnlog/isdnlog/isdnlog.c +++ b/isdnlog/isdnlog/isdnlog.c @@ -1,4 +1,4 @@ -/* $Id: isdnlog.c,v 1.75 2004/12/16 22:40:30 tobiasb Exp $ +/* $Id: isdnlog.c,v 1.76 2005/02/23 14:33:39 tobiasb Exp $ * * ISDN accounting for isdn4linux. (log-module) * @@ -19,6 +19,15 @@ * along with this program; if not, write to the Free Software * * $Log: isdnlog.c,v $ + * Revision 1.76 2005/02/23 14:33:39 tobiasb + * New feature: provider skipping. + * Certain providers can be completely ignored (skipped) when loading the + * rate-file. The selection is done by Q: tags in rate.conf or by skipProv= + * in the parameter file. The syntax is explained in the new manual page + * rate.conf(5). Absurd settings for provider skipping may cause trouble. + * The version number will change to 4.70 in a few days after an update + * of the rate-de.dat. + * * Revision 1.75 2004/12/16 22:40:30 tobiasb * Fix for rate computation of outgoing calls from other devices and for logging * of calls from and to the observed card (simultaneous SETUP messages). @@ -541,6 +550,7 @@ #include "isdnlog.h" #include "dest.h" +#include "rate_skip.h" #ifdef POSTGRES #include "postgres.h" #endif @@ -591,6 +601,7 @@ static char **hup_argv; /* args to restart with */ static int sqldump = 0; static char *param_myarea = NULL; +static char *param_skipprov = NULL; /*****************************************************************************/ @@ -1326,6 +1337,9 @@ static int read_param_file(char *FileName) if (p && *p) param_myarea = p; } + else + if (!strcmp(Ptr->name,CONF_ENT_SKIPPROV)) + param_skipprov = strdup(Ptr->value); else print_msg(PRT_ERR,"Error: Invalid entry `%s'!\n",Ptr->name); @@ -1718,21 +1732,46 @@ int main(int argc, char *argv[], char *envp[]) if (!Q931dmp) { initHoliday(holifile, &version); - if (*version) print_msg(PRT_NORMAL, "%s\n", version); initDest(destfile, &version); - if (*version) print_msg(PRT_NORMAL, "%s\n", version); - initRate(rateconf, ratefile, zonefile, &version); + if (param_skipprov) { + i = add_skipped_provider(param_skipprov, &version); + if (i) + print_msg(PRT_WARN, "%s in parameter file contains an error: %s\n", + CONF_ENT_SKIPPROV, version); + i = dump_skipped_provider(s, sizeof s); + if (i > -1) + print_msg(PRT_DEBUG_GENERAL, "dump_skipped_provider after " + "add_skipped_provider for parameter file: >%s< (%i).\n", + s, i); + else + print_msg(PRT_DEBUG_GENERAL, "dump_skipped_provider after " + "add_skipped_provider for parameter file: FAILED.\n"); + free(param_skipprov); + param_skipprov = NULL; + } + initRate(rateconf, ratefile, zonefile, &version); if (*version) print_msg(PRT_NORMAL, "%s\n", version); } /* if */ + + i = dump_skipped_provider(s, sizeof s); + if (i > -1) + print_msg(PRT_DEBUG_GENERAL, "dump_skipped_provider after initRate:" + " >%s< (%i).\n", s, i); + else + print_msg(PRT_DEBUG_GENERAL, "dump_skipped_provider after initRate:" + "FAILED.\n"); + i = clear_skipped_provider(); + print_msg(PRT_DEBUG_GENERAL, "clear_skipped_provider: %i freed.\n", i); + if (sqldump) { auto FILE *fo = fopen(((sqldump == 2) ? "/tmp/isdnconf.csv" : "/tmp/isdn.conf.sql"), "w"); register int i; diff --git a/isdnlog/tools/.cvsignore b/isdnlog/tools/.cvsignore index f8ec0ca5..5cf39237 100644 --- a/isdnlog/tools/.cvsignore +++ b/isdnlog/tools/.cvsignore @@ -1,3 +1,5 @@ country isdnrate.1 +rate.conf.5 +rate_skip rate-files.5 diff --git a/isdnlog/tools/ChangeLog b/isdnlog/tools/ChangeLog index 822b0957..fa47564d 100644 --- a/isdnlog/tools/ChangeLog +++ b/isdnlog/tools/ChangeLog @@ -1,3 +1,16 @@ +2005-02-23 Tobias Becker + + * rate_skip.c, rate_skip.h: This implements the new feature of + provider skipping. For end user information there is a new + manual page rate.conf(5), the interface is described in rate_skip.c. + + * rate.c (initRate): Call add_skipped_provider for Q: tags in + rate.conf. Moved parsing of P: tag from rate-file to new function + parse_P. Added provider skipping for rate-file reading and parsing. + + * tools.h (CONF_ENT_SKIPPROV): New constant for name of skipProv + entry in parameter file. + 2005-01-12 Tobias Becker * dest.c (getDest): Do not shorten the given number to less than one diff --git a/isdnlog/tools/rate-files.man b/isdnlog/tools/rate-files.man index e557b4ba..2790b150 100644 --- a/isdnlog/tools/rate-files.man +++ b/isdnlog/tools/rate-files.man @@ -1,6 +1,6 @@ '\" t '\" ** above should format a table ** -.\" CHECKIN $Date: 2004/10/04 14:50:41 $ +.\" CHECKIN $Date: 2005/02/23 14:33:40 $ .TH rate-files 5 "@MANDATE@" -lt- .SH NAME rate-files \- Format of rate-files @@ -469,6 +469,7 @@ T:[01.01.2004]E,H/*=0.06/60 weekend .SH SEE ALSO .IR isdnlog(8) , .IR isdnrate(1) , +.IR rate.conf(5) , isdnlog/README, rate-at.dat .SH AUTHOR Leopold Toetsch (of this man page of course). diff --git a/isdnlog/tools/rate.c b/isdnlog/tools/rate.c index 35b92dea..f4c86d73 100644 --- a/isdnlog/tools/rate.c +++ b/isdnlog/tools/rate.c @@ -1,6 +1,6 @@ /* #define DEBUG_REDIRZ */ -/* $Id: rate.c,v 1.89 2005/01/02 16:37:21 tobiasb Exp $ +/* $Id: rate.c,v 1.90 2005/02/23 14:33:40 tobiasb Exp $ * * Tarifdatenbank * @@ -21,6 +21,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: rate.c,v $ + * Revision 1.90 2005/02/23 14:33:40 tobiasb + * New feature: provider skipping. + * Certain providers can be completely ignored (skipped) when loading the + * rate-file. The selection is done by Q: tags in rate.conf or by skipProv= + * in the parameter file. The syntax is explained in the new manual page + * rate.conf(5). Absurd settings for provider skipping may cause trouble. + * The version number will change to 4.70 in a few days after an update + * of the rate-de.dat. + * * Revision 1.89 2005/01/02 16:37:21 tobiasb * Improved utilization of special number information from ratefile. * @@ -765,6 +774,7 @@ extern const char *basename (const char *name); #include "zone.h" #include "dest.h" #include "rate.h" +#include "rate_skip.h" #define LENGTH 1024 /* max length of lines in data file */ #define STRINGS 8 /* number of buffers for printRate() */ @@ -867,6 +877,16 @@ typedef struct { int _zone; /* internal zone */ } PRSEL; +/* takes parsing result for P:[\[daterange\]]nn[,v] description */ +typedef struct { + int prefix; /* nn -- provider number, not internal prefix */ + int variant; /* v -- provider variant or UNKNOWN if missing */ + time_t from_d; /* begin of daterange or 0 if not given */ + time_t to_d; /* end of daterange or 0 if not given */ + char *name; /* description/name for provider or NULL if missing */ + int booked; /* is this provider booked by a rate-conf P: entry? */ +} PLINE; /* in case of syntax errors, prefix will be UNKNOWN */ + static char Format[STRINGL]=""; static PROVIDER *Provider=NULL; static int nProvider=0; @@ -1297,6 +1317,54 @@ static char * epnum(int prefix) { } +/* parse s="P:[\[daterange\]]nn[,v] description" from file *dat into *res */ +static void parse_P(char *s, char *dat, PLINE *res) { + int i; + + /* set default values */ + res->prefix = res->variant = UNKNOWN; + res->from_d = res->to_d = 0; + res->name = NULL; + res->booked = 0; + + /* parsing code taken from initRate */ + s+=2; + while (isblank(*s)) + s++; + if (*s == '[') + if (!parse2dates(dat, &s, &res->from_d, &res->to_d)) + return; + if (!isdigit(*s)) { + warning (dat, "Invalid provider-number '%c'", *s); + return; + } + res->prefix = strtol(s, &s ,10); + while (isblank(*s)) + s++; + if (*s == ',') { + s++; + while (isblank(*s)) + s++; + if (!isdigit(*s)) { + warning (dat, "Invalid variant '%c'", *s); + res->prefix = UNKNOWN; + return; + } + res->variant = strtol(s, &s, 10); + } + while (isblank(*s)) + s++; + res->name = *s ? strdup(s) : NULL; + + /* booked search also taken from initRate */ + for (i = 0; i < nBooked; i++) + if (Booked[i]._variant == res->variant && + Booked[i]._prefix == res->prefix) { + res->booked = 1; + break; + } +} + void parse_X(char *s, char *dat) { char *c; @@ -1443,18 +1511,19 @@ int initRate(char *conf, char *dat, char *dom, char **msg) char buffer[LENGTH], path[LENGTH], Version[LENGTH]=""; char *c, *s; int Comments=0; - int Areas=0, Zones=0, Hours=0; + int Areas=0, Zones=0, Hours=0, Skipped = 0; int where=DOMESTIC, prefix=UNKNOWN; int zone, zone1, zone2, day1, day2, hour1, hour2, freeze, delay; int *number, numbers; int i, n, t, u, v, z; int any; + PLINE prov; time_t from_d, to_d; #define MAX_INCLUDE 3 int lines[MAX_INCLUDE]; FILE *streams[MAX_INCLUDE]; char *files[MAX_INCLUDE]; - int include = 0; + int include = 0, skip = 0; initTelNum(); /* we need defnum */ mytld = getMynum()->tld; @@ -1525,6 +1594,12 @@ int initRate(char *conf, char *dat, char *dom, char **msg) parse_X(s, conf); break; + case 'Q': /* skipped providers list, see rate.conf(5) */ + i = add_skipped_provider(s+2, &c); + if (i) + warning(conf, "error in contents of Q: %s", c); + break; + default: warning(conf, "Unknown tag '%c'", *s); } @@ -1566,6 +1641,11 @@ again: continue; } + /* When skipping provider, ignore all lines until next P:-Tag, + * includes and exceptions are ignored too */ + if (skip && *s != 'P') + continue; + switch (*s) { case 'I': /* I:file include */ s+=2; while(isblank(*s)) s++; @@ -1608,7 +1688,20 @@ again: parse_X(s, dat); break; - case 'P': /* P:\[daterange\]nn[,v] Bezeichnung */ + case 'P': /* P:[\[daterange\]]nn[,v] description */ + /* At first parse the entire line in order to check for a skipped + * provider. In case of skipping, nothing further happens */ + parse_P(s, dat, &prov); + skip = 0; + if (prov.prefix != UNKNOWN && + is_skipped_provider(prov.prefix, prov.variant, prov.booked)) { + skip = 1; + Skipped++; + if (prov.name) + free(prov.name); + continue; /* try to read next line */ + } + /* the "end of provider" code below also occurs after the input loop */ if (zone!=UNKNOWN) { Provider[prefix].Zone[zone].Domestic = (where & DOMESTIC) == DOMESTIC; @@ -1622,7 +1715,8 @@ again: #endif line++; } - else if(nProvider && !Provider[prefix].nRedir) { /* silently ignore empty providers */ + /* silently ignore empty providers, may be also useful when skipping */ + else if(nProvider && !Provider[prefix].nRedir) { free_provider(prefix); nProvider--; } @@ -1637,44 +1731,24 @@ again: zone = UNKNOWN; where = DOMESTIC; - s+=2; while (isblank(*s)) s++; - from_d = to_d = 0; - if (*s == '[') - if (!parse2dates(dat, &s, &from_d, &to_d)) - continue; - if (!isdigit(*s)) { - warning (dat, "Invalid provider-number '%c'", *s); - prefix=UNKNOWN; - continue; + /* almost the old (before provider skipping) syntax error handling */ + if (prov.prefix == UNKNOWN) { + prefix = UNKNOWN; + continue; } - prefix = strtol(s, &s ,10); + + prefix = prov.prefix; Provider=realloc(Provider, (nProvider+1)*sizeof(PROVIDER)); memset(&Provider[nProvider], 0, sizeof(PROVIDER)); Provider[nProvider]._provider._prefix=prefix; prefix=nProvider; /* the internal prefix */ nProvider++; - Provider[prefix]._provider._variant=UNKNOWN; - Provider[prefix].FromDate = from_d; - Provider[prefix].ToDate = to_d; - while (isblank(*s)) s++; - if (*s == ',') { - s++; while (isblank(*s)) s++; - if (!isdigit(*s)) { - warning (dat, "Invalid variant '%c'", *s); - prefix=UNKNOWN; - continue; - } - v=strtol(s, &s, 10); - Provider[prefix]._provider._variant=v; - } - while (isblank(*s)) s++; - Provider[prefix].Name=*s?strdup(s):NULL; - for (i = 0; i < nBooked; i++) - if (Booked[i]._variant==Provider[prefix]._provider._variant && - Booked[i]._prefix==Provider[prefix]._provider._prefix) { - Provider[prefix].booked=1; - break; - } + Provider[prefix]._provider._variant = prov.variant; + Provider[prefix].FromDate = prov.from_d; + Provider[prefix].ToDate = prov.to_d; + Provider[prefix].Name = prov.name; + Provider[prefix].booked = prov.booked; + break; case 'B': /* B: VBN */ @@ -2170,8 +2244,8 @@ again: default: warning (dat, "Unknown tag '%c'", *s); break; - } - } + } /* /switch tag */ + } /* /while read from current ratefile sucessful */ fclose(stream); if (include) { free(files[include]); @@ -2213,13 +2287,18 @@ again: prsel_find_zone_area(); fix_redirz(dat); - if (msg) snprintf (message, LENGTH, - "Rates Version %s loaded [%d Providers, %d Zones, %d Areas, %d Services, %d Comments, %d eXceptions, %d Redirects, %d Rates from %s]", - Version, nProvider, Zones, Areas, nService, Comments, nPrsel, nRedir, Hours, dat); + if (msg) + snprintf(message, LENGTH, + "Rates Version %s loaded [%d Providers, %d skipped, %d Zones, " + "%d Areas, %d Services, %d Comments, %d eXceptions, %d Redirects, " + "%d Rates from %s]", + Version, nProvider, Skipped, Zones, + Areas, nService, Comments, nPrsel, nRedir, + Hours, dat); free(files[0]); return 0; -} +} /* /initRate */ char *getProvider (int prefix) { diff --git a/isdnlog/tools/rate.conf.5.in b/isdnlog/tools/rate.conf.5.in new file mode 100644 index 00000000..b2030968 --- /dev/null +++ b/isdnlog/tools/rate.conf.5.in @@ -0,0 +1,199 @@ +.\" $Id: rate.conf.5.in,v 1.1 2005/02/23 14:33:40 tobiasb Exp $ +.\" CHECKIN $Date: 2005/02/23 14:33:40 $ +.TH rate.conf 5 "@MANDATE_RATE_CONF@" "ISDN 4 Linux @I4LVERSION@" "isdnlog @ISDNLOG_VERSION@" + +.SH NAME +@I4LCONFDIR@/rate.conf \- rate and provider configuration + +.SH DESCRIPTION +isdnlog and related programs like isdnrep or isdnrate obtain the +information about telephone rates or fees from a rate-file. +In addition to the general data from the rate-file it is necessary +to provide information about the individual situation. +This is the purpose of the configuration file rate.conf. + +Words below consisting of uppercase letters like +.SB RATEFILE +refer to the so named setting in the general isdnlog configuration file +.IR @I4LCONFDIR@/@CONFFILE@ . + +.SS General Concepts + +The rate-file contains one or more providers for a country. +A provider covers an offer of a telephone company. +Usually there are now many telephone companies in a country and +most companies offer several different price lists. + +A provider is identified by provider number and provider variant or +sub number. The provider number, short +.IR pnum , +is commonly used for all offers of one company. +The provider variant, short +.IR var , +is used to number these offers starting from 0. +A specific provider is referenced as +.IB pnum , var +or +.IB pnum _ var +depending on the context. + +.SB VBN +contains the shared leading digits of the carrier selection prefixes. +The entire prefix for a provider is specified in the rate-file by the B: tag. +In Germany the carrier selection prefix begins with 010 followed by +two or three digits which make the +.I pnum +ranging from 10 to 199. +A mapping like this is not required but common. + +The overall format of rate.conf is similar to the rate-file, lines +starting with tags +.BR P: ", " X: ", or " Q: +may occur in any order and quantity. +(Of course, the resulting configuration should make sense.) + +.SS Provider Booking + +.BI P: pnum = var + +Mark the provider specified by +.IR pnum " and " var +as booked or active. +Only booked providers are taken into account when isdnlog computes +the connection costs. Booking also tells isdnlog the provider +variant to use if there are more than one. + +Beside computation of real connections booking also splits the providers +in two groups: the booked ones that are available at the specific subscriber +line at the not booked ones that are less important for price comparison. + +One provider in booked group is declared the default provider by setting +.SB PRESELECTED +to its +.IR pnum . +This provider is assumed to be used if a connection is made without a +carrier selection prefix and no exceptions matching. + +.SS Exceptions to Provider Selection + +.BI X: number = pnum +.br +.BI X: number = pnum z zone + +Connections to +.I number +will be assigned the booked provider with +.I pnum +as provider number regardless of a dialed provider selection prefix or the +.SB PRESELECTED +setting. +.I zone +if present +replaces the normal zone selection based on destination codes. +Exceptions can also be given in the rate-file. + +In rate.conf exceptions may become necessary if there different +preselected providers for local and distance calls for example or if +preselection does not apply generally, e.g. not for connections to special +numbers. + +.SS Provider Skipping + +At least for some countries there are universal rate-files distributed with +isdnlog or provided elsewhere. In this case it is desirable to keep the +rate-file unmodified so that updates require no further changes beyond +installing the new rate-file. If a rate-file aims to cover the telephone +market in an entire nation there will be always providers in it which are +not available or not suitable for a specific installation. +Such providers can be disabled by not booking them but they remain present +and may be displayed as overall cheapest provider or the like. + +Provider skipping completely ignores selected, so called skipped providers, +from the rate-file. To be more precise, the effect of skipped provider +could also be achieved by deleting its lines starting from its P: tag to +the last line before the P: tag of the next provider from the rate-file. + +Providers to skip can also be configured in the parameter file of isdnlog +using the syntax described below in a line starting with +.BR skipProv= " instead of " Q: . + +.BR Q: [ ! | ~ ]\fIlist\fP + +.TP +.I list +:= +.IR range [\fB;\fP list ] + +.TP +.I range +:= +.RI (\fB*\fP| prov | prov \fB-\fP|\fB-\fP prov | prov\fB-\fPprov )[\fB!\fP|\fB~\fP] + +.TP +.I prov +:= +.IR pnum [\fB,\fR var ] + +.P +Skipping applies to all providers that are matched by a given +.IR range. +If +.I var +is missing, all providers with +.I pnum +are skipped. + +.B * +matches all providers. + +Booked providers are not skipped unless +.B ! +is given at end of the +.I range +or in front of the entire list where it applies to whole line. + +The +.B ~ +can be given alternatively to +.BR !. +Providers that match such a +.I range +are not skipped under any circumstances. + +Space can occur anywhere in the line after +.BR Q:. + +Example: +.br +Q:*; 13,1~; 33-33,1~; 200-299!; 321-323! + +This skips all not booked providers except 13_1, 33_0, and 33_1. +Additionally all providers with a +.I pnum +between 200 and 299 or 321 and 323 are skipped. + +.SH FILES +.TP +.B @I4LCONFDIR@/rate.conf +This file. +.SB RATECONF +may be used to specify an alternative rate and provider configuration file. + +.TP +.BI @DATADIR@/rate- CC .dat +The rate-file for your country. Replace +.I CC +with your two letter country code, e.g. +.I de +for Germany. +.SB RATEFILE +defines the rate-file to use. + +.SH AUTHOR +Tobias Becker + +.SH SEE ALSO +.BR isdnlog (8) +.BR rate-files (5) +.BR isdn.conf (5) + diff --git a/isdnlog/tools/rate_skip.c b/isdnlog/tools/rate_skip.c new file mode 100644 index 00000000..630c9a5e --- /dev/null +++ b/isdnlog/tools/rate_skip.c @@ -0,0 +1,470 @@ +/* + * $Id: rate_skip.c,v 1.1 2005/02/23 14:33:40 tobiasb Exp $ + * + * rate database (Tarifdatenbank) -- skipping of providers + * + * Copyright 2005 Tobias Becker + * + * 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. + */ + +/* + * Skipped providers: The user may decide to completely ignore ("skip") + * a subset of providers defined in the rate file. This done by Q:<...> + * lines in rate.conf and/or a skipProv=<...> line in the parameter file. + * Skipping is either unconditional or takes place only if the provider + * is not explicit mentioned by a P:... line in rate.conf. + * + * The internal list of skipped providers is kept simple as it will be + * used only while reading the ratefile. No care is taken about + * overlapping entries and similar things. + * + * If the rate file uses redirs (R:...), disabling all non booked providers by + * the * wildcard entry will probably cause error during rate file loading like + * "rate-de.dat:@1938 Couldn't find provider 33_1 for redir #3 pnum 33_2 (7)". + * Because of this, a second list of entries becomes necessary. If a provider + * is matched by this "white" list, it is not skipped, regardless of any + * entries in the regular "black" list. + * + * Interface: + * + * int add_skipped_provider(char *line, char **msg); + * Parse line as list of skipped providers. The format is explained in + * rate.conf(5). The return value is 0 for proper input and 1 otherwise. + * If msg is not NULL, it will be used for an description in case of error. + * line is modified during parsing. + * + * int is_skipped_provider(int prov, int var, int booked); + * Returns 1 if the provider written as P:prov,var in the rate file is to + * be skipped or 0 otherwise. var may be UNKNOWN (-1). booked states + * whether there is a line P:prov=var in rate.conf or not. + * + * int clear_skipped_provider(void); + * This clears the internal list of skipped providers. Returns the number + * of freed list entries. + * + * int dump_skipped_provider(char *str, int len); + * Write the internal list of skipped providers to str with a maxium of len + * characters. The format of the output is the same as expected for input + * in add_skipped_provider. Returns the number of list entries or -1 in + * case of error. + */ + +#include +#include +#include +#include + +#include "rate_skip.h" + +#ifndef UNKNOWN /* tools.h is a little too heavy ... */ +#define UNKNOWN (-1) +#endif + +#define BLACK 0 /* indices for regular and */ +#define WHITE 1 /* exceptional list */ + +#define FLAG_ALL 0x1 /* matches all providers */ +#define FLAG_UNCOND 0x2 /* valid for booked providers too */ +#define FLAG_PROV0 0x4 /* value for prov[0] present */ +#define FLAG_PROV1 0x8 /* value for prov[1] present */ +#define FLAG_VAR0 0x10 /* value for var[0] present */ +#define FLAG_VAR1 0x20 /* value for var[1] present */ +#define FLAG_WHITE 0x40 /* value for entry in white list */ + +struct skip { + struct skip *next; /* next entry in list or NULL if last */ + int flags; /* details about kind of entry */ + int prov[2]; /* first [0] and last [1] provider number */ + int var[2]; /* same for variant number */ +}; + +static struct skip *list[2] = {NULL, NULL}; + +/* remove space and comment in string */ +static void strip (char *from) { + char *to = from; + while (*from && *from != '#') { + if (!isspace(*from)) + *to++ = *from; + ++from; + } + *to = '\0'; +} + + +int add_skipped_provider(char *line, char **msg) { + char *next, *p[2], *q; + int l, colour, uncond = 0, all_white = 0; + struct skip entry, *add, *last[2] = {NULL, NULL}; + static char errmsg[128]; + + *msg = errmsg; + **msg = '\0'; + + strip(line); + + /* whole line unconditional? */ + if (*line == '!') { + uncond = 1; + line++; + } + /* whole line for white list? */ + else if (*line == '~') { + all_white = 1; + line++; + } + + while (1) { + next = strchr(line, ';'); + if (next) + *next++ = '\0'; + + /* silently ignore empty ranges */ + if (!*line) { + if (next) { + line = next; + continue; + } + else + break; + } + + /* select default list */ + colour = all_white ? WHITE : BLACK; + + /* line points to a NUL-terminated range */ + entry.flags = uncond ? FLAG_UNCOND : 0; + + /* current entry unconditional? */ + l = strlen(line); + if ( *(line + l - 1) == '!' ) { + *(line + --l) = '\0'; + entry.flags |= FLAG_UNCOND; + } + /* current entry for white list? */ + else if ( *(line + l - 1) == '~' ) { + *(line + --l) = '\0'; + colour = WHITE; + } + if (colour == WHITE) { + entry.flags |= FLAG_WHITE; + /* either on white list or uncondional or none of both */ + entry.flags &= ~FLAG_UNCOND; + } + /* wildcard entry? */ + if (*line == '*') { + if (*(line + 1)) { + snprintf(*msg, sizeof errmsg, "unexpected characters after '*': %s", + line +1); + return 1; + } + else + entry.flags |= FLAG_ALL; + } + /* range entry: - | - | - | */ + else { + if (*line == '-') { + p[0] = NULL; + p[1] = line+1; + } + else if (*(line + l - 1) == '-') { + *(line + --l) = '\0'; + p[0] = line; + p[1] = NULL; + } + else if ( (q = strchr(line,'-')) ) { + *q = '\0'; + p[0] = line; + p[1] = q + 1; + } + else { + p[0] = p[1] = line; + } + for (l=0; l < 2; l++) { + if (!p[l]) + continue; + q = NULL; + entry.prov[l] = (int) strtol(p[l], &q, 10); + entry.flags |= l ? FLAG_PROV1 : FLAG_PROV0; + if (q && *q == ',') { + p[l] = q + 1; + q = NULL; + entry.var[l] = (int) strtol(p[l], &q, 10); + entry.flags |= l ? FLAG_VAR1 : FLAG_VAR0; + } + if (q && *q) { + snprintf(*msg, sizeof errmsg, + "unexpected characters for prov[,var]: %s", q); + return 1; + } + } + } /* /range entry */ + + /* entry is complete, save it to list */ + add = malloc(sizeof(struct skip)); + if (!add) { + snprintf(*msg, sizeof errmsg, "Out of memory!"); + return 1; + } + *add = entry; + /* wildcard entries are added on top of list */ + if (entry.flags & FLAG_ALL) { + add->next = list[colour]; + list[colour] = add; + } + else { + if (!last[colour] && list[colour]) { + last[colour] = list[colour]; + while (last[colour]->next) + last[colour] = last[colour]->next; + } + if (last[colour]) + last[colour]->next = add; + else + list[colour] = add; + add->next = NULL; + last[colour] = add; + } + + if (next) + line = next; + else + break; + } /* /loop over ranges: ; */ + + *msg = NULL; + return 0; +} + + +static int on_list(struct skip *testlist, int prov, int var, int booked) { + struct skip *test = testlist; + register int match, flags; + + while (test) { + /* compare entry with query */ + match = 1; + flags = test->flags; + if (!(flags & FLAG_ALL)) { + if (match && flags & FLAG_PROV0 && prov < test->prov[0]) + match = 0; + if (match && flags & FLAG_PROV1 && prov > test->prov[1]) + match = 0; + if (match && var != UNKNOWN) { + if (flags & FLAG_PROV0 && prov == test->prov[0] && + flags & FLAG_VAR0 && var < test->var[0]) + match = 0; + if (match && flags & FLAG_PROV1 && prov == test->prov[1] && + flags & FLAG_VAR1 && var > test->var[1]) + match = 0; + } + /* for UNKNOWN variant, entry must be valid for whole provider, + * not only for some variant of this provider + */ + if (match && var == UNKNOWN) { + if (flags & FLAG_PROV0 && prov == test->prov[0] && flags & FLAG_VAR0) + match = 0; + if (match && flags & FLAG_PROV1 && prov == test->prov[1] && + flags & FLAG_VAR1) + match = 0; + } + } /* /no wildcard entry */ + + if (match && ((test->flags & FLAG_UNCOND) == FLAG_UNCOND) >= booked) + return 1; + + test = test->next; + } + + return 0; +} + +int is_skipped_provider(int prov, int var, int booked) { + /* first look at white list, where there is no booked attribute */ + if (on_list(list[WHITE], prov, var, 0)) + return 0; + + return on_list(list[BLACK], prov, var, booked); +} + + +static int clear_list(struct skip **alist) { + struct skip *this, *next = *alist; + int n = 0; + + while ( (this=next) != NULL ) { + next = this->next; + free(this); + ++n; + } + + *alist = NULL; + + return n; +} + +int clear_skipped_provider(void) { + return clear_list(&list[WHITE]) + clear_list(&list[BLACK]); +} + + +int dump_skipped_provider(char *str, int len) { + int colour = BLACK; + struct skip *entry = list[colour]; + char *end = str + len, *p; + int n = 0, v; + char range[64]; + + if (len < 1) + return -1; + *str = '\0'; + + if (!entry && colour == BLACK) + entry = list[colour = WHITE]; + while (entry && str < end) { + + /* build string from range: * | [[,][-][[,]] */ + p = range; + *p = '\0'; + if (entry->flags & FLAG_PROV0) { + p += snprintf(p, 15, "%i", entry->prov[0]); + if (entry->flags & FLAG_VAR0) + p += snprintf(p, 15, ",%i", entry->var[0]); + } + /* write '-' separator when necessary: + * - not both provider numbers present + * - different provider numbers + * (both provider number present and identical and:) + * - both variants present and different + * - exact one variant present + */ + if ((entry->flags & (FLAG_PROV0|FLAG_PROV1)) != (FLAG_PROV0|FLAG_PROV1) || + entry->prov[0] != entry->prov[1] || + ( (v=(entry->flags & (FLAG_VAR0|FLAG_VAR1))) == (FLAG_VAR0|FLAG_VAR1) + && entry->var[0] != entry->var[1] ) || + v == FLAG_VAR0 || v== FLAG_VAR1) { + *p++ = '-'; + if (entry->flags & FLAG_PROV1) { + p += snprintf(p, 15, "%i", entry->prov[1]); + if (entry->flags & FLAG_VAR1) + p += snprintf(p, 15, ",%i", entry->var[1]); + } + } + if (entry->flags & FLAG_ALL) { + /* range should be "-" */ + range[0] = '*'; + range[1] = '\0'; + } + + str += snprintf(str, end-str, "%s%s%s%s", n ? ";" : "", range, + entry->flags & FLAG_WHITE ? "~" : "", + entry->flags & FLAG_UNCOND ? "!" : ""); + + ++n; + entry = entry->next; + if (!entry && colour == BLACK) + entry = list[colour = WHITE]; + } + + return (entry) ? -1 : n; +} + + +#ifdef STANDALONE +/* build it using + gcc -g -Wall -DSTANDALONE -o rate_skip rate_skip.c + */ + +int main (int argc, char *argv[]) { + char input[BUFSIZ], *p; + int ret, prov, var, booked; + + printf("Testing provider skipping, available commands:\n" + " a -- add string to list of skipped providers\n" + " c -- clear list of skipped providers\n" + " d -- dump list of skipped providers\n" + " i -- is ... on list?\n" + " q -- quit\n" + " s -- strip \n"); + + do { + printf("."); + fflush(stdout); + fgets(input, BUFSIZ, stdin); + input[BUFSIZ-1] = '\0'; + switch (*input) { + case 'a': ret = add_skipped_provider(input+1, &p); + if (ret) + printf("msg = %s\n", p); + printf("ret = %i (%s)\n", ret, ret ? "ERROR" : "OK"); + break; + + case 'c': ret = clear_skipped_provider(); + printf("ret = %i (number of freed entries)\n", ret); + break; + + case 'd': ret = dump_skipped_provider(input, BUFSIZ); + printf("out =>%s<\n", input); + printf("ret = %i (%s)\n", ret, + ret >= 0 ? "number dumped entries" : "ERROR"); + break; + + case 'i': p = input + 1; + prov = var = UNKNOWN; + booked = 0; + prov = (int) strtol(p, &p, 10); + if (p && *p) { + var = (int) strtol(p, &p, 10); + if (p && *p) + booked = (int) strtol(p, NULL, 10); + } + ret = is_skipped_provider(prov, var, booked); + printf("ret = %i (%s) for prov = %i, var = %i, booked = %i\n", + ret, ret ? "YES" : "NO", prov, var, booked); + break; + + case 'q': + break; + + case 's': strip(input+1); + printf("res =>%s<\n", input+1); + break; + + default: printf("Unknown command (q to quit)\n"); + break; + + } /* /switch */ + } while (*input != 'q'); + + return 0; +} +#endif /* STANDALONE */ + + +/* + * $Log: rate_skip.c,v $ + * Revision 1.1 2005/02/23 14:33:40 tobiasb + * New feature: provider skipping. + * Certain providers can be completely ignored (skipped) when loading the + * rate-file. The selection is done by Q: tags in rate.conf or by skipProv= + * in the parameter file. The syntax is explained in the new manual page + * rate.conf(5). Absurd settings for provider skipping may cause trouble. + * The version number will change to 4.70 in a few days after an update + * of the rate-de.dat. + * + */ + +/* vim:set ts=2: */ diff --git a/isdnlog/tools/rate_skip.h b/isdnlog/tools/rate_skip.h new file mode 100644 index 00000000..3b7dbac9 --- /dev/null +++ b/isdnlog/tools/rate_skip.h @@ -0,0 +1,46 @@ +/* + * $Id: rate_skip.h,v 1.1 2005/02/23 14:33:40 tobiasb Exp $ + * + * rate database (Tarifdatenbank) -- skipping of providers + * + * Copyright 2005 Tobias Becker + * + * 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 _RATE_SKIP_H_ +#define _RATE_SKIP_H_ + +int add_skipped_provider(char *line, char **msg); +int is_skipped_provider(int prov, int var, int booked); +int clear_skipped_provider(void); +int dump_skipped_provider(char *str, int len); + +#endif /* _RATE_SKIP_H_ */ + +/* + * $Log: rate_skip.h,v $ + * Revision 1.1 2005/02/23 14:33:40 tobiasb + * New feature: provider skipping. + * Certain providers can be completely ignored (skipped) when loading the + * rate-file. The selection is done by Q: tags in rate.conf or by skipProv= + * in the parameter file. The syntax is explained in the new manual page + * rate.conf(5). Absurd settings for provider skipping may cause trouble. + * The version number will change to 4.70 in a few days after an update + * of the rate-de.dat. + * + */ + +/* vim:set ts=2: */ diff --git a/isdnlog/tools/tools.h b/isdnlog/tools/tools.h index ac0aa28e..9561d7cf 100644 --- a/isdnlog/tools/tools.h +++ b/isdnlog/tools/tools.h @@ -1,4 +1,4 @@ -/* $Id: tools.h,v 1.63 2004/09/29 21:02:02 tobiasb Exp $ +/* $Id: tools.h,v 1.64 2005/02/23 14:33:40 tobiasb Exp $ * * ISDN accounting for isdn4linux. * @@ -20,6 +20,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: tools.h,v $ + * Revision 1.64 2005/02/23 14:33:40 tobiasb + * New feature: provider skipping. + * Certain providers can be completely ignored (skipped) when loading the + * rate-file. The selection is done by Q: tags in rate.conf or by skipProv= + * in the parameter file. The syntax is explained in the new manual page + * rate.conf(5). Absurd settings for provider skipping may cause trouble. + * The version number will change to 4.70 in a few days after an update + * of the rate-de.dat. + * * Revision 1.63 2004/09/29 21:02:02 tobiasb * Changed handling of multiple "calling party number" information elements. * The network provided number is now preferred in any case. The other @@ -910,6 +919,8 @@ #define CONF_ENT_PROVIDERCHANGE "PROVIDERCHANGE" #define CONF_ENT_CLOSEFDS "CLOSEFDS" #define CONF_ENT_IGNOREUPD "IGNOREUPD" +#define CONF_ENT_SKIPPROV "SKIPPROV" + /****************************************************************************/ /* Keywords for isdn.conf */