isdn4k-utils/isdnlog/isdnrep/rep_main.c

664 lines
21 KiB
C
Raw Permalink Blame History

/* $Id: rep_main.c,v 1.21 2005/01/22 18:47:16 tobiasb Exp $
*
* ISDN accounting for isdn4linux. (Report-module)
*
* Copyright 1995 .. 2000 by Andreas Kool (akool@isdn4linux.de)
* and Stefan Luethje (luethje@sl-gw.lake.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: rep_main.c,v $
* Revision 1.21 2005/01/22 18:47:16 tobiasb
* New: "isdnrep -t y" for calls of yesterday.
* Added some more verifications in the processing of isdnrep's -t option.
*
* Revision 1.20 2004/12/16 21:30:50 tobiasb
* New option -U: default source number for outgoing calls.
*
* Revision 1.19 2004/07/25 14:21:13 tobiasb
* New isdnrep option -m [*|/]number. It multiplies or divide the cost of
* each call by the given number. `-m/1.16' for example displays the costs
* without the German `Umsatzsteuer'.
*
* Revision 1.18 2004/07/24 17:58:06 tobiasb
* New isdnrep options: `-L:' controls the displayed call summaries in the
* report footer. `-x' displays only call selected or not deselected by
* hour or type of day -- may be useful in conjunction with `-r'.
*
* Activated new configuration file entry `REPOPTIONS' for isdnrep default
* options. This options can be disabled by `-c' on the command line.
*
* Revision 1.17 2003/10/29 17:41:35 tobiasb
* isdnlog-4.67:
* - Enhancements for isdnrep:
* - New option -r for recomputing the connection fees with the rates
* from the current (and for a different or the cheapest provider).
* - Revised output format of summaries at end of report.
* - New format parameters %j, %v, and %V.
* - 2 new input formats for -t option.
* - Fix for dualmode workaround 0x100 to ensure that incoming calls
* will not become outgoing calls if a CALL_PROCEEDING message with
* an B channel confirmation is sent by a terminal prior to CONNECT.
* - Fixed and enhanced t: Tag handling in pp_rate.
* - Fixed typo in interface description of tools/rate.c
* - Fixed typo in tools/isdnrate.man, found by Paul Slootman.
* - Minor update to sample isdn.conf files:
* - Default isdnrep format shows numbers with 16 chars (+ & 15 digits).
* - New isdnrep format (-FNIO) without display of transfered bytes.
* - EUR as currency in Austria, may clash with outdated rate-at.dat.
* The number left of the currency symbol is nowadays insignificant.
* - Changes checked in earlier but after step to isdnlog-4.66:
* - New option for isdnrate: `-rvNN' requires a vbn starting with NN.
* - Do not compute the zone with empty strings (areacodes) as input.
* - New ratefile tags r: und t: which need an enhanced pp_rate.
* For a tag description see rate-files(5).
* - Some new and a few updated international cellphone destinations.
*
* NOTE: If there any questions, problems, or problems regarding isdnlog,
* feel free to join the isdn4linux mailinglist, see
* https://www.isdn4linux.de/mailman/listinfo/isdn4linux for details,
* or send a mail in English or German to <tobiasb@isdn4linux.de>.
*
* Revision 1.16 2003/07/25 22:18:03 tobiasb
* isdnlog-4.65:
* - New values for isdnlog option -2x / dual=x with enable certain
* workarounds for correct logging in dualmode in case of prior
* errors. See `man isdnlog' and isdnlog/processor.c for details.
* - New isdnlog option -U2 / ignoreCOLP=2 for displaying ignored
* COLP information.
* - Improved handling of incomplete D-channel frames.
* - Increased length of number aliases shown immediately by isdnlog.
* Now 127 instead of 32 chars are possible. (Patch by Jochen Erwied.)
* - The zone number for an outgoing call as defined in the rate-file
* is written to the logfile again and used by isdnrep
* - Improved zone summary of isdnrep. Now the real zone numbers as
* defined in the rate-file are shown. The zone number is taken
* from the logfile as mentioned before or computed from the current
* rate-file. Missmatches are indicated with the chars ~,+ and *,
* isdnrep -v ... explains the meanings.
* - Fixed provider summary of isdnrep. Calls should no longer be
* treated wrongly as done via the default (preselected) provider.
* - Fixed the -pmx command line option of isdnrep, where x is the xth
* defined [MSN].
* - `make install' restarts isdnlog after installing the data files.
* - A new version number generates new binaries.
* - `make clean' removes isdnlog/isdnlog/ilp.o when called with ILP=1.
*
* Revision 1.15 2002/03/11 16:17:11 paul
* DM -> EUR
*
* Revision 1.14 2000/08/17 21:34:44 akool
* isdnlog-4.40
* - README: explain possibility to open the "outfile=" in Append-Mode with "+"
* - Fixed 2 typos in isdnlog/tools/zone/de - many thanks to
* Tobias Becker <tobias@talypso.de>
* - detect interface (via IIOCNETGPN) _before_ setting CHARGEINT/HUPTIMEOUT
* - isdnlog/isdnlog/processor.c ... fixed wrong init of IIOCNETGPNavailable
* - isdnlog/isdnrep/isdnrep.c ... new option -S summary
* - isdnlog/isdnrep/rep_main.c
* - isdnlog/isdnrep/isdnrep.1.in
* - isdnlog/tools/NEWS
* - isdnlog/tools/cdb/debian ... (NEW dir) copyright and such from orig
* - new "rate-de.dat" from sourceforge (hi and welcome: Who is "roro"?)
*
* Revision 1.13 2000/03/06 07:03:20 akool
* isdnlog-4.15
* - isdnlog/tools/tools.h ... moved one_call, sum_calls to isdnrep.h
* ==> DO A 'make clean' PLEASE
* - isdnlog/tools/telnum.c ... fixed a small typo
* - isdnlog/isdnrep/rep_main.c ... incl. dest.h
* - isdnlog/isdnrep/isdnrep.c ... fixed %l, %L
* - isdnlog/isdnrep/isdnrep.h ... struct one_call, sum_calls are now here
*
* Support for Norway added. Many thanks to Tore Ferner <torfer@pvv.org>
* - isdnlog/rate-no.dat ... NEW
* - isdnlog/holiday-no.dat ... NEW
* - isdnlog/samples/isdn.conf.no ... NEW
* - isdnlog/samples/rate.conf.no ... NEW
*
* Revision 1.12 1999/12/31 13:57:19 akool
* isdnlog-4.00 (Millenium-Edition)
* - Oracle support added by Jan Bolt (Jan.Bolt@t-online.de)
* - resolved *any* warnings against rate-de.dat
* - Many new rates
* - CREDITS file added
*
* Revision 1.11 1999/12/17 22:51:55 akool
* isdnlog-3.79
* - isdnlog/isdnrep/isdnrep.{c,h} ... error -handling, print_msg
* - isdnlog/isdnrep/rep_main.c
* - isdnlog/isdnrep/isdnrep.1.in
* - isdnlog/tools/rate.c ... dupl entry in rate.conf
* - isdnlog/tools/NEWS
* - isdnlog/tools/isdnrate.c
* - isdnlog/tools/dest/configure{,.in}
* - isdnlog/tools/zone/configure{,.in}
*
* Revision 1.10 1999/07/18 08:40:57 akool
* fix from Michael
*
* Revision 1.9 1999/07/12 11:37:38 calle
* Bugfix: isdnrep defined print_msg as function pointer, the object files
* in tools directory, declare it as external function.
* compiler and linker did not detect the problem.
* Now print_msg is a function in rep_main.c and I copied
* print_in_modules from isdnconf. Also set_print_fct_for_isdnrep
* is removed from isdnrep.c. isdnrep didn<64>t crash now, but throw
* out warning messages about rate.dat and did<69>t generate output.
*
* Revision 1.8 1999/06/13 14:08:08 akool
* isdnlog Version 3.32
*
* - new option "-U1" (or "ignoreCOLP=1") to ignore CLIP/COLP Frames
* - TEI management decoded
*
* Revision 1.7 1999/01/24 19:02:33 akool
* - second version of the new chargeint database
* - isdnrep reanimated
*
* Revision 1.6 1998/11/24 20:52:55 akool
* - changed my email-adress
* - new Option "-R" to supply the preselected provider (-R24 -> Telepassport)
* - made Provider-Prefix 6 digits long
* - full support for internal S0-bus implemented (-A, -i Options)
* - isdnlog now ignores unknown frames
* - added 36 allocated, but up to now unused "Auskunft" Numbers
* - added _all_ 122 Providers
* - Patch from Jochen Erwied <mack@Joker.E.Ruhr.DE> for Quante-TK-Anlagen
* (first dialed digit comes with SETUP-Frame)
*
* Revision 1.5 1998/03/29 19:54:22 luethje
* idnrep: added html feature (incoming/outgoing calls)
*
* Revision 1.4 1997/05/15 22:21:41 luethje
* New feature: isdnrep can transmit via HTTP fax files and vbox files.
*
* Revision 1.3 1997/05/04 20:19:58 luethje
* README completed
* isdnrep finished
* interval-bug fixed
*
* Revision 1.2 1997/04/20 22:52:29 luethje
* isdnrep has new features:
* -variable format string
* -can create html output (option -w1 or ln -s isdnrep isdnrep.cgi)
* idea and design from Dirk Staneker (dirk.staneker@student.uni-tuebingen.de)
* bugfix of processor.c from akool
*
* Revision 1.1 1997/04/06 21:03:38 luethje
* switch -f is working again
* currency_factor is float again ;-)
* renamed files isdnrep.c to rep_main.c and function.c isdnrep.c
*
* Revision 1.7 1997/04/03 22:30:02 luethje
* improved performance
*
* Revision 1.6 1997/03/31 22:43:15 luethje
* Improved performance of the isdnrep, made some changes of README
*
* Revision 1.5 1997/03/24 22:52:12 luethje
* isdnrep completed.
*
* Revision 1.4 1997/03/23 23:11:59 luethje
* improved performance
*
* Revision 1.3 1997/03/23 20:25:23 luethje
* tmporary (running) result of the new structure of isdnrep
*
* Revision 1.2 1997/03/20 00:19:13 luethje
* inserted the line #include <errno.h> in avmb1/avmcapictrl.c and imon/imon.c,
* some bugfixes, new structure in isdnlog/isdnrep/isdnrep.c.
*
* Revision 1.1 1997/03/16 20:59:05 luethje
* Added the source code isdnlog. isdnlog is not working yet.
* A workaround for that problem:
* copy lib/policy.h into the root directory of isdn4k-utils.
*
* Revision 2.6.19 1997/01/04 13:00:35 akool
* Korrektur bzgl. ISDN_CH
* Danke an Markus Maeder (mmaeder@cyberlink.ch)
*
* Revision 2.6.15 1997/01/02 11:32:35 akool
* -V Option added
*
* Revision 2.6.11 1996/12/30 10:17:35 akool
* Dutch accounting (Ad Aerts <ad@aasup.nl>)
*
* Revision 2.50 1996/08/25 11:48:35 akool
* Auswertung bei non-AOCE-Anschluessen verbessert
*
* Revision 2.13 1996/03/16 16:11:35 akool
* Andruck der "ibytes" implementiert
*
* Revision 2.10 1996/01/16 01:04:35 sl
* Ausgabe von bestimmten MSN's ergaenzt, Nur ankommende dor ausgehende
* Gespraeche anzeigen, Ueberarbeitung der kompletten Sourcen.
* Funktion fuer fremde Waehrungen ergaenzt
*
* Revision 2.03 1996/01/07 03:35:17 sl
* Optionen -c und -6 entfernt, Tab-Bug behoben, Bug in automatischer
* Gebuehrenberechnung beim alten Logformat behoben,
* Zeitangabe beim Summary,
*
* Revision 2.02 1996/01/07 03:35:17 sl
* Zeitraumausgabe angepasst, loeschen von isdn.log-Eintraegen
*
* Revision 2.01 1996/01/06 18:15:20 sl
* Zeitraumausgabe, nur Calls-Anzeige, optionales Logfile
*
* Revision 2.00 1996/01/01 17:50:19 akool
* Auswertung der neuen Eintraege (I/O, Cause) implementiert
* Vollstaendiges Redesign
*
* Revision 1.25 1995/11/19 09:56:19 akool
* Neue Option "-c" aktiviert die eigene Berechnung der Einheiten bei
* fehlender Gebuehreninfo
*
* Revision 1.24 1995/11/12 11:09:19 akool
* Formatfelder vergroessert
* Fremdverursachte Einheiten werden ge-()
* Alle Floating-Point-Zahlen werden deutsch (mit Komma) ausgegeben
*
* Revision 1.23 1995/11/06 18:04:19 akool
* Denkfehler in der "-6" Berechnung :-(
*
* Revision 1.22 1995/10/22 15:31:19 akool
* Aufschluesselung bach Tarifzonen implementiert
*
* Revision 1.21 1995/10/17 19:53:19 akool
* Auf echte Charging-Info umgestellt
*
* Revision 1.20 1995/10/15 17:58:19 akool
* Vergleich errechnete zu uebermittelten Einheiten implementiert
*
* Revision 1.16 1995/10/12 13:50:19 akool
* Neue Option "MYMSNS=x" in der "isdnlog.conf" zum definieren der Anzahl
* eigener MSN's
*
* Revision 1.15 1995/10/09 18:42:18 akool
* Offensichtlich sinnlose Daten i.d. "isdn.log" werden nun ignoriert
*
* Revision 1.14 1995/10/08 10:25:16 akool
* Ueberschreitung verschiedener Zeittakte bei einer Verbindung implementiert.
*
* Revision 1.6 1995/09/30 19:55:17 akool
* First public release
*
* Revision 1.1 1995/09/23 16:44:19 akool
* Initial revision
*
*/
#define _ISDNREP_C_
#include "dest.h"
#include "isdnrep.h"
/*****************************************************************************/
static int parse_options(int argc, char *argv[], char *myname);
int print_msg(int Level, const char *fmt, ...);
int print_in_modules(const char *fmt, ...);
static int set_linefmt(char *linefmt);
/*****************************************************************************/
static char fnbuff[512] = "";
static char usage[] = "%s: usage: %s [ -%s ]\n";
static char wrongdate[] = "unknown date: %s\n";
static char wrongxopt[] = "error in -x option starting at: %s\n";
static char options[] = "abcd:f:him:nop:r:s:t:uvw:x:EF:L:M:NR:SU:V";
static char *linefmt = "";
static char *htmlreq = NULL;
static char *phonenumberarg = NULL;
static int do_defopts = 1;
/*****************************************************************************/
int main(int argc, char *argv[], char *envp[])
{
auto int c;
auto char *myname = basename(argv[0]);
auto char *ptr = NULL;
auto char **pptr;
set_print_fct_for_tools(print_in_modules);
recalc.mode = '\0'; recalc.prefix = UNKNOWN; recalc.input = NULL;
recalc.count = recalc.unknown = recalc.cheaper = 0;
modcost.mode = defsrc.mode = 0;
select_summaries(sel_sums, NULL); /* default: all summaries */
/* we don't need this at the moment:
new_args(&argc,&argv);
*/
/* readconfig should be done before option parsing. At least -pmx
* needs access to known in set_msnlist. Otherwise no selection of
* configured MSNs via their index (x=1..) is possible. By the other
* hand this order can cause problems. A corrupt config can block
* the simple `isdnrep -V'. Resolution: parse options first but call
* set_msnlist after readconfig.
*/
/* TODO: parse_options may print to stdout regardless a missing
* Content-Type header. (tobiasb|200407) */
if ((c=parse_options(argc, argv, myname) > 0))
return c;
if (readconfig(myname) != 0)
return 1;
pptr = (char **) 0;
while (do_defopts && isdnrep_defopts) /* default options from isdn.conf */
{
int dargc;
char **dargv;
pptr = String_to_Array(isdnrep_defopts, ';');
if (!pptr)
break;
dargc = 0;
dargv = pptr;
while (*dargv++)
dargc++;
if (!dargc)
break;
dargv = (char **) calloc(dargc+2, sizeof(char *));
if (!dargv)
break;
dargv[0] = argv[0];
memcpy(dargv+1, pptr, dargc * sizeof(char *));
if ((c=parse_options(dargc+1, dargv, myname) > 0))
return c;
break;
}
if (pptr)
del_Array(pptr);
if (phonenumberonly && phonenumberarg != NULL) {
set_msnlist(phonenumberarg);
free(phonenumberarg);
}
if (defsrc.mode > 0 && *defsrc.number == '.') {
/* prefix country and area code from isdn.conf */
ptr = calloc(strlen(mycountry) + strlen(myarea) + strlen(defsrc.number),
sizeof(char));
if (ptr == NULL) {
printf("No memory for complete default source number (-U)\n");
return 1;
}
strcat(ptr, mycountry);
strcat(ptr, myarea);
strcat(ptr, defsrc.number + 1);
free(defsrc.number);
defsrc.number = ptr;
}
if (htmlreq)
{
send_html_request(myname,htmlreq);
exit(0);
}
if (!html && (ptr = strrchr(myname,'.')) != NULL && !strcasecmp(ptr+1,"cgi"))
html = H_PRINT_HEADER;
if (html)
{
seeunknowns = 0;
header++;
}
if (linefmt != NULL)
{
if (*linefmt == '\0')
{
if (html)
set_linefmt("WWW");
else
set_linefmt(linefmt);
}
else
{
if (set_linefmt(linefmt))
{
printf("Error: %s can not find format `%s%s'!\n",myname,CONF_ENT_REPFMT,To_Upper(linefmt));
exit(0);
}
}
}
if (!currency_factor)
currency = "EUR";
if (fnbuff[0])
logfile = fnbuff;
return (read_logfile(myname));
}
/*****************************************************************************/
/* handle options from cammandline and isdn.conf */
static int parse_options(int argc, char *argv[], char *myname)
{
auto int c;
auto char *ptr = NULL;
/* reset internal state of getopt ...
* for an explanation look at bugs.debian.org, bug #192834 */
#ifdef __GLIBC__
optind = 0;
#else
optind = 1;
#endif
while ((c = getopt(argc, argv, options)) != EOF)
switch (c) {
case 'a' : timearea++;
begintime = 0;
time(&endtime);
break;
case 'i' : incomingonly++;
break;
case 'o' : outgoingonly++;
break;
case 'h' : header = 0;
break;
case 'n' : numbers++;
break;
case 'd' : delentries++;
case 't' : Strncpy(timestring, optarg, sizeof timestring);
if (!get_term(timestring,&begintime,&endtime,delentries))
{
printf(wrongdate, timestring);
return 1;
}
timearea++;
break;
case 'u' : seeunknowns++;
break;
case 'v' : verbose++;
break;
case 'E' : print_failed++;
break;
case 'f' : strcpy(fnbuff, optarg);
break;
case 'p' : if (!phonenumberonly) phonenumberarg = strdup(optarg);
phonenumberonly++;
break;
case 'w' : html = strtol(optarg, NIL, 0)?H_PRINT_HEADER:H_PRINT_HTML;
break;
case 's' : lineformat = strdup(optarg);
linefmt = NULL;
break;
case 'F' : if (linefmt && !*linefmt)
linefmt = strdup(optarg);
break;
case 'N' : use_new_config = 0;
break;
case 'M' : htmlreq = strdup(optarg);
break;
case 'R' : preselect = (int)strtol(optarg, NIL, 0);
break;
case 'b' : bill++;
break;
case 'V' : print_version(myname);
exit(0);
case 'S' : summary++;
break;
case 'r' : recalc.mode = *optarg;
recalc.input = strdup(optarg+1);
break;
case 'L' : select_summaries(sel_sums, optarg);
break;
case 'x' : ptr = select_day_hour(days, hours, optarg);
if (ptr) {
printf(wrongxopt, ptr);
return 1;
}
break;
case 'c' : do_defopts = 0;
break;
case 'm' : modcost.mode = (*optarg =='/') ? 2 : 1;
modcost.numstr = strdup(optarg);
if (*optarg == '*' || *optarg == '/')
modcost.numstr++;
ptr = NULL;
modcost.number = strtod(modcost.numstr, &ptr);
if (modcost.numstr == ptr)
{
printf("no number in -m option: %s\n", modcost.numstr);
return 1;
}
if (modcost.mode == 2 && modcost.number == 0.0)
{
printf("division by 0 as requested in -m option not allowed.\n");
return 1;
}
if (ptr && *ptr)
*ptr = 0;
break;
case 'U' : defsrc.mode = (*optarg == '_') ? 2 : 1;
ptr = optarg - 1 + defsrc.mode;
/* mycountry and myarea may not yet known */
defsrc.number = calloc(strlen(ptr) + 1, sizeof(char));
if (!defsrc.number) {
printf("No memory for default source number (-U)\n");
return 1;
}
strcat(defsrc.number, ptr);
break;
case '?' : printf(usage, argv[0], argv[0], options);
return(1);
} /* switch */
return 0;
} /* /parse_options() */
/*****************************************************************************/
int print_msg(int Level, const char *fmt,...)
{
auto va_list ap;
auto char String[BUFSIZ * 3];
if ((Level > PRT_ERR && !verbose) || (Level > PRT_WARN && verbose < 2))
return (1);
va_start(ap, fmt);
(void) vsnprintf(String, BUFSIZ * 3, fmt, ap);
va_end(ap);
fprintf(stderr, "%s", String);
return (0);
} /* print_msg */
/*****************************************************************************/
int print_in_modules(const char *fmt, ...)
{
auto va_list ap;
auto char String[LONG_STRING_SIZE];
va_start(ap, fmt);
(void)vsnprintf(String, LONG_STRING_SIZE, fmt, ap);
va_end(ap);
return print_msg(PRT_ERR, "%s", String);
}
/*****************************************************************************/
int set_linefmt(char *linefmt)
{
int i = 0;
int RetCode = -1;
if (lineformats != NULL)
{
while(lineformats[i] != NULL)
{
if (!strcasecmp(linefmt,lineformats[i][0]))
{
lineformat = lineformats[i][1];
RetCode = 0;
break;
}
i++;
}
}
return RetCode;
}
/*****************************************************************************/
/* vim:set ts=2: */