Logo Search packages:      
Sourcecode: isdnutils version File versions  Download package

rep_main.c

/* $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īt crash now, but throw
 *    out warning messages about rate.dat and didī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: */

Generated by  Doxygen 1.6.0   Back to index