1999-04-30 19:07:28 +00:00
|
|
|
|
/* $Id: rate.c,v 1.12 1999/04/30 19:08:08 akool Exp $
|
1999-03-14 12:15:56 +00:00
|
|
|
|
*
|
|
|
|
|
* Tarifdatenbank
|
|
|
|
|
*
|
|
|
|
|
* Copyright 1995, 1999 by Andreas Kool (akool@isdn4linux.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: rate.c,v $
|
1999-04-30 19:07:28 +00:00
|
|
|
|
* Revision 1.12 1999/04/30 19:08:08 akool
|
|
|
|
|
* isdnlog Version 3.23
|
|
|
|
|
*
|
|
|
|
|
* - changed LCR probing duration from 181 seconds to 153 seconds
|
|
|
|
|
* - "rate-de.dat" filled with May, 1. rates
|
|
|
|
|
*
|
1999-04-29 19:02:56 +00:00
|
|
|
|
* Revision 1.11 1999/04/29 19:03:56 akool
|
|
|
|
|
* isdnlog Version 3.22
|
|
|
|
|
*
|
|
|
|
|
* - T-Online corrected
|
|
|
|
|
* - more online rates for rate-at.dat (Thanks to Leopold Toetsch <lt@toetsch.at>)
|
|
|
|
|
*
|
1999-04-26 22:11:33 +00:00
|
|
|
|
* Revision 1.10 1999/04/26 22:12:34 akool
|
|
|
|
|
* isdnlog Version 3.21
|
|
|
|
|
*
|
|
|
|
|
* - CVS headers added to the asn* files
|
|
|
|
|
* - repaired the "4.CI" message directly on CONNECT
|
|
|
|
|
* - HANGUP message extended (CI's and EH's shown)
|
|
|
|
|
* - reactivated the OVERLOAD message
|
|
|
|
|
* - rate-at.dat extended
|
|
|
|
|
* - fixes from Michael Reinelt
|
|
|
|
|
*
|
1999-04-20 20:31:48 +00:00
|
|
|
|
* Revision 1.9 1999/04/20 20:32:03 akool
|
|
|
|
|
* isdnlog Version 3.19
|
|
|
|
|
* patches from Michael Reinelt
|
|
|
|
|
*
|
1999-04-19 19:23:14 +00:00
|
|
|
|
* Revision 1.8 1999/04/19 19:25:36 akool
|
|
|
|
|
* isdnlog Version 3.18
|
|
|
|
|
*
|
|
|
|
|
* - countries-at.dat added
|
|
|
|
|
* - spelling corrections in "countries-de.dat" and "countries-us.dat"
|
|
|
|
|
* - LCR-function of isdnconf now accepts a duration (isdnconf -c .,duration)
|
|
|
|
|
* - "rate-at.dat" and "rate-de.dat" extended/fixed
|
|
|
|
|
* - holiday.c and rate.c fixed (many thanks to reinelt@eunet.at)
|
|
|
|
|
*
|
1999-04-16 14:39:07 +00:00
|
|
|
|
* Revision 1.7 1999/04/16 14:40:03 akool
|
|
|
|
|
* isdnlog Version 3.16
|
|
|
|
|
*
|
|
|
|
|
* - more syntax checks for "rate-xx.dat"
|
|
|
|
|
* - isdnrep fixed
|
|
|
|
|
*
|
1999-04-15 19:14:09 +00:00
|
|
|
|
* Revision 1.6 1999/04/15 19:15:17 akool
|
|
|
|
|
* isdnlog Version 3.15
|
|
|
|
|
*
|
|
|
|
|
* - reenable the least-cost-router functions of "isdnconf"
|
|
|
|
|
* try "isdnconf -c <areacode>" or even "isdnconf -c ."
|
|
|
|
|
* - README: "rate-xx.dat" documented
|
|
|
|
|
* - small fixes in processor.c and rate.c
|
|
|
|
|
* - "rate-de.dat" optimized
|
|
|
|
|
* - splitted countries.dat into countries-de.dat and countries-us.dat
|
|
|
|
|
*
|
1999-04-14 13:16:01 +00:00
|
|
|
|
* Revision 1.5 1999/04/14 13:17:24 akool
|
|
|
|
|
* isdnlog Version 3.14
|
|
|
|
|
*
|
|
|
|
|
* - "make install" now install's "rate-xx.dat", "rate.conf" and "ausland.dat"
|
|
|
|
|
* - "holiday-xx.dat" Version 1.1
|
|
|
|
|
* - many rate fixes (Thanks again to Michael Reinelt <reinelt@eunet.at>)
|
|
|
|
|
*
|
1999-04-10 16:34:57 +00:00
|
|
|
|
* Revision 1.4 1999/04/10 16:36:39 akool
|
|
|
|
|
* isdnlog Version 3.13
|
|
|
|
|
*
|
|
|
|
|
* WARNING: This is pre-ALPHA-dont-ever-use-Code!
|
|
|
|
|
* "tarif.dat" (aka "rate-xx.dat"): the next generation!
|
|
|
|
|
*
|
|
|
|
|
* You have to do the following to test this version:
|
|
|
|
|
* cp /usr/src/isdn4k-utils/isdnlog/holiday-de.dat /etc/isdn
|
|
|
|
|
* cp /usr/src/isdn4k-utils/isdnlog/rate-de.dat /usr/lib/isdn
|
|
|
|
|
* cp /usr/src/isdn4k-utils/isdnlog/samples/rate.conf.de /etc/isdn/rate.conf
|
|
|
|
|
*
|
|
|
|
|
* After that, add the following entries to your "/etc/isdn/isdn.conf" or
|
|
|
|
|
* "/etc/isdn/callerid.conf" file:
|
|
|
|
|
*
|
|
|
|
|
* [ISDNLOG]
|
|
|
|
|
* SPECIALNUMBERS = /usr/lib/isdn/sonderrufnummern.dat
|
|
|
|
|
* HOLIDAYS = /usr/lib/isdn/holiday-de.dat
|
|
|
|
|
* RATEFILE = /usr/lib/isdn/rate-de.dat
|
|
|
|
|
* RATECONF = /etc/isdn/rate.conf
|
|
|
|
|
*
|
|
|
|
|
* Please replace any "de" with your country code ("at", "ch", "nl")
|
|
|
|
|
*
|
|
|
|
|
* Good luck (Andreas Kool and Michael Reinelt)
|
|
|
|
|
*
|
1999-03-24 19:37:29 +00:00
|
|
|
|
* Revision 1.3 1999/03/24 19:39:00 akool
|
|
|
|
|
* - isdnlog Version 3.10
|
|
|
|
|
* - moved "sondernnummern.c" from isdnlog/ to tools/
|
|
|
|
|
* - "holiday.c" and "rate.c" integrated
|
|
|
|
|
* - NetCologne rates from Oliver Flimm <flimm@ph-cip.uni-koeln.de>
|
|
|
|
|
* - corrected UUnet and T-Online rates
|
|
|
|
|
*
|
1999-03-16 17:37:08 +00:00
|
|
|
|
* Revision 1.2 1999/03/16 17:38:09 akool
|
|
|
|
|
* - isdnlog Version 3.07
|
|
|
|
|
* - Michael Reinelt's patch as of 16Mar99 06:58:58
|
|
|
|
|
* - fix a fix from yesterday with sondernummern
|
|
|
|
|
* - ignore "" COLP/CLIP messages
|
|
|
|
|
* - dont show a LCR-Hint, if same price
|
|
|
|
|
*
|
1999-03-14 12:15:56 +00:00
|
|
|
|
* Revision 1.1 1999/03/14 12:16:42 akool
|
|
|
|
|
* - isdnlog Version 3.04
|
|
|
|
|
* - general cleanup
|
|
|
|
|
* - new layout for "rate-xx.dat" and "holiday-xx.dat" files from
|
|
|
|
|
* Michael Reinelt <reinelt@eunet.at>
|
|
|
|
|
* unused by now - it's a work-in-progress !
|
|
|
|
|
* - bugfix for Wolfgang Siefert <siefert@wiwi.uni-frankfurt.de>
|
|
|
|
|
* The Agfeo AS 40 (Software release 2.1b) uses AOC_AMOUNT, not AOC_UNITS
|
|
|
|
|
* - bugfix for Ralf G. R. Bergs <rabe@RWTH-Aachen.DE> - 0800/xxx numbers
|
|
|
|
|
* are free of charge ;-)
|
|
|
|
|
* - tarif.dat V 1.08 - new mobil-rates DTAG
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Schnittstelle zur Tarifdatenbank:
|
|
|
|
|
*
|
|
|
|
|
* void exitRate(void)
|
|
|
|
|
* deinitialisiert die Tarifdatenbank
|
|
|
|
|
*
|
1999-03-16 17:37:08 +00:00
|
|
|
|
* void initRate(char *conf, char *dat, char **msg)
|
|
|
|
|
* initialisiert die Tarifdatenbank
|
1999-03-14 12:15:56 +00:00
|
|
|
|
*
|
1999-04-10 16:34:57 +00:00
|
|
|
|
* char* getProvidername (int prefix)
|
|
|
|
|
* liefert den Namen des Providers oder NULL wenn unbekannt
|
|
|
|
|
*
|
|
|
|
|
* int getZone (int prefix, char *num)
|
|
|
|
|
* liefert die Zone, mit der die Rufnummer beim Provider prefix
|
|
|
|
|
* verrechnet wird, oder unknown
|
|
|
|
|
*
|
1999-03-16 17:37:08 +00:00
|
|
|
|
* int getRate(RATE*Rate, char **msg)
|
1999-03-24 19:37:29 +00:00
|
|
|
|
* liefert die Tarifberechnung in *Rate, UNKNOWN im
|
1999-03-16 17:37:08 +00:00
|
|
|
|
* Fehlerfall, *msg enth<EFBFBD>lt die Fehlerbeschreibung
|
1999-03-14 12:15:56 +00:00
|
|
|
|
*
|
1999-04-10 16:34:57 +00:00
|
|
|
|
* int getLeastCost (RATE *Rate, int skip)
|
1999-03-16 17:37:08 +00:00
|
|
|
|
* berechnet den billigsten Provider zu *Rate, R<EFBFBD>ckgabewert
|
|
|
|
|
* ist der Prefix des billigsten Providers oder UNKNOWN wenn
|
1999-04-10 16:34:57 +00:00
|
|
|
|
* *Rate bereits den billigsten Tarif enth<EFBFBD>lt. Der Provider
|
|
|
|
|
* 'skip' wird <EFBFBD>bersprungen (falls <EFBFBD>berlastet).
|
|
|
|
|
*
|
|
|
|
|
* int guessZone (RATE *Rate, int units)
|
|
|
|
|
* versucht die Zone zu erraten, wenn mit den Daten in Rate
|
|
|
|
|
* units Einheiten gemeldet wurden
|
1999-03-14 12:15:56 +00:00
|
|
|
|
*
|
1999-04-14 13:16:01 +00:00
|
|
|
|
* char *explainRate (RATE *Rate)
|
|
|
|
|
* liefert eine textuelle Begr<EFBFBD>ndung f<EFBFBD>r den Tarif in der Form
|
|
|
|
|
* "Provider, Zone, Wochentag, Zeit"
|
|
|
|
|
*
|
1999-03-14 12:15:56 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define _RATE_C_
|
|
|
|
|
|
1999-03-24 19:37:29 +00:00
|
|
|
|
#ifdef STANDALONE
|
1999-03-14 12:15:56 +00:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <time.h>
|
1999-03-16 17:37:08 +00:00
|
|
|
|
#include <unistd.h>
|
1999-04-16 14:39:07 +00:00
|
|
|
|
extern const char *basename (const char *name);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
#else
|
1999-03-24 19:37:29 +00:00
|
|
|
|
#include "isdnlog.h"
|
|
|
|
|
#include "tools.h"
|
1999-04-10 16:34:57 +00:00
|
|
|
|
#endif
|
1999-03-16 17:37:08 +00:00
|
|
|
|
#include "holiday.h"
|
1999-03-14 12:15:56 +00:00
|
|
|
|
#include "rate.h"
|
|
|
|
|
|
|
|
|
|
#define LENGTH 250 /* max length of lines in data file */
|
1999-04-16 14:39:07 +00:00
|
|
|
|
#ifdef STANDALONE
|
|
|
|
|
#define MAXPROVIDER 1000
|
1999-03-14 12:15:56 +00:00
|
|
|
|
#define UNKNOWN -1
|
1999-04-16 14:39:07 +00:00
|
|
|
|
#endif
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-04-14 13:16:01 +00:00
|
|
|
|
typedef struct _STACK {
|
|
|
|
|
int data;
|
|
|
|
|
struct _STACK *next;
|
|
|
|
|
} STACK;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
int Duration;
|
|
|
|
|
int Delay;
|
|
|
|
|
double Price;
|
|
|
|
|
} UNIT;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
char *Name;
|
|
|
|
|
bitfield Day;
|
|
|
|
|
bitfield Hour;
|
|
|
|
|
int nUnit;
|
|
|
|
|
UNIT *Unit;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
} HOUR;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-04-16 14:39:07 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
char *Code;
|
|
|
|
|
int Zone;
|
|
|
|
|
} AREA;
|
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
typedef struct {
|
|
|
|
|
int used;
|
|
|
|
|
char *Name;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
int nHour;
|
|
|
|
|
HOUR *Hour;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
} ZONE;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
int booked;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
int used;
|
|
|
|
|
char *Name;
|
|
|
|
|
int nZone;
|
|
|
|
|
ZONE *Zone;
|
1999-04-16 14:39:07 +00:00
|
|
|
|
int nArea;
|
|
|
|
|
AREA *Area;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
} PROVIDER;
|
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
static PROVIDER *Provider=NULL;
|
|
|
|
|
static int nProvider=0;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
static int line=0;
|
|
|
|
|
|
1999-04-16 14:39:07 +00:00
|
|
|
|
static void warning (char *file, char *fmt, ...)
|
1999-03-14 12:15:56 +00:00
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
char msg[BUFSIZ];
|
|
|
|
|
|
|
|
|
|
va_start (ap, fmt);
|
|
|
|
|
vsnprintf (msg, BUFSIZ, fmt, ap);
|
|
|
|
|
va_end (ap);
|
|
|
|
|
#ifdef STANDALONE
|
1999-04-16 14:39:07 +00:00
|
|
|
|
fprintf(stderr, "WARNING: %s line %3d: %s\n", basename(file), line, msg);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
#else
|
1999-04-16 14:39:07 +00:00
|
|
|
|
print_msg(PRT_NORMAL, "WARNING: %s line %3d: %s\n", basename(file), line, msg);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *strip (char *s)
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
|
|
|
|
|
1999-04-26 22:11:33 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
for (p=s; *p; p++)
|
|
|
|
|
if (*p=='#' || *p=='\n') {
|
|
|
|
|
*p='\0';
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
for (p--; p>s && isblank(*p); p--)
|
1999-03-14 12:15:56 +00:00
|
|
|
|
*p='\0';
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
static char* str2set (char **s)
|
|
|
|
|
{
|
|
|
|
|
static char buffer[BUFSIZ];
|
|
|
|
|
char *p=buffer;
|
|
|
|
|
|
|
|
|
|
while (**s) {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (**s==',')
|
1999-04-10 16:34:57 +00:00
|
|
|
|
break;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
else
|
|
|
|
|
*p++=*(*s)++;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
*p = '\0';
|
1999-04-10 16:34:57 +00:00
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-14 13:16:01 +00:00
|
|
|
|
static int strmatch (const char *pattern, const char *string)
|
|
|
|
|
{
|
1999-04-29 19:02:56 +00:00
|
|
|
|
int l, length=0;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
while (*pattern) {
|
1999-04-29 19:02:56 +00:00
|
|
|
|
if (*pattern=='*') {
|
|
|
|
|
pattern+=strlen(pattern)-1;
|
|
|
|
|
l=strlen(string);
|
|
|
|
|
string+=l-1;
|
|
|
|
|
length+=l;
|
|
|
|
|
while (*pattern!='*') {
|
|
|
|
|
if (*pattern!=*string && *pattern!='?')
|
|
|
|
|
return 0;
|
|
|
|
|
pattern--;
|
|
|
|
|
string--;
|
|
|
|
|
}
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
if ((*pattern!=*string && *pattern!='?') || *string=='\0')
|
1999-04-14 13:16:01 +00:00
|
|
|
|
return 0;
|
|
|
|
|
pattern++;
|
|
|
|
|
string++;
|
1999-04-16 14:39:07 +00:00
|
|
|
|
length++;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
}
|
1999-04-16 14:39:07 +00:00
|
|
|
|
return length;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void push (STACK **stack, int data)
|
|
|
|
|
{
|
|
|
|
|
STACK *new=malloc(sizeof(STACK));
|
|
|
|
|
new->data=data;
|
|
|
|
|
new->next=*stack;
|
|
|
|
|
*stack=new;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int pop (STACK **stack)
|
|
|
|
|
{
|
|
|
|
|
STACK *old=*stack;
|
|
|
|
|
int data;
|
|
|
|
|
|
|
|
|
|
if (!old)
|
|
|
|
|
return UNKNOWN;
|
|
|
|
|
data=old->data;
|
|
|
|
|
*stack=old->next;
|
|
|
|
|
return (data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void empty (STACK **stack)
|
|
|
|
|
{
|
|
|
|
|
STACK *old;
|
|
|
|
|
while (*stack) {
|
|
|
|
|
old=*stack;
|
|
|
|
|
*stack=old->next;
|
|
|
|
|
free(old);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-16 14:39:07 +00:00
|
|
|
|
static int byArea(const void *a, const void *b)
|
|
|
|
|
{
|
|
|
|
|
return strcmp (((AREA*)a)->Code, ((AREA*)b)->Code);
|
|
|
|
|
}
|
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
void exitRate(void)
|
|
|
|
|
{
|
|
|
|
|
int i, j, k;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
for (i=0; i<nProvider; i++) {
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (Provider[i].used) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
for (j=0; j<Provider[i].nZone; j++) {
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (Provider[i].Zone[j].used) {
|
|
|
|
|
Provider[i].Zone[j].used=0;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (Provider[i].Zone[j].Name) free (Provider[i].Zone[j].Name);
|
1999-03-16 17:37:08 +00:00
|
|
|
|
for (k=0; k<Provider[i].Zone[j].nHour; k++) {
|
|
|
|
|
if (Provider[i].Zone[j].Hour[k].Name) free (Provider[i].Zone[j].Hour[k].Name);
|
|
|
|
|
if (Provider[i].Zone[j].Hour[k].Unit) free (Provider[i].Zone[j].Hour[k].Unit);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
1999-03-24 19:37:29 +00:00
|
|
|
|
if (Provider[i].Zone[j].Hour) free (Provider[i].Zone[j].Hour);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
1999-04-16 14:39:07 +00:00
|
|
|
|
}
|
1999-03-24 19:37:29 +00:00
|
|
|
|
if(Provider[i].Zone) free (Provider[i].Zone);
|
1999-04-16 14:39:07 +00:00
|
|
|
|
for (j=0; j<Provider[i].nArea; j++)
|
|
|
|
|
if (Provider[i].Area[j].Code) free (Provider[i].Area[j].Code);
|
|
|
|
|
if(Provider[i].Area) free (Provider[i].Area);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (Provider[i].Name) free (Provider[i].Name);
|
|
|
|
|
Provider[i].used=0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
int initRate(char *conf, char *dat, char **msg)
|
1999-03-14 12:15:56 +00:00
|
|
|
|
{
|
1999-04-16 14:39:07 +00:00
|
|
|
|
static char message[LENGTH];
|
1999-03-14 12:15:56 +00:00
|
|
|
|
FILE *stream;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
STACK *zones=NULL, *zp;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
bitfield day, hour;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
double price, divider, duration;
|
1999-04-16 14:39:07 +00:00
|
|
|
|
char buffer[LENGTH], Version[LENGTH]="<unknown>";
|
1999-04-14 13:16:01 +00:00
|
|
|
|
char *a, *c, *s;
|
1999-04-16 14:39:07 +00:00
|
|
|
|
int booked[MAXPROVIDER], variant[MAXPROVIDER];
|
|
|
|
|
int Providers=0, Areas=0, Zones=0, Hours=0;
|
|
|
|
|
int ignore=0, prefix=UNKNOWN;
|
|
|
|
|
int zone1, zone2, day1, day2, hour1, hour2, delay;
|
|
|
|
|
int i, t, u, v, z;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (msg)
|
|
|
|
|
*(*msg=message)='\0';
|
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
for (i=0; i<MAXPROVIDER; i++) {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
booked[i]=0;
|
|
|
|
|
variant[i]=UNKNOWN;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (conf && *conf) {
|
|
|
|
|
if ((stream=fopen(conf,"r"))==NULL) {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (msg) snprintf (message, LENGTH, "Error: could not load rate configuration from %s: %s",
|
1999-04-10 16:34:57 +00:00
|
|
|
|
conf, strerror(errno));
|
|
|
|
|
return -1;
|
1999-04-19 19:23:14 +00:00
|
|
|
|
}
|
|
|
|
|
line=0;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
while ((s=fgets(buffer,LENGTH,stream))!=NULL) {
|
|
|
|
|
line++;
|
|
|
|
|
if (*(s=strip(s))=='\0')
|
|
|
|
|
continue;
|
|
|
|
|
if (s[1]!=':') {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (conf, "expected ':', got '%s'!", s+1);;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
switch (*s) {
|
|
|
|
|
case 'P':
|
1999-04-20 20:31:48 +00:00
|
|
|
|
s+=2;
|
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
|
|
|
|
warning (conf, "Invalid provider-number %s", s);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
prefix = strtol(s, &s ,10);
|
|
|
|
|
if (prefix >= MAXPROVIDER) {
|
|
|
|
|
warning (conf, "Invalid provider-number %d", prefix);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
booked[prefix]=1;
|
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (*s == '=') {
|
|
|
|
|
s++;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
1999-04-20 20:31:48 +00:00
|
|
|
|
warning (conf, "Invalid variant %s", s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-20 20:31:48 +00:00
|
|
|
|
if ((v=strtol(s, &s, 10))<1) {
|
|
|
|
|
warning (conf, "Invalid variant %s", s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-20 20:31:48 +00:00
|
|
|
|
variant[prefix]=v;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
1999-04-20 20:31:48 +00:00
|
|
|
|
if (*s) {
|
|
|
|
|
warning (conf, "trailing junk '%s' ignored.", s);
|
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
1999-04-29 19:02:56 +00:00
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
default:
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning(conf, "Unknown tag '%c'", *s);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fclose (stream);
|
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (!dat || !*dat) {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (msg) snprintf (message, LENGTH, "Warning: no rate database specified!",
|
1999-04-10 16:34:57 +00:00
|
|
|
|
conf, strerror(errno));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if ((stream=fopen(dat,"r"))==NULL) {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (msg) snprintf (message, LENGTH, "Error: could not load rate database from %s: %s",
|
1999-04-10 16:34:57 +00:00
|
|
|
|
dat, strerror(errno));
|
1999-03-14 12:15:56 +00:00
|
|
|
|
return -1;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
line=0;
|
|
|
|
|
prefix=UNKNOWN;
|
|
|
|
|
while ((s=fgets(buffer,LENGTH,stream))!=NULL) {
|
|
|
|
|
line++;
|
|
|
|
|
if (*(s=strip(s))=='\0')
|
|
|
|
|
continue;
|
|
|
|
|
if (s[1]!=':') {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "expected ':', got '%s'!", s+1);;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
switch (*s) {
|
1999-04-10 16:34:57 +00:00
|
|
|
|
|
|
|
|
|
case 'P': /* P:nn[,v] Bezeichnung */
|
1999-04-14 13:16:01 +00:00
|
|
|
|
v = UNKNOWN;
|
1999-04-19 19:23:14 +00:00
|
|
|
|
ignore = 1;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
empty(&zones);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
s+=2; while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Invalid provider-number '%c'", *s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
continue;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
prefix = strtol(s, &s ,10);
|
|
|
|
|
if (prefix >= MAXPROVIDER) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Invalid provider-number %d", prefix);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (*s == ',') {
|
|
|
|
|
s++; while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Invalid variant '%c'", *s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-19 19:23:14 +00:00
|
|
|
|
v=strtol(s, &s, 10);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
1999-04-19 19:23:14 +00:00
|
|
|
|
/* Fixme: is this correct? */
|
|
|
|
|
/* if ((variant[prefix]!=UNKNOWN) && (v!=UNKNOWN) && (variant[prefix]!=v)) { */
|
|
|
|
|
if (variant[prefix]==v) {
|
|
|
|
|
ignore = 0;
|
|
|
|
|
} else {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
v = UNKNOWN;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (prefix>=nProvider) {
|
|
|
|
|
Provider=realloc(Provider, (prefix+1)*sizeof(PROVIDER));
|
|
|
|
|
for (i=nProvider; i<=prefix; i++)
|
|
|
|
|
Provider[i].used=0;
|
|
|
|
|
nProvider=prefix+1;
|
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (Provider[prefix].used++) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Duplicate entry for provider %d (%s)", prefix, Provider[prefix].Name);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (Provider[prefix].Name) free(Provider[prefix].Name);
|
1999-03-24 19:37:29 +00:00
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
Provider[prefix].Name=*s?strdup(s):NULL;
|
|
|
|
|
Provider[prefix].booked=booked[prefix];
|
1999-03-14 12:15:56 +00:00
|
|
|
|
Provider[prefix].nZone=0;
|
|
|
|
|
Provider[prefix].Zone=NULL;
|
1999-04-16 14:39:07 +00:00
|
|
|
|
Provider[prefix].nArea=0;
|
|
|
|
|
Provider[prefix].Area=NULL;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
Providers++;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
case 'G': /* P:tt.mm.jjjj Hour gueltig ab */
|
1999-03-24 19:37:29 +00:00
|
|
|
|
if (ignore) continue;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
case 'C': /* C:Comment */
|
1999-03-24 19:37:29 +00:00
|
|
|
|
if (ignore) continue;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
|
1999-04-14 13:16:01 +00:00
|
|
|
|
case 'Z': /* Z:n[-n][,n] Bezeichnung */
|
1999-03-24 19:37:29 +00:00
|
|
|
|
if (ignore) continue;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (prefix == UNKNOWN) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Unexpected tag '%c'", *s);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
s+=2;
|
|
|
|
|
empty(&zones);
|
|
|
|
|
while (1) {
|
|
|
|
|
while (isblank(*s)) s++;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
if (!isdigit(*s)) {
|
|
|
|
|
warning (dat, "Invalid zone '%c'", *s);
|
1999-04-14 13:16:01 +00:00
|
|
|
|
empty(&zones);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
zone1=strtol(s,&s,10);
|
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (*s=='-') {
|
|
|
|
|
s++; while (isblank(*s)) s++;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
if (!isdigit(*s)) {
|
|
|
|
|
warning (dat, "Invalid zone '%c'", *s);
|
1999-04-14 13:16:01 +00:00
|
|
|
|
empty(&zones);
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-04-15 19:14:09 +00:00
|
|
|
|
zone2=strtol(s,&s,10);
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (zone2<zone1) {
|
|
|
|
|
i=zone2; zone2=zone1; zone1=i;
|
|
|
|
|
}
|
|
|
|
|
for (i=zone1; i<=zone2; i++)
|
|
|
|
|
push (&zones, i);
|
|
|
|
|
} else {
|
|
|
|
|
push (&zones, zone1);
|
|
|
|
|
}
|
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (*s==',') {
|
|
|
|
|
s++;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!zones)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
zp=zones;
|
|
|
|
|
while (zp) {
|
|
|
|
|
z=pop(&zp);
|
|
|
|
|
if (z>=Provider[prefix].nZone) {
|
|
|
|
|
Provider[prefix].Zone=realloc(Provider[prefix].Zone, (z+1)*sizeof(ZONE));
|
|
|
|
|
for (i=Provider[prefix].nZone; i<z; i++)
|
1999-04-20 20:31:48 +00:00
|
|
|
|
Provider[prefix].Zone[i].used=0;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
Provider[prefix].nZone = z+1;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
Provider[prefix].Zone[z].used=1;
|
|
|
|
|
Provider[prefix].Zone[z].Name=*s?strdup(s):NULL;
|
|
|
|
|
Provider[prefix].Zone[z].nHour=0;
|
|
|
|
|
Provider[prefix].Zone[z].Hour=NULL;
|
1999-04-16 14:39:07 +00:00
|
|
|
|
Zones++;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
case 'A': /* A:areacode[,areacode...] */
|
|
|
|
|
if (ignore) continue;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (!zones) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Unexpected tag '%c'", *s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s+=2;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
a=s;
|
|
|
|
|
while(1) {
|
|
|
|
|
if (*(c=strip(str2set(&a)))) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
for (i=0; i<Provider[prefix].nArea; i++) {
|
|
|
|
|
if (strcmp (Provider[prefix].Area[i].Code,c)==0) {
|
|
|
|
|
warning (dat, "Duplicate Area %s", c);
|
|
|
|
|
c=NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (c) {
|
|
|
|
|
Provider[prefix].Area=realloc(Provider[prefix].Area, (Provider[prefix].nArea+1)*sizeof(AREA));
|
|
|
|
|
Provider[prefix].Area[Provider[prefix].nArea].Code=strdup(c);
|
|
|
|
|
Provider[prefix].Area[Provider[prefix].nArea].Zone=zones->data; /* ugly: use first zone */
|
|
|
|
|
Provider[prefix].nArea++;
|
|
|
|
|
Areas++;
|
|
|
|
|
}
|
1999-04-20 20:31:48 +00:00
|
|
|
|
} else {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Ignoring empty areacode");
|
1999-04-14 13:16:01 +00:00
|
|
|
|
}
|
1999-04-20 20:31:48 +00:00
|
|
|
|
if (*a==',') {
|
|
|
|
|
a++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
s=a;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
break;
|
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
case 'T': /* T:d-d/h-h=p/s:t[=]Bezeichnung */
|
1999-03-24 19:37:29 +00:00
|
|
|
|
if (ignore) continue;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (!zones) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Unexpected tag '%c'", *s);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
s+=2;
|
|
|
|
|
day=0;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
hour=0;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
while (1) {
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (*s=='*') { /* jeder Tag */
|
1999-04-14 13:16:01 +00:00
|
|
|
|
day |= 1<<EVERYDAY;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
s++;
|
|
|
|
|
} else if (*s=='W') { /* Wochentag 1-5 */
|
1999-04-14 13:16:01 +00:00
|
|
|
|
day |= 1<<WORKDAY;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
s++;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
} else if (*s=='E') { /* weekEnd */
|
1999-04-14 13:16:01 +00:00
|
|
|
|
day |= 1<<WEEKEND;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
s++;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
} else if (*s=='H') { /* Holiday */
|
1999-04-14 13:16:01 +00:00
|
|
|
|
day |= 1<<HOLIDAY;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
s++;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
} else if (isdigit(*s)) { /* 1 oder 1-5 */
|
1999-03-14 12:15:56 +00:00
|
|
|
|
day1=strtol(s,&s,10);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (*s=='-') {
|
|
|
|
|
s++; while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid day '%s'", s);
|
1999-04-14 13:16:01 +00:00
|
|
|
|
day=0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
day2=strtol(s,&s,10);
|
|
|
|
|
} else day2=day1;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (day1<1 || day1>7) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid day %d", day1);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
day=0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (day2<1 || day2>7) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid day %d", day2);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
day=0;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
break;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (day2<day1) {
|
|
|
|
|
i=day2; day2=day1; day1=i;
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
for (i=day1; i<=day2; i++)
|
1999-04-14 13:16:01 +00:00
|
|
|
|
day|=(1<<i);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
} else {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid day '%c'", *s);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
day=0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (*s==',') {
|
|
|
|
|
s++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
break;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
1999-03-24 19:37:29 +00:00
|
|
|
|
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (!day)
|
|
|
|
|
break;
|
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (*s!='/') {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "expected '/', got '%s'!", s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
day=0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s++;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
while (1) {
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (*s=='*') { /* jede Stunde */
|
|
|
|
|
hour |= 0xffffff; /* alles 1er */
|
|
|
|
|
s++;
|
|
|
|
|
} else if (isdigit(*s)) { /* 8-12 oder 1,5 */
|
|
|
|
|
hour1=strtol(s,&s,10);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (*s=='-') hour2=strtol(s+1,&s,10);
|
|
|
|
|
else hour2=hour1+1;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (hour1<0 || hour1>24) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid hour %d", hour1);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
hour=0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (hour2<0 || hour2>24) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid hour %d", hour2);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
hour=0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
if (hour2>=hour1)
|
|
|
|
|
for (i=hour1; i<hour2; i++) hour|=(1<<i);
|
|
|
|
|
else {
|
|
|
|
|
for (i=hour1; i<24; i++) hour|=(1<<i);
|
|
|
|
|
for (i=0; i<hour2; i++) hour|=(1<<i);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid hour '%c'", *s);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
hour=0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (*s==',') {
|
|
|
|
|
s++;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (!hour)
|
|
|
|
|
break;
|
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (*s!='=') {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "expected '=', got '%s'!", s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
hour=0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-14 13:16:01 +00:00
|
|
|
|
zp=zones;
|
|
|
|
|
while (zp) {
|
|
|
|
|
z=pop(&zp);
|
|
|
|
|
t=Provider[prefix].Zone[z].nHour++;
|
|
|
|
|
Provider[prefix].Zone[z].Hour = realloc(Provider[prefix].Zone[z].Hour, (t+1)*sizeof(HOUR));
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Name=NULL;
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Day=day;
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Hour=hour;
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].nUnit=0;
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Unit=NULL;
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
|
|
|
|
|
s++;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
while (1) {
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid price '%c'", *s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
price=strtod(s,&s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
divider=0;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
duration=1;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (*s=='(') {
|
|
|
|
|
s++; while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "invalid divider '%c'", *s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
divider=strtod(s,&s);
|
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
if (*s!=')') {
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "expected ')', got '%s'!", s);
|
1999-04-10 16:34:57 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s++; while (isblank(*s)) s++;
|
|
|
|
|
}
|
1999-04-20 20:31:48 +00:00
|
|
|
|
while (1) {
|
|
|
|
|
if (*s=='/') {
|
|
|
|
|
s++; while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
|
|
|
|
warning (dat, "invalid duration '%c'", *s);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
duration=strtod(s,&s);
|
|
|
|
|
while (isblank(*s)) s++;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
1999-04-20 20:31:48 +00:00
|
|
|
|
if (*s==':') {
|
|
|
|
|
s++; while (isblank(*s)) s++;
|
|
|
|
|
if (!isdigit(*s)) {
|
|
|
|
|
warning (dat, "invalid delay '%c'", *s);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
delay=strtol(s,&s,10);
|
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
} else {
|
|
|
|
|
delay=UNKNOWN;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
1999-04-20 20:31:48 +00:00
|
|
|
|
if ((*s==',' || *s=='/') && delay==UNKNOWN)
|
|
|
|
|
delay=duration;
|
|
|
|
|
if (*s!=',' && *s!='/' && delay!=UNKNOWN) {
|
|
|
|
|
warning(dat, "last rate must not have a delay, will be ignored!");
|
|
|
|
|
delay=UNKNOWN;
|
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
|
1999-04-20 20:31:48 +00:00
|
|
|
|
zp=zones;
|
|
|
|
|
while (zp) {
|
|
|
|
|
z=pop(&zp);
|
|
|
|
|
t=Provider[prefix].Zone[z].nHour-1;
|
|
|
|
|
u=Provider[prefix].Zone[z].Hour[t].nUnit++;
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Unit=realloc(Provider[prefix].Zone[z].Hour[t].Unit, (u+1)*sizeof(UNIT));
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Unit[u].Duration=duration;
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Unit[u].Delay=delay;
|
1999-04-29 19:02:56 +00:00
|
|
|
|
if (duration!=0.0 && divider!=0.0)
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Unit[u].Price=price*duration/divider;
|
|
|
|
|
else
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Unit[u].Price=price;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
}
|
|
|
|
|
if (*s=='/') {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
Hours++;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
break;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
if (*s==',') {
|
|
|
|
|
s++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
break;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
while (isblank(*s)) s++;
|
|
|
|
|
zp=zones;
|
|
|
|
|
while (zp) {
|
|
|
|
|
z=pop(&zp);
|
|
|
|
|
t=Provider[prefix].Zone[z].nHour-1;
|
|
|
|
|
Provider[prefix].Zone[z].Hour[t].Name=*s?strdup(s):NULL;
|
1999-04-29 19:02:56 +00:00
|
|
|
|
Hours++;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
case 'V': /* V:xxx Version der Datenbank */
|
1999-03-14 12:15:56 +00:00
|
|
|
|
strcpy(Version, s+2);
|
|
|
|
|
break;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
default:
|
1999-04-16 14:39:07 +00:00
|
|
|
|
warning (dat, "Unknown tag '%c'", *s);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fclose(stream);
|
1999-04-14 13:16:01 +00:00
|
|
|
|
empty(&zones);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-04-16 14:39:07 +00:00
|
|
|
|
for (i=0; i<nProvider; i++) {
|
|
|
|
|
if (Provider[i].used) {
|
|
|
|
|
qsort(Provider[i].Area, Provider[i].nArea, sizeof(AREA), byArea);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (msg) snprintf (message, LENGTH, "Rate Version %s loaded [%d Providers, %d Zones, %d Areas, %d Rates from %s]",
|
|
|
|
|
Version, Providers, Zones, Areas, Hours, dat);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
return 0;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
char *getProvidername (int prefix)
|
|
|
|
|
{
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (prefix<0 || prefix>=nProvider || !Provider[prefix].used) {
|
1999-04-10 16:34:57 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return Provider[prefix].Name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int getZone (int prefix, char *number)
|
|
|
|
|
{
|
1999-04-16 14:39:07 +00:00
|
|
|
|
int a, l, m, max, z;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (prefix<0 || prefix>=nProvider || !Provider[prefix].used) {
|
1999-04-10 16:34:57 +00:00
|
|
|
|
return UNKNOWN;
|
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
|
1999-04-16 14:39:07 +00:00
|
|
|
|
l=0;
|
|
|
|
|
max=0;
|
|
|
|
|
z=UNKNOWN;
|
|
|
|
|
for (a=0; a<Provider[prefix].nArea; a++) {
|
|
|
|
|
m=strmatch(Provider[prefix].Area[a].Code, number);
|
|
|
|
|
if (m>max) {
|
|
|
|
|
z=Provider[prefix].Area[a].Zone;
|
|
|
|
|
max=m;
|
1999-04-29 19:02:56 +00:00
|
|
|
|
}
|
1999-04-16 14:39:07 +00:00
|
|
|
|
l=m;
|
1999-04-20 20:31:48 +00:00
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
|
|
|
|
|
return z;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
int getRate(RATE *Rate, char **msg)
|
1999-03-14 12:15:56 +00:00
|
|
|
|
{
|
1999-03-16 17:37:08 +00:00
|
|
|
|
static char message[LENGTH];
|
1999-04-14 13:16:01 +00:00
|
|
|
|
bitfield hourBits;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
ZONE *Zone;
|
|
|
|
|
HOUR *Hour;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
UNIT *Unit;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
int prefix, zone, hour, i;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
time_t now, run, end;
|
|
|
|
|
struct tm tm;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (msg)
|
|
|
|
|
*(*msg=message)='\0';
|
|
|
|
|
|
1999-03-24 19:37:29 +00:00
|
|
|
|
if (!Rate)
|
1999-03-16 17:37:08 +00:00
|
|
|
|
return UNKNOWN;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-03-24 19:37:29 +00:00
|
|
|
|
prefix=Rate->prefix;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (prefix<0 || prefix>=nProvider || !Provider[prefix].used) {
|
|
|
|
|
if (msg) snprintf(message, LENGTH, "unknown provider %d", prefix);
|
1999-03-16 17:37:08 +00:00
|
|
|
|
return UNKNOWN;
|
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
zone=Rate->zone;
|
|
|
|
|
if (zone<1 || zone>=Provider[prefix].nZone || !Provider[prefix].Zone[zone].used) {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (msg) snprintf(message, LENGTH, "unknown zone %d", zone);
|
1999-03-16 17:37:08 +00:00
|
|
|
|
return UNKNOWN;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
1999-03-16 17:37:08 +00:00
|
|
|
|
|
|
|
|
|
Zone=&Provider[prefix].Zone[zone];
|
|
|
|
|
Rate->Provider=Provider[prefix].Name;
|
|
|
|
|
Rate->Zone=Zone->Name;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
Rate->Basic=0;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
Rate->Price=0;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
Rate->Duration=0;
|
|
|
|
|
Rate->Units=0;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
Rate->Charge=0;
|
|
|
|
|
Rate->Rest=0;
|
|
|
|
|
|
|
|
|
|
Hour=NULL;
|
|
|
|
|
Unit=NULL;
|
|
|
|
|
hour=UNKNOWN; /* Stundenwechsel erzwingen */
|
1999-04-10 16:34:57 +00:00
|
|
|
|
now=Rate->start;
|
|
|
|
|
end=Rate->now;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
Rate->Time=end-now;
|
|
|
|
|
run=0;
|
|
|
|
|
while (end>=now) {
|
|
|
|
|
tm=*localtime(&now);
|
|
|
|
|
if (hour!=tm.tm_hour) { /* Neuberechnung bei Stundenwechsel */
|
|
|
|
|
hour=tm.tm_hour;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
hourBits=1<<tm.tm_hour;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
for (i=0; i<Zone->nHour; i++) {
|
|
|
|
|
Hour = &Zone->Hour[i];
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if ((Hour->Hour & hourBits) && isDay(&tm, Hour->Day, &Rate->Day))
|
1999-03-16 17:37:08 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (i==Zone->nHour) {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (msg) snprintf(message, LENGTH,
|
1999-03-24 19:37:29 +00:00
|
|
|
|
"no rate found for provider=%d zone=%d day=%d hour=%d",
|
1999-04-14 13:16:01 +00:00
|
|
|
|
prefix, zone, tm.tm_wday+1, tm.tm_hour);
|
1999-03-16 17:37:08 +00:00
|
|
|
|
return UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
Rate->Hour=Hour->Name;
|
|
|
|
|
Unit=Hour->Unit;
|
|
|
|
|
}
|
1999-03-24 19:37:29 +00:00
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
Rate->Charge+=Unit->Price;
|
1999-04-29 19:02:56 +00:00
|
|
|
|
Rate->Duration=Unit->Duration;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
Rate->Rest+=Unit->Duration;
|
|
|
|
|
now+=Unit->Duration;
|
|
|
|
|
run+=Unit->Duration;
|
1999-04-14 13:16:01 +00:00
|
|
|
|
if (run==0 && Unit->Duration==0)
|
|
|
|
|
Rate->Basic=Unit->Price;
|
1999-04-29 19:02:56 +00:00
|
|
|
|
else
|
|
|
|
|
Rate->Price=Unit->Price;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
if (Unit->Duration>0)
|
1999-03-16 17:37:08 +00:00
|
|
|
|
Rate->Units++;
|
|
|
|
|
if (Unit->Delay!=UNKNOWN && Unit->Delay<=run)
|
1999-03-14 12:15:56 +00:00
|
|
|
|
Unit++;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
Rate->Rest-=Rate->Time;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
int getLeastCost (RATE *Rate, int skip)
|
1999-03-16 17:37:08 +00:00
|
|
|
|
{
|
1999-03-24 19:37:29 +00:00
|
|
|
|
int i, min;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
RATE Curr, Least;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
Least=*Rate;
|
|
|
|
|
Least.Charge=1e9;
|
|
|
|
|
if (Least.start==Least.now)
|
1999-04-30 19:07:28 +00:00
|
|
|
|
Least.now+=TESTDURATION;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
Curr=Least;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
min=UNKNOWN;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
for (i=0; i<nProvider; i++) {
|
|
|
|
|
if (i==skip)
|
|
|
|
|
continue;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
Curr.prefix=i;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (getRate(&Curr, NULL)!=UNKNOWN && Curr.Charge<Least.Charge) {
|
1999-03-24 19:37:29 +00:00
|
|
|
|
min=i;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
Least=Curr;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-04-10 16:34:57 +00:00
|
|
|
|
|
|
|
|
|
if (Least.prefix==Rate->prefix)
|
|
|
|
|
return UNKNOWN;
|
|
|
|
|
|
|
|
|
|
*Rate=Least;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
return min;
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
int guessZone (RATE *Rate, int units)
|
|
|
|
|
{
|
|
|
|
|
#if 0
|
|
|
|
|
px="";
|
|
|
|
|
err=60*60*24*365; /* sehr gross */
|
|
|
|
|
for (c = 1; c < 31; c++) {
|
|
|
|
|
call[chan].zone=c;
|
|
|
|
|
tack = (-n -1) * (double)taktlaenge(chan, why);
|
|
|
|
|
if ((tack > 0) && (abs(tack - tx)<err)) {
|
|
|
|
|
call[chan].tick = tack;
|
|
|
|
|
err = abs(tack) - tx;
|
|
|
|
|
px = z2s(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
call[chan].zone=-1;
|
|
|
|
|
#else
|
|
|
|
|
return UNKNOWN;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-14 13:16:01 +00:00
|
|
|
|
char *explainRate (RATE *Rate)
|
|
|
|
|
{
|
|
|
|
|
char p[BUFSIZ], z[BUFSIZ], d[BUFSIZ]="", h[BUFSIZ]="";
|
|
|
|
|
static char r[BUFSIZ];
|
|
|
|
|
|
|
|
|
|
if (Rate->Provider && *Rate->Provider)
|
|
|
|
|
strncpy (p, Rate->Provider, BUFSIZ);
|
|
|
|
|
else
|
|
|
|
|
snprintf (p, BUFSIZ, "010%02d", Rate->prefix);
|
|
|
|
|
|
|
|
|
|
if (Rate->Zone && *Rate->Zone)
|
|
|
|
|
snprintf (z, BUFSIZ, ", %s", Rate->Zone);
|
|
|
|
|
else
|
|
|
|
|
snprintf (z, BUFSIZ, ", Zone %d", Rate->zone);
|
|
|
|
|
|
|
|
|
|
if (Rate->Day && *Rate->Day)
|
|
|
|
|
snprintf (d, BUFSIZ, ", %s", Rate->Day);
|
|
|
|
|
|
|
|
|
|
if (Rate->Hour && *Rate->Hour)
|
|
|
|
|
snprintf (h, BUFSIZ, ", %s", Rate->Hour);
|
|
|
|
|
|
|
|
|
|
snprintf (r, BUFSIZ, "%s%s%s%s", p, z, d, h);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
1999-03-14 12:15:56 +00:00
|
|
|
|
#ifdef STANDALONE
|
|
|
|
|
void main (int argc, char *argv[])
|
|
|
|
|
{
|
1999-04-14 13:16:01 +00:00
|
|
|
|
int z;
|
1999-03-16 17:37:08 +00:00
|
|
|
|
char *msg;
|
1999-04-10 16:34:57 +00:00
|
|
|
|
struct tm now;
|
|
|
|
|
|
1999-03-16 17:37:08 +00:00
|
|
|
|
RATE Rate, LCR;
|
|
|
|
|
|
|
|
|
|
initHoliday ("../holiday-at.dat", &msg);
|
|
|
|
|
printf ("%s\n", msg);
|
1999-03-24 19:37:29 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
initRate ("/etc/isdn/rate.conf", "../rate-at.dat", &msg);
|
1999-03-14 12:15:56 +00:00
|
|
|
|
printf ("%s\n", msg);
|
|
|
|
|
|
1999-04-29 19:02:56 +00:00
|
|
|
|
Rate.prefix = 1;
|
|
|
|
|
Rate.zone = 4;
|
1999-03-24 19:37:29 +00:00
|
|
|
|
|
1999-04-29 19:02:56 +00:00
|
|
|
|
if (argc==2) {
|
1999-04-14 13:16:01 +00:00
|
|
|
|
z=getZone(01, argv[1]);
|
|
|
|
|
printf("number <%s> is Zone <%d>\n", argv[1], z);
|
|
|
|
|
exit (0);
|
|
|
|
|
}
|
1999-04-29 19:02:56 +00:00
|
|
|
|
if (argc==3) {
|
|
|
|
|
printf ("strmatch(%s, %s)=%d\n", argv[1], argv[2], strmatch(argv[1], argv[2]));
|
|
|
|
|
exit (0);
|
|
|
|
|
}
|
1999-04-14 13:16:01 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
time(&Rate.start);
|
1999-03-16 17:37:08 +00:00
|
|
|
|
while (1) {
|
1999-04-10 16:34:57 +00:00
|
|
|
|
time(&Rate.now);
|
1999-03-16 17:37:08 +00:00
|
|
|
|
if (getRate(&Rate, &msg)==UNKNOWN)
|
1999-04-10 16:34:57 +00:00
|
|
|
|
printf ("Ooops: %s\n", msg);
|
|
|
|
|
else {
|
|
|
|
|
now=*localtime(&Rate.now);
|
1999-04-29 19:02:56 +00:00
|
|
|
|
printf ("%02d.%02d.%04d %02d:%02d:%02d %s %6.2f sec %7.3f + %7.3f <20>S %3d EH %6.2f <20>S %3ld sec %3ld sec\n",
|
1999-04-10 16:34:57 +00:00
|
|
|
|
now.tm_mday, now.tm_mon+1, now.tm_year+1900,
|
|
|
|
|
now.tm_hour, now.tm_min, now.tm_sec,
|
1999-04-14 13:16:01 +00:00
|
|
|
|
explainRate(&Rate),
|
1999-04-29 19:02:56 +00:00
|
|
|
|
Rate.Duration, Rate.Basic, Rate.Price, Rate.Units, Rate.Charge, Rate.Time, Rate.Rest);
|
1999-03-16 17:37:08 +00:00
|
|
|
|
|
1999-04-10 16:34:57 +00:00
|
|
|
|
LCR=Rate;
|
1999-04-29 19:02:56 +00:00
|
|
|
|
#if 0
|
1999-04-10 16:34:57 +00:00
|
|
|
|
if (getLeastCost(&LCR,-1)!=UNKNOWN) {
|
1999-04-29 19:02:56 +00:00
|
|
|
|
printf ("least cost would be: %s %6.2f %7.3f %3d %6.2f %3ld %3ld\n",
|
|
|
|
|
explainRate(&LCR),
|
|
|
|
|
LCR.Duration, LCR.Price, LCR.Units, LCR.Charge, LCR.Time, LCR.Rest);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
1999-04-10 16:34:57 +00:00
|
|
|
|
}
|
1999-03-16 17:37:08 +00:00
|
|
|
|
sleep(1);
|
|
|
|
|
}
|
1999-03-14 12:15:56 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|