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

isdnconf.c

/* $Id: isdnconf.c,v 1.36 2004/07/24 16:16:56 tobiasb Exp $
 *
 * ISDN accounting for isdn4linux. (Utilities)
 *
 * 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: isdnconf.c,v $
 * Revision 1.36  2004/07/24 16:16:56  tobiasb
 * New entry `REPOPTIONS' in section [ISDNLOG] of the isdn configuration
 * file.  This will be used for commandline options defaults of isdnrep.
 *
 * Revision 1.35  2004/02/06 16:58:01  tobiasb
 * Fixed outdated source code comment.
 *
 * Revision 1.34  2002/07/04 10:29:18  paul
 * "DEM" -> "EUR"
 *
 * Revision 1.33  2000/09/01 06:30:20  paul
 * Now install country-de.dat as country.dat; renaming the source can be done by
 * someone who is more experienced with CVS.
 * Default value for country.dat changed in isdnconf.c; also default zonefile
 * etc. changed from .gdbm to .cdb
 *
 * Revision 1.32  2000/02/20 19:03:08  akool
 * isdnlog-4.12
 *  - ABC_LCR enhanced
 *  - country-de.dat more aliases
 *  - new rates
 *  - isdnlog/Makefile.in ... defined NATION
 *  - isdnlog/isdnlog/processor.c ... msn patch for NL
 *  - isdnlog/tools/isdnconf.c ... default config
 *
 * Revision 1.31  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.30  1999/10/25 18:30:03  akool
 * isdnlog-3.57
 *   WARNING: Experimental version!
 *       Please use isdnlog-3.56 for production systems!
 *
 * Revision 1.29  1999/06/15 20:05:08  akool
 * isdnlog Version 3.33
 *   - big step in using the new zone files
 *   - *This*is*not*a*production*ready*isdnlog*!!
 *   - Maybe the last release before the I4L meeting in Nuernberg
 *
 * Revision 1.28  1999/05/13 11:39:47  akool
 * isdnlog Version 3.28
 *
 *  - "-u" Option corrected
 *  - "ausland.dat" removed
 *  - "countries-de.dat" fully integrated
 *      you should add the entry
 *      "COUNTRYFILE = /usr/lib/isdn/countries-de.dat"
 *      into section "[ISDNLOG]" of your config file!
 *  - rate-de.dat V:1.02-Germany [13-May-1999 12:26:24]
 *  - countries-de.dat V:1.02-Germany [13-May-1999 12:26:26]
 *
 * Revision 1.27  1999/05/04 19:33:37  akool
 * isdnlog Version 3.24
 *
 *  - fully removed "sondernummern.c"
 *  - removed "gcc -Wall" warnings in ASN.1 Parser
 *  - many new entries for "rate-de.dat"
 *  - better "isdnconf" utility
 *
 * Revision 1.26  1999/04/15 19:14:58  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
 *
 * Revision 1.25  1999/04/10 16:36:36  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)
 *
 * Revision 1.24  1999/03/24 19:38:57  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
 *
 * Revision 1.23  1999/03/15 21:28:44  akool
 * - isdnlog Version 3.06
 * - README: explain some terms about LCR, corrected "-c" Option of "isdnconf"
 * - isdnconf: added a small LCR-feature - simply try "isdnconf -c 069"
 * - isdnlog: dont change CHARGEINT, if rate is't known!
 * - sonderrufnummern 1.02 [15-Mar-99] :: added WorldCom
 * - tarif.dat 1.09 [15-Mar-99] :: added WorldCom
 * - isdnlog now correctly handles the new "Ortstarif-Zugang" of UUnet
 *
 * Revision 1.22  1999/02/28 19:33:39  akool
 * Fixed a typo in isdnconf.c from Andreas Jaeger <aj@arthur.rhein-neckar.de>
 * CHARGEMAX fix from Oliver Lauer <Oliver.Lauer@coburg.baynet.de>
 * isdnrep fix from reinhard.karcher@dpk.berlin.fido.de (Reinhard Karcher)
 * "takt_at.c" fixes from Ulrich Leodolter <u.leodolter@xpoint.at>
 * sondernummern.c from Mario Joussen <mario.joussen@post.rwth-aachen.de>
 * Reenable usage of the ZONE entry from Schlottmann-Goedde@t-online.de
 * Fixed a typo in callerid.conf.5
 *
 * Revision 1.21  1999/01/24 19:02:45  akool
 *  - second version of the new chargeint database
 *  - isdnrep reanimated
 *
 * Revision 1.20  1998/11/24 20:53:03  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.19  1998/09/26 18:30:08  akool
 *  - quick and dirty Call-History in "-m" Mode (press "h" for more info) added
 *    - eat's one more socket, Stefan: sockets[3] now is STDIN, FIRST_DESCR=4 !!
 *  - Support for tesion)) Baden-Wuerttemberg Tarif
 *  - more Providers
 *  - Patches from Wilfried Teiken <wteiken@terminus.cl-ki.uni-osnabrueck.de>
 *    - better zone-info support in "tools/isdnconf.c"
 *    - buffer-overrun in "isdntools.c" fixed
 *  - big Austrian Patch from Michael Reinelt <reinelt@eunet.at>
 *    - added $(DESTDIR) in any "Makefile.in"
 *    - new Configure-Switches "ISDN_AT" and "ISDN_DE"
 *      - splitted "takt.c" and "tools.c" into
 *          "takt_at.c" / "takt_de.c" ...
 *          "tools_at.c" / "takt_de.c" ...
 *    - new feature
 *        CALLFILE = /var/log/caller.log
 *        CALLFMT  = %b %e %T %N7 %N3 %N4 %N5 %N6
 *      in "isdn.conf"
 *  - ATTENTION:
 *      1. "isdnrep" dies with an seg-fault, if not HTML-Mode (Stefan?)
 *      2. "isdnlog/Makefile.in" now has hardcoded "ISDN_DE" in "DEFS"
 *          should be fixed soon
 *
 * Revision 1.18  1998/06/14 15:34:35  akool
 * AVM B1 support (Layer 3)
 * Telekom's new currency DEM 0,121 supported
 * Disable holiday rates #ifdef ISDN_NL
 * memory leak in "isdnrep" repaired
 *
 * Revision 1.17  1998/05/20 12:34:38  paul
 * More paranoid about freeing pointers.
 *
 * Revision 1.16  1998/05/19 15:55:57  paul
 * Moved config stuff for City Weekend from isdnlog.c to tools/isdnconf.c, so
 * that isdnrep also understands a "cityweekend=y" line in isdn.conf.
 *
 * Revision 1.15  1998/03/08 11:43:13  luethje
 * I4L-Meeting Wuerzburg final Edition, golden code - Service Pack number One
 *
 * Revision 1.14  1998/03/01 20:36:22  keil
 * bugfixes from Florian La Roche
 *
 * Revision 1.13  1997/06/24 23:35:33  luethje
 * isdnctrl can use a config file
 *
 * Revision 1.12  1997/06/22 23:03:34  luethje
 * In subsection FLAGS it will be checked if the section name FLAG is korrect
 * isdnlog recognize calls abroad
 * bugfix for program starts
 *
 * Revision 1.11  1997/05/25 19:41:13  luethje
 * isdnlog:  close all files and open again after kill -HUP
 * isdnrep:  support vbox version 2.0
 * isdnconf: changes by Roderich Schupp <roderich@syntec.m.EUnet.de>
 * conffile: ignore spaces at the end of a line
 *
 * Revision 1.10  1997/05/15 22:21:45  luethje
 * New feature: isdnrep can transmit via HTTP fax files and vbox files.
 *
 * Revision 1.9  1997/05/10 22:41:17  luethje
 * bug in format string fixed
 *
 * Revision 1.8  1997/05/04 20:20:01  luethje
 * README completed
 * isdnrep finished
 * interval-bug fixed
 *
 * Revision 1.7  1997/04/20 22:52:32  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.6  1997/04/17 20:09:57  luethje
 * patch of Ingo Schneider
 *
 */

/****************************************************************************/

#define  _ISDNCONF_C_

/****************************************************************************/

#include "tools.h"

/****************************************************************************/

static char ***Environment = NULL;
static char *OlabelPtr = NULL;
static char *IlabelPtr = NULL;

/****************************************************************************/

static char *NextItem(char *Line, int komma);
static char*NextOption(char** Options, char* Delim);
static void Append(char **Target, char*Source);
static int SetFlags(KNOWN *FlagPtr, char *flags);
static int IsVariable(char *string);
static int Set_Globals(section *SPtr);
static info_args** Set_Flags(section *SPtr, int *Flags);
static int Get_Events(char* Flags);
static int Set_Numbers(section *SPtr, char *Section, int msn);
static int Set_known_Size(int msn);
static section* writeentry(section *SPtr, int Index);
static int readconfigfile(char *_myname);
static int _readconfig(char *_myname);
static int readoldconfig(char *myname);
static section* writeinfoargs(section *SPtr, info_args *infoarg);
static void appendflag(char*str1, char*str2);
static char *writeflags(int flag);
static section* writevariables(section *SPtr);
static section* writeglobal(section *SPtr);
static int SetEnv(char ****EnvPtr, char *name, char *value);
static int GetNextEnv(char ***EnvPtr, char **name, char **value);
static int ClearEnv(char ****EnvPtr);
static int Set_ILabel(char *value);
static int Set_OLabel(char *value);
static char *Get_FmtStr(char *Ptr, char *name);

/****************************************************************************/

static char *NextItem(char *Line, int komma)
{
  register char *p;
  register char *Ptr = Line;


  while (*Line && (*Line != ' ') && (*Line != '\t'))
    Line++;

  p = Line;

  while ((*Line == ' ') || (*Line == '\t'))
    Line++;

  *p = 0;

       p = Line;

       while((Ptr = Check_Quote(Ptr, komma ? "\\$@;#" : S_QUOTES, QUOTE_DELETE)) != NULL);

  return(Line);
} /* NextItem */

/******************************************************************************/

static char*NextOption(char** Options, char* Delim)
{
      char *RetCode = NULL;
      char *Ptr = *Options;
      int Len;

      *Delim = '\0';

      if (Ptr == NULL)
            return NULL;

      if ((Ptr = Check_Quote(Ptr,";,",QUOTE_DELETE)) == NULL)
            Ptr = "";

      if (*Ptr == ',' || *Ptr == ';' || *Ptr == '\0')
      {
            *Delim = *Ptr;

            if (Ptr != *Options)
            {
                  Len = Ptr-(*Options);
                  RetCode = (char*) calloc(Len+1, sizeof(char));
                  strncpy(RetCode,*Options,Len);
            }

            if (*Ptr == ',')
            {
                  *Options = Ptr+1;
            }
            else
            {
                  while(!isalpha(*Ptr) && *Ptr != '\0')
                        Ptr++;

                  if (*Ptr == '\0')
                    *Options = NULL;
                  else
                    *Options = Ptr;
            }
      }

      return RetCode;
}

/******************************************************************************/

static void Append(char **Target, char*Source)
{
      if (*Target == NULL)
      {
            *Target = Source;
            return;
      }

      if (Source == NULL)
            return;

      *Target = (char*) realloc(*Target, sizeof(char)*(strlen(*Target)+strlen(Source)+2));
      strcat(*Target,",");
      strcat(*Target,Source);
}

/******************************************************************************/

static int SetFlags(KNOWN *FlagPtr, char *flags)
{
      auto char Delim = '\0';
      auto char *Ptr;
  auto int  NumArgs = 0;
      auto int  flag = 0;

      while (*flags == ' ' || *flags == '\t')
            flags++;

  FlagPtr->infoargs = NULL;
  FlagPtr->flags = 0;

  while (flags && *flags) {
      flag = 0;

    while(isalpha(*flags) || isspace(*flags))
    {
      switch (toupper(*flags++)) {
        case 'I' : flag |= RING_INCOMING; break;
        case 'O' : flag |= RING_OUTGOING; break;
        case 'R' : flag |= RING_RING    ; break;
        case 'C' : flag |= RING_CONNECT ; break;
        case 'B' : flag |= RING_BUSY    ; break;
        case 'A' : flag |= RING_AOCD    ; break;
        case 'E' : flag |= RING_ERROR   ; break;
        case 'H' : flag |= RING_HANGUP  ; break;
        case 'K' : flag |= RING_KILL    ; break;
        case 'L' : flag |= RING_LOOP    ; break;
        case 'S' : flag |= RING_SPEAK   ; break;
        case 'P' : flag |= RING_PROVIDER; break;
        case 'U' : flag |= RING_UNIQUE  ; break;
        case ' ' : break;
        case '\t': break;

        default : _print_msg( "%s: WARNING: Unknown flag ``%c'' in file \"%s\" line %d, ignored\n", Myname, *(flags-1), OLDCONFFILE, ln);
                  break;
      } /* switch */
    }

    if (flag != 0)
    {
      if(*flags == '=')
      {
        flags++;
        FlagPtr->flags |= flag;
        FlagPtr->infoargs = (info_args**) realloc(FlagPtr->infoargs, sizeof(info_args*) * (NumArgs+2));
        FlagPtr->infoargs[NumArgs] = (info_args*) calloc(1, sizeof(info_args));

              FlagPtr->infoargs[NumArgs]->flag    = flag;
              FlagPtr->infoargs[NumArgs]->infoarg = NextOption(&flags,&Delim);

              if (Delim == ',')
              {
                         if ((Ptr = NextOption(&flags,&Delim)) != NULL)
                         {
                           FlagPtr->infoargs[NumArgs]->interval= atoi(Ptr);
                           free(Ptr);
                         }
                  }

              if (Delim == ',')
                do
                  Append(&(FlagPtr->infoargs[NumArgs]->time),
                         NextOption(&flags,&Delim));
                while(Delim == ',');

        if (Delim != ';')
        {
          _print_msg( "%s: WARNING: Syntax-Error in file \"%s\" line %d, ignored (\";\" expected, but found \"%c\")\n", Myname, OLDCONFFILE, ln, Delim);
          flags = NULL;
        }

        FlagPtr->infoargs[++NumArgs] = NULL;
      }
      else
      {
        _print_msg( "%s: WARNING: Syntax-Error in file \"%s\" line %d, ignored (\"=\" expected, but found \"%c\")\n", Myname, OLDCONFFILE, ln, *flags);
        flags = NULL;
      }
    }
  } /* while */

  return 0;
}

/******************************************************************************/

static int IsVariable(char *string)
{
  char s1[SHORT_STRING_SIZE] = "",
       s2[LONG_STRING_SIZE] = "";

  if (sscanf(string,"%[a-zA-Z0-9] = %[^\n]",s1,s2) == 2)
  {
    if (SetEnv(&Environment,s1,s2) == 0)
      return 1;

    _print_msg( "%s: WARNING: Error in file \"%s\" line %d: Can't set variable (%s)!\n", Myname, OLDCONFFILE, ln, strerror(errno));
  }

  return 0;
}

/****************************************************************************/

int writeconfig(char *_myname)
{
      int i;
  auto char     s[BUFSIZ];
  auto section *SPtr = NULL;


      if ((SPtr = writevariables(SPtr)) == NULL)
      {
            free_section(SPtr);
            return -1;
      }

      if ((SPtr = writeglobal(SPtr)) == NULL)
      {
            free_section(SPtr);
            return -1;
      }

  sprintf(s, "%s%c%s", confdir(), C_SLASH, CONFFILE);
      write_file(SPtr,s,_myname,VERSION);

      free_section(SPtr);
      SPtr = NULL;

      for (i = 0; i < knowns; i++)
      {
            if ((SPtr = writeentry(SPtr,i)) == NULL)
            {
                  free_section(SPtr);
                  return -1;
            }
      }

  sprintf(s, "%s%c%s", confdir(), C_SLASH, CALLERIDFILE);
      write_file(SPtr,s,_myname,VERSION);

      free_section(SPtr);

      return 0;
}

/****************************************************************************/

static void appendflag(char*str1, char*str2)
{
      char delim[2];

      delim[0] = C_FLAG_DELIM;
      delim[1] = '\0';

      if (str1[0] != '\0')
            strcat(str1,delim);

      strcat(str1,str2);
}

/****************************************************************************/

static char *writeflags(int flag)
{
      static char string[BUFSIZ];

      string[0] = '\0';

      if (flag & RING_INCOMING)
            appendflag(string,"I");
      if (flag & RING_OUTGOING)
            appendflag(string,"O");
      if (flag & RING_RING)
            appendflag(string,"R");
      if (flag & RING_CONNECT)
            appendflag(string,"C");
      if (flag & RING_BUSY)
            appendflag(string,"B");
      if (flag & RING_AOCD)
            appendflag(string,"A");
      if (flag & RING_ERROR)
            appendflag(string,"E");
      if (flag & RING_HANGUP)
            appendflag(string,"H");
      if (flag & RING_KILL)
            appendflag(string,"K");
      if (flag & RING_LOOP)
            appendflag(string,"L");
      if (flag & RING_SPEAK)
            appendflag(string,"S");
      if (flag & RING_PROVIDER)
            appendflag(string,"P");
      if (flag & RING_UNIQUE)
            appendflag(string,"U");

      return string;
}

/****************************************************************************/

static section* writeinfoargs(section *SPtr, info_args *infoarg)
{
      section *Ptr;
      auto char     s[BUFSIZ];
      auto char     s1[BUFSIZ];

      strcpy(s, CONF_SEC_FLAG);
      if ((Ptr = Set_Section(&SPtr,s,C_OVERWRITE | C_WARN | C_NOT_UNIQUE)) == NULL)
      {
            _print_msg("Can't set section `%s'!\n",CONF_SEC_FLAG);
            free_section(SPtr);
            return NULL;
      }

      sprintf(s1,"%d",infoarg->flag);
      strcpy(s, CONF_ENT_FLAGS);
      if (Set_Entry(Ptr,NULL,s,writeflags(infoarg->flag),C_OVERWRITE | C_WARN) == NULL)
      {
            _print_msg("Can't set entry `%s'!\n",CONF_ENT_FLAGS);
            free_section(SPtr);
            return NULL;
      }

      strcpy(s, CONF_ENT_PROG);
      if (Set_Entry(Ptr,NULL,s,infoarg->infoarg,C_OVERWRITE | C_WARN) == NULL)
      {
            _print_msg("Can't set entry `%s'!\n",CONF_ENT_PROG);
            free_section(SPtr);
            return NULL;
      }

      if (infoarg->user != NULL)
      {
            strcpy(s, CONF_ENT_USER);
            if (Set_Entry(Ptr,NULL,s,infoarg->user,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_USER);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (infoarg->group != NULL)
      {
            strcpy(s, CONF_ENT_GROUP);
            if (Set_Entry(Ptr,NULL,s,infoarg->group,C_OVERWRITE | C_WARN) == NULL)
            {
            _print_msg("Can't set entry `%s'!\n",CONF_ENT_GROUP);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (infoarg->interval != 0)
      {
            sprintf(s1,"%d",infoarg->interval);
            strcpy(s, CONF_ENT_INTVAL);
            if (Set_Entry(Ptr,NULL,s,s1,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_INTVAL);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (infoarg->time != NULL)
      {
            strcpy(s, CONF_ENT_TIME);
            if (Set_Entry(Ptr,NULL,s,infoarg->time,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_TIME);
                  free_section(SPtr);
                  return NULL;
            }
      }

      return SPtr;
}

/****************************************************************************/

static section* writevariables(section *SPtr)
{
      char *name;
      char *value;
      auto char     s[BUFSIZ];
      section *Ptr;


      strcpy(s, CONF_SEC_VAR);
      if ((Ptr = Set_Section(&SPtr,s,C_OVERWRITE | C_WARN)) == NULL)
      {
            _print_msg("Can't set section `%s'!\n",CONF_SEC_VAR);
            free_section(SPtr);
            return NULL;
      }

      if (GetNextEnv(Environment,&name,&value) == 0)
            do
            {
                  if (Set_Entry(Ptr,NULL,name,value,C_OVERWRITE | C_WARN) == NULL)
                  {
                        _print_msg("Can't set entry `%s'!\n",name);
                        free_section(SPtr);
                        return NULL;
                  }
            }
            while(GetNextEnv(NULL,&name,&value) == 0);

      return SPtr;
}

/****************************************************************************/

static section* writeglobal(section *SPtr)
{
      auto char     s[BUFSIZ];
      auto char     s1[BUFSIZ];
      int      IIndex = 0;
      section *Ptr;
      section *SubPtr = NULL;


      strcpy(s, CONF_SEC_GLOBAL);
      if ((Ptr = Set_Section(&SPtr,s,C_OVERWRITE | C_WARN)) == NULL)
      {
            _print_msg("Can't set section `%s'!\n",CONF_SEC_GLOBAL);
            free_section(SPtr);
            return NULL;
      }

      if (mycountry != NULL && mycountry[0] != '\0')
      {
            strcpy(s, CONF_ENT_COUNTRY);
            if (Set_Entry(Ptr,NULL,s,mycountry,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_COUNTRY);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (myarea != NULL && myarea[0] != '\0')
      {
            strcpy(s, CONF_ENT_AREA);
            if (Set_Entry(Ptr,NULL,s,myarea,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_AREA);
                  free_section(SPtr);
                  return NULL;
            }
      }

      strcpy(s, CONF_SEC_ISDNLOG);
      if ((Ptr = Set_Section(&SPtr,s,C_OVERWRITE | C_WARN)) == NULL)
      {
            _print_msg("Can't set section `%s'!\n",CONF_SEC_ISDNLOG);
            free_section(SPtr);
            return NULL;
      }

      if (reloadcmd != NULL)
      {
            strcpy(s, CONF_ENT_RELOAD);
            if (Set_Entry(Ptr,NULL,s,reloadcmd,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_RELOAD);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (stopcmd != NULL)
      {
            strcpy(s, CONF_ENT_STOP);
            if (Set_Entry(Ptr,NULL,s,stopcmd,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_STOP);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (rebootcmd != NULL)
      {
            strcpy(s, CONF_ENT_REBOOT);
            if (Set_Entry(Ptr,NULL,s,rebootcmd,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_REBOOT);
                  free_section(SPtr);
                  return NULL;
            }
      }

#if 0 /* Fixme: remove */
      if (CityWeekend != 0)
      {
            strcpy(s, CONF_ENT_CW);
            if (Set_Entry(Ptr,NULL,s,"yes",C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_CW);
                  free_section(SPtr);
                  return NULL;
            }
      }
#endif
      if (chargemax != 0)
      {
            strcpy(s, CONF_ENT_CHARGE);
            sprintf(s1, "%.2f",chargemax);
            if (Set_Entry(Ptr,NULL,s,s1,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_CHARGE);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (connectmax != 0)
      {
            strcpy(s, CONF_ENT_CONNECT);
            sprintf(s1, "%.10g,%d",connectmax,connectmaxmode);
            if (Set_Entry(Ptr,NULL,s,s1,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_CONNECT);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (bytemax != 0)
      {
            strcpy(s, CONF_ENT_BYTE);
            sprintf(s1, "%.10g,%d",bytemax,bytemaxmode);
            if (Set_Entry(Ptr,NULL,s,s1,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_BYTE);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (currency != NULL && currency_factor != 0)
      {
            strcpy(s, CONF_ENT_CURR);
            sprintf(s1, "%.3f,%s",currency_factor,currency);
            if (Set_Entry(Ptr,NULL,s,s1,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_CURR);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (IlabelPtr != NULL)
      {
            strcpy(s, CONF_ENT_ILABEL);
            if (Set_Entry(Ptr,NULL,s,IlabelPtr,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_ILABEL);
                  free_section(SPtr);
                  return NULL;
            }
      }

      if (OlabelPtr != NULL)
      {
            strcpy(s, CONF_ENT_OLABEL);
            if (Set_Entry(Ptr,NULL,s,OlabelPtr,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_OLABEL);
                  free_section(SPtr);
                  return NULL;
            }
      }

      IIndex = 0;

      if (start_procs.infoargs != NULL && start_procs.infoargs[0] != NULL)
      {
            while (start_procs.infoargs[IIndex] != NULL)
            {
                  if ((SubPtr = writeinfoargs(SubPtr,start_procs.infoargs[IIndex])) == NULL)
                  {
                        _print_msg("Can't set entry `%s'!\n",CONF_SEC_START);
                        free_section(SPtr);
                        return NULL;
                  }

                  IIndex++;
            }

            strcpy(s, CONF_SEC_START);

            if (Set_SubSection(Ptr,s,SubPtr,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_SEC_START);
                  free_section(SPtr);
                  return NULL;
            }
      }

      return SPtr;
}

/****************************************************************************/

static section* writeentry(section *SPtr, int Index)
{
      section *Ptr;
      int IIndex = 0;
      section *SubPtr = NULL;
      auto char     s[BUFSIZ];
      auto char     s1[BUFSIZ];


      if (Index < mymsns)
            strcpy(s,CONF_SEC_MSN);
      else
            strcpy(s,CONF_SEC_NUM);

      if ((Ptr = Set_Section(&SPtr,s,C_OVERWRITE | C_WARN | C_NOT_UNIQUE)) == NULL)
      {
            _print_msg("Can't set section `%s'!\n",CONF_SEC_NUM);
            free_section(SPtr);
            return NULL;
      }

      strcpy(s, CONF_ENT_NUM);
      if (Set_Entry(Ptr,NULL,s,known[Index]->num,C_OVERWRITE | C_WARN) == NULL)
      {
            _print_msg("Can't set entry `%s'!\n",CONF_ENT_NUM);
            free_section(SPtr);
            return NULL;
      }

      if (known[Index]->si != 0)
      {
            strcpy(s, CONF_ENT_SI);
            sprintf(s1,"%d",known[Index]->si);
            if (Set_Entry(Ptr,NULL,s,s1,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_SI);
                  free_section(SPtr);
                  return NULL;
            }
      }

      strcpy(s, CONF_ENT_ALIAS);
      if (Set_Entry(Ptr,NULL,s,known[Index]->who,C_OVERWRITE | C_WARN) == NULL)
      {
            _print_msg("Can't set entry `%s'!\n",CONF_ENT_ALIAS);
            free_section(SPtr);
            return NULL;
      }

      if (strcmp(known[Index]->interface,"-") != 0 && known[Index]->interface[0] != '\0')
      {
            strcpy(s, CONF_ENT_INTFAC);
            if (Set_Entry(Ptr,NULL,s,known[Index]->interface,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_ENT_INTFAC);
                  free_section(SPtr);
                  return NULL;
            }
      }

      strcpy(s, CONF_ENT_ZONE);
      sprintf(s1,"%d",known[Index]->zone);
      if (Set_Entry(Ptr,NULL,s,s1,C_OVERWRITE | C_WARN) == NULL)
      {
            _print_msg("Can't set entry `%s'!\n",CONF_ENT_ZONE);
            free_section(SPtr);
            return NULL;
      }

      IIndex = 0;

      if (known[Index]->infoargs != NULL && known[Index]->infoargs[0] != NULL)
      {
            while (known[Index]->infoargs[IIndex] != NULL)
            {
                  if ((SubPtr = writeinfoargs(SubPtr,known[Index]->infoargs[IIndex])) == NULL)
                  {
                        _print_msg("Can't set entry `%s'!\n",CONF_SEC_START);
                        free_section(SPtr);
                        return NULL;
                  }

                  IIndex++;
            }

            strcpy(s, CONF_SEC_START);

            if (Set_SubSection(Ptr,s,SubPtr,C_OVERWRITE | C_WARN) == NULL)
            {
                  _print_msg("Can't set entry `%s'!\n",CONF_SEC_START);
                  free_section(SPtr);
                  return NULL;
            }
      }

      return SPtr;
}

/****************************************************************************/

void setDefaults()
{
  if (currency == NULL)
    currency="EUR";

  if (currency_factor == 0.0)
    currency_factor = 0.062;

  currency_mode = AOC_UNITS;
} /* setDefaults */

/****************************************************************************/

int readconfig(char *_myname)
{
  register int cc;


  if (!(cc = readconfigfile(_myname)))
    setDefaults();

  return(cc);
} /* readconfig */

/****************************************************************************/

static int readconfigfile(char *_myname)
{
  auto char     file1[BUFSIZ];
  auto char     file2[BUFSIZ];
  struct stat buf1, buf2;
  int ret1, ret2;


  if (use_new_config) {
  sprintf(file1, "%s%c%s", confdir(), C_SLASH, CONFFILE);
  ret1 = stat(file1,&buf1);

      sprintf(file2, "%s%c%s", confdir(), C_SLASH, OLDCONFFILE);
  ret2 = stat(file2,&buf2);

      if (ret1 == 0)
      {
            if (access(file1,R_OK) == 0)
            {
                  if (ret2 == 0 && access(file2,R_OK) == 0)
                  {
                        if (buf1.st_mtime >= buf2.st_mtime)
                        {
                              return _readconfig(_myname);
                        }
                        else
                        {
                              if (readoldconfig(_myname) == 0)
                                    return writeconfig(_myname);
                              else
                              {
                                    _print_msg("Can't read file %s!\n",file2);
                                    return -1;
                              }
                        }
                  }
                  else
                  {
                        return _readconfig(_myname);
                  }
            }
            else
            {
                  _print_msg("Can't read file %s!\n",file1);
                  return -1;
            }
      }
      else
      {
            if (ret2 == 0 && access(file2,R_OK) == 0)
            {
                  if (readoldconfig(_myname) == 0)
                        return writeconfig(_myname);
                  else
                  {
                        _print_msg("Can't read file %s!\n",file2);
                        return -1;
                  }
            }
            else
            {
                  _print_msg("Can't read file %s!\n",file2);
                  return -1;
            }
      }

      return 0;
  }
  else
    return(readoldconfig(_myname));
}

/****************************************************************************/

section *read_isdnconf(section **_conf_dat)
{
      read_conffiles(_conf_dat,NULL);

      return *_conf_dat;
}

/****************************************************************************/

static int _readconfig(char *_myname)
{
  auto section *SPtr;
  auto int      i;
  int  cur_msn = 0;


  Myname         = _myname;
  mymsns         = 0;
  mycountry      = "";
  myarea         = "";
  currency       = NULL;
#if 0 /* Fixme: remove */
  CityWeekend    = 0;
#endif
  chargemax      = 0.0;
  connectmax     = 0;
  connectmaxmode = 0;
  bytemax        = 0;
  bytemaxmode    = 0;
  knowns         = retnum = 0;
  known          = NULL;
  reloadcmd      = RELOADCMD;
  stopcmd        = STOPCMD;
  rebootcmd      = REBOOTCMD;
  logfile        = LOGFILE;
  callfile       = NULL;
  callfmt        = NULL;
  holifile       = CONFIG_DATADIR"/holiday-"NATION".dat";
  countryfile      = CONFIG_DATADIR"/country.dat";
  rateconf       = CONFIG_I4LCONFDIR"/rate.conf";
  ratefile       = CONFIG_DATADIR"/rate-"NATION".dat";
  zonefile   = CONFIG_DATADIR"/zone-"NATION"-%s.cdb";
  destfile   = CONFIG_DATADIR"/dest.cdb";
  lcdfile        = NULL;
  start_procs.infoargs = NULL;
  start_procs.flags    = 0;
  conf_dat       = NULL;
  vboxpath      = NULL;
  vboxcommand1  = NULL;
  vboxcommand2  = NULL;
  mgettypath    = NULL;
  mgettycommand = NULL;
      isdnrep_defopts = NULL;


      ClearEnv(&Environment);

      if ((SPtr = read_isdnconf(&conf_dat)) == NULL)
            return -1;

      if (Replace_Variables(conf_dat) != 0)
            return -1;

      Set_Globals(conf_dat);

      while (SPtr != NULL)
      {
            if (!strcmp(SPtr->name,CONF_SEC_MSN))
                  Set_Numbers(SPtr,SPtr->name,cur_msn++);
            else
            if (!strcmp(SPtr->name,CONF_SEC_NUM))
                  Set_Numbers(SPtr,SPtr->name,NO_MSN);

            SPtr = SPtr->next;
      }

      for (i = 0; i < mymsns; i++)
            if (known[i]->num == NULL)
            {
            _print_msg("Error: MSN number %d is not set!\n",i+1);
            return -1;
      }

      return 0;
}

/****************************************************************************/

static char *Get_FmtStr(char *Ptr, char *name)
{
      static char *RetCode = NULL;
      char *ptr2;

      if (*Ptr != '\"')
            return Ptr;

      free(RetCode);
      ptr2 = RetCode = strdup(++Ptr);

      while(*Ptr != '\"')
      {
            if (*Ptr == '\0')
            {
            _print_msg("Warning: Missing character `\"' at the end of entry `%s'!\n",name);
            break;
      }

            if (*Ptr == '\\' && Ptr[1] == '\"')
                  Ptr++;

            *ptr2++ = *Ptr++;
      }

      *ptr2 = '\0';

      if (*Ptr == '\"')
            Ptr++;

      while(isspace(*Ptr)) Ptr++;

      if (*Ptr != '\0')
            _print_msg("Warning: Invalid token at the end of entry `%s'!\n",name);

  return RetCode;
}

/****************************************************************************/

static int Set_Globals(section *SPtr)
{
      auto int      cnt = 0;
      auto char  ***sPtr = lineformats;
      auto section *Ptr;
  auto entry   *CEPtr;

      if (sPtr != NULL)
      {
            while (sPtr != NULL)
            {
                  if (sPtr[0])
                        free(sPtr[0]);
                  if (sPtr[1])
                        free(sPtr[1]);
                  free(sPtr);

                  sPtr++;
            }

            free(lineformats);
      }

      if ((Ptr = Get_Section(SPtr,CONF_SEC_ISDNLOG)) != NULL)
      {
            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_ILABEL)) != NULL)
                  Set_ILabel(Get_FmtStr(CEPtr->value,CEPtr->name));
            else
                  Set_ILabel(NULL);

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_OLABEL)) != NULL)
                  Set_OLabel(Get_FmtStr(CEPtr->value,CEPtr->name));
            else
                  Set_OLabel(NULL);

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_START)) != NULL)
                  start_procs.infoargs = Set_Flags(CEPtr->subsection,&(start_procs.flags));

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_RELOAD)) != NULL)
                  reloadcmd = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_STOP)) != NULL)
                  stopcmd = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_REBOOT)) != NULL)
                  rebootcmd = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_LOGFILE)) != NULL)
                  logfile = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_CALLFILE)) != NULL)
                  callfile = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_CALLFMT)) != NULL)
                  callfmt = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_HOLIFILE)) != NULL)
                  holifile = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_COUNTRYFILE)) != NULL)
                  countryfile = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_ZONEFILE)) != NULL)
                  zonefile = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_RATECONF)) != NULL)
                  rateconf = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_RATEFILE)) != NULL)
                  ratefile = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_DESTFILE)) != NULL)
                  destfile = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_PRESELECT)) != NULL)
                  preselect = atoi(CEPtr->value);

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_VBN)) != NULL)
                  vbn = CEPtr->value;
            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_VBNLEN)) != NULL)
                  vbnlen = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_LCDFILE)) != NULL)
                  lcdfile = CEPtr->value;

#if 0 /* Fixme: remove */
            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_CW)) != NULL)
                  CityWeekend = toupper(*(CEPtr->value)) == 'Y'?1:0;
#endif
            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_CHARGE)) != NULL)
                  chargemax = strtod(CEPtr->value,NULL);

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_CONNECT)) != NULL)
        {
          if (sscanf(CEPtr->value,"%lg,%d", &connectmax, &connectmaxmode) != 2)
            _print_msg("%s: WARNING: Syntax error in `%s' in Line %d, ignored\n", Myname, CONF_ENT_CONNECT, ln);
        }

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_BYTE)) != NULL)
        {
          if (sscanf(CEPtr->value,"%lg,%d", &bytemax, &bytemaxmode) != 2)
            _print_msg("%s: WARNING: Syntax error in `%s' in Line %d, ignored\n", Myname, CONF_ENT_BYTE, ln);
        }

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_CURR)) != NULL)
        {
          currency_factor = atof(CEPtr->value);

          if ((currency = strchr(CEPtr->value, ',')) == NULL)
            _print_msg("%s: WARNING: Syntax error in `%s' in Line %d, ignored\n", Myname, CONF_ENT_CURR, ln);
          else
            currency++;
        }

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_VBOXPATH)) != NULL)
                  vboxpath = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_VBOXCMD1)) != NULL)
                  vboxcommand1 = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_VBOXCMD2)) != NULL)
                  vboxcommand2 = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_MGTYPATH)) != NULL)
                  mgettypath = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_MGTYCMD)) != NULL)
                  mgettycommand = CEPtr->value;

            if ((CEPtr = Get_Entry(Ptr->entries,CONF_ENT_REPOPTS)) != NULL)
                  isdnrep_defopts = CEPtr->value;

            CEPtr = Ptr->entries;
            cnt = 0;

        while (CEPtr != NULL)
        {
            if (!strncmp(CEPtr->name,CONF_ENT_REPFMT,strlen(CONF_ENT_REPFMT)))
            {
                  if ((lineformats = (char ***) realloc(lineformats,sizeof(char**)*(cnt+2))) == NULL)
                  {
                              _print_msg("%s: ERROR: Can't allocate memory!\n", Myname);
                              return 0;
                        }

                  if ((lineformats[cnt] = (char **) calloc(2,sizeof(char*))) == NULL)
                  {
                              _print_msg("%s: ERROR: Can't allocate memory!\n", Myname);
                              return 0;
                        }

                  if ((lineformats[cnt][0] = strdup(CEPtr->name+strlen(CONF_ENT_REPFMT))) == NULL)
                  {
                              _print_msg("%s: ERROR: Can't allocate memory!\n", Myname);
                              return 0;
                        }

                  if ((lineformats[cnt][1] = strdup(Get_FmtStr(CEPtr->value,CEPtr->name))) == NULL)
                  {
                              _print_msg("%s: ERROR: Can't allocate memory!\n", Myname);
                              return 0;
                        }

                        lineformats[++cnt] = NULL;
            }

            CEPtr = CEPtr->next;
        }
      }
      else
            _print_msg("%s: WARNING: There is no section `%s'!\n", Myname, CONF_SEC_ISDNLOG);

      if (mycountry == NULL && mycountry[0] == '\0') {
            _print_msg("%s: WARNING: Variable `%s' is not set!\n", Myname, CONF_ENT_COUNTRY);
            mycountry = "";
      }

      if (myarea == NULL && myarea[0] == '\0')
      {
            _print_msg("%s: WARNING: Variable `%s' is not set!\n", Myname, CONF_ENT_AREA);
            myarea = "";
      }
#if 0
  if (chargemax == 0)
  {
      _print_msg("%s: WARNING: Variable `%s' is not set, \nperforming no action when chargemax-overflow\n", Myname, CONF_ENT_CHARGE);
  }
#endif
      return 0;
}

/****************************************************************************/

static info_args** Set_Flags(section *SPtr, int *Flags)
{
      static int NumArgs;
      info_args** RetCode = NULL;
      entry* EPtr;
      int Flag;


      if (SPtr == NULL)
      {
            NumArgs = 0;
            return NULL;
      }

      RetCode = Set_Flags(SPtr->next,Flags);

      if (strcmp(SPtr->name,CONF_SEC_FLAG))
            return RetCode;

      RetCode = realloc(RetCode, sizeof(info_args*) * (NumArgs+2));
      RetCode[NumArgs] = (info_args*) calloc(1, sizeof(info_args));

      EPtr = SPtr->entries;

      while (EPtr != NULL)
      {
            if (!strcmp(EPtr->name,CONF_ENT_FLAGS))
            {
            if ((Flag = Get_Events(EPtr->value)) < 0)
                  _print_msg("Error: Invalid value of variable `%s'!\n",EPtr->name);
            else
            {
                    RetCode[NumArgs]->flag = Flag;
                    *Flags |= Flag;
                  }
            }
            else
            if (!strcmp(EPtr->name,CONF_ENT_PROG))
            {
              RetCode[NumArgs]->infoarg = EPtr->value;
            }
            else
            if (!strcmp(EPtr->name,CONF_ENT_USER))
            {
              RetCode[NumArgs]->user = EPtr->value;
            }
            else
            if (!strcmp(EPtr->name,CONF_ENT_GROUP))
            {
              RetCode[NumArgs]->group = EPtr->value;
            }
            else
            if (!strcmp(EPtr->name,CONF_ENT_INTVAL))
            {
                  if (EPtr->value != NULL)
                        RetCode[NumArgs]->interval = atoi(EPtr->value);
            }
            else
            if (!strcmp(EPtr->name,CONF_ENT_TIME))
            {
              RetCode[NumArgs]->time = EPtr->value;
            }
/*
            else
            _print_msg("Error: Invalid variable `%s'!\n",EPtr->name);
*/

            EPtr = EPtr->next;
      }


  RetCode[++NumArgs] = NULL;

  return RetCode;
}

/****************************************************************************/

static int Get_Events(char* Flags)
{
      int flag = 0, Index = 0;


      while (*Flags != '\0')
      {
            while (isspace(*Flags) || *Flags == C_FLAG_DELIM) Flags++;

            if (*Flags != '\0')
            {
                  switch (toupper(*Flags))
                  {
                              case 'I' : flag |= RING_INCOMING; break;
                              case 'O' : flag |= RING_OUTGOING; break;
                              case 'R' : flag |= RING_RING    ; break;
                              case 'C' : flag |= RING_CONNECT ; break;
                              case 'B' : flag |= RING_BUSY    ; break;
                              case 'A' : flag |= RING_AOCD    ; break;
                              case 'E' : flag |= RING_ERROR   ; break;
                              case 'H' : flag |= RING_HANGUP  ; break;
                              case 'K' : flag |= RING_KILL    ; break;
                              case 'L' : flag |= RING_LOOP    ; break;
                              case 'S' : flag |= RING_SPEAK   ; break;
                              case 'P' : flag |= RING_PROVIDER; break;
                              case 'U' : flag |= RING_UNIQUE  ; break;

                              default : _print_msg( "%s: WARNING: Unknown flag `%c' in file \"%s\" line %d, ignored\n", Myname, *Flags, CONFFILE, ln);
                                        break;
                  } /* switch */

                  Flags++;
            }

            Index++;
      }

      return flag;
}

/****************************************************************************/

static int Set_Numbers(section *SPtr, char *Section, int msn)
{
  auto entry *CEPtr;
  auto char  *num = 0, *who = 0;
  auto int    Index;


      if ((CEPtr = Get_Entry(SPtr->entries,CONF_ENT_NUM)) != NULL)
            num = CEPtr->value;
      else
      {
            _print_msg("%s: ERROR: There is no variable `%s' in section `%s'!\n", Myname, CONF_ENT_NUM, Section);
            num = S_UNKNOWN;
      }

      if ((CEPtr = Get_Entry(SPtr->entries,CONF_ENT_ALIAS)) != NULL)
            who = CEPtr->value;
      else
      {
            _print_msg("%s: ERROR: There is no variable `%s' in section `%s'!\n", Myname, CONF_ENT_ALIAS, Section);
            who = S_UNKNOWN;
      }

      if (*num && *who) {

            if ((Index = Set_known_Size(msn)) >= 0) {

                  known[Index]->num       = num;
                  known[Index]->who       = who;
                  known[Index]->day     = -1;
                  known[Index]->charge  = 0.0;
                  known[Index]->rcharge = 0.0;
                  known[Index]->scharge = 0.0;

                  known[Index]->month   = -1;
                  known[Index]->online  = 0.0;
                  known[Index]->sonline = 0.0;

                  known[Index]->bytes   = 0.0;
                  known[Index]->sbytes  = 0.0;

                  if ((CEPtr = Get_Entry(SPtr->entries,CONF_ENT_ZONE)) != NULL)
                        known[Index]->zone = atoi(CEPtr->value);
#if 0 /* FIXME - or REMOVEME */
                  else {
                    if (msn < 0) {
                            if ((known[Index]->zone = area_diff(NULL, num)) < 1) {
                              if (is_sondernummer(num, DTAG)) /* Fixme: DTAG is specific to Germany */
                          known[Index]->zone = SONDERNUMMER;
                              else {
                          _print_msg("%s: WARNING: There is no variable `%s' for number `%s' -- assuming GermanCall!\n", Myname, CONF_ENT_ZONE, num);
                              known[Index]->zone = GERMANCALL;
                              } /* else */
                            } /* if */
                        }
                        else
                      known[Index]->zone = CITYCALL; /* sich selbst anrufen kostet CityCall */
                  }
#endif
                  if ((CEPtr = Get_Entry(SPtr->entries,CONF_ENT_INTFAC)) != NULL)
                        known[Index]->interface = CEPtr->value;
                  else
                        known[Index]->interface = "-";

                  if ((CEPtr = Get_Entry(SPtr->entries,CONF_ENT_SI)) != NULL)
                        known[Index]->si = strtol(CEPtr->value, NIL, 0);
                  else
                        known[Index]->si = 0;

                  if ((CEPtr = Get_Entry(SPtr->entries,CONF_ENT_START)) != NULL)
                        known[Index]->infoargs = Set_Flags(CEPtr->subsection,&(known[Index]->flags));
                  else
                        known[Index]->infoargs = NULL;
            }
            else
            {
                  _print_msg("%s: ERROR: Can't allocate memory!\n", Myname);
                  return -1;
            }
      }

      return 0;
}

/****************************************************************************/

static int Set_known_Size(int msn)
{
      int Index;
      KNOWN **Ptr;

      if (knowns == 0)
            mymsns = 0;

      if (msn < 0)
      {
            if ((known = (KNOWN **) realloc(known, sizeof(KNOWN *) * (knowns + 1))) == NULL)
                  return -1;

            knowns++;
      }
      else
      if (mymsns <= msn)
      {
            int NewKnowns = msn+knowns-mymsns+1;

            if ((Ptr = (KNOWN **) calloc(NewKnowns, sizeof(KNOWN *))) == NULL)
                  return -1;

            if (known != NULL)
            {
                  memcpy(Ptr,known,sizeof(KNOWN*) * (mymsns));
                  memcpy(&(Ptr[msn+1]),&(known[mymsns]),sizeof(KNOWN*) * (knowns-mymsns));
                  free(known);
            }

            known = Ptr;
            knowns= NewKnowns;
            mymsns = msn+1;
      }

      if (msn < 0)
            Index = knowns - 1;
      else
            Index = msn;

  if ((known[Index] = (KNOWN *) calloc(1,sizeof(KNOWN))) == NULL)
      return -1;

      return Index;
}

/****************************************************************************/

static int readoldconfig(char *myname)
{
  register char *p;
  register int     i;
  auto     int   start_ln = 0;
  auto     FILE *f;
  auto     char  s[BUFSIZ];
  auto         char *num, *who, *zone, *flags, *interface;
  auto     char *Ptr;

      ln = 0;

  mymsns     = 3;
  mycountry     = "";
  myarea   = "";
  currency   = NULL;
  chargemax  = 0.0;
  connectmax = 0.0;
  bytemax    = 0.0;
  connectmaxmode = 0;
  bytemaxmode = 0;
  knowns     = retnum = 0;
  known      = (KNOWN **)NULL;
  start_procs.infoargs = NULL;
  start_procs.flags    = 0;


  sprintf(s, "%s%c%s", confdir(), C_SLASH, OLDCONFFILE);

  if ((f = fopen(s, "r")) != (FILE *)NULL) {

    while (FGets(s, BUFSIZ, f, &ln) != NULL) {
      if ((*s != '\0') && (*s != '\n')) {

        if ((p = strchr(s, '\n'))) {
          *p = 0;

          while (*--p == ' ')
            *p = 0;
        } /* if */

        if (!IsVariable(s))
        {
          num       = s;
          who         = NextItem(num, 1);
          zone      = NextItem(who, 0);
          interface = NextItem(zone, 0);
          flags     = NextItem(interface, 0);

          if (*num && *who) {
            known = realloc(known, sizeof(KNOWN *) * (knowns + 1));

            if ((known[knowns] = (KNOWN *)malloc(sizeof(KNOWN)))) {

              if ((p = strchr(num, ','))) { /* MSN,SI */
                    known[knowns]->si      = atoi(p + 1);
            *p = 0;
              }
              else
                    known[knowns]->si      = 0;

                  known[knowns]->num       = strdup(num);
                  known[knowns]->who       = strdup(who);
                  known[knowns]->zone      = atoi(zone);
            known[knowns]->interface = strdup(interface);
              known[knowns]->flags     = 0;

              SetFlags(known[knowns], flags);

            known[knowns]->dur[CALLING] = known[knowns]->dur[CALLED] = 0.0;
            known[knowns]->eh = 0;
            known[knowns]->usage[DIALOUT] = known[knowns]->usage[DIALIN] = 0;

                  known[knowns]->day     = -1;
                  known[knowns]->charge  = 0.0;
                  known[knowns]->rcharge = 0.0;
                  known[knowns]->scharge = 0.0;

                  known[knowns]->month   = -1;
              known[knowns]->online  = 0.0;
              known[knowns]->sonline = 0.0;

              known[knowns]->bytes   = 0.0;
            known[knowns]->sbytes  = 0.0;

              knowns++;
            }
            else {
              _print_msg("%s: WARNING: Out of memory in Line %d\n", myname, ln);
              break;
            } /* else */
          }
          else {
              _print_msg("%s: WARNING: Syntax error in Line %d, ignored\n", myname, ln);
            /* break; */
          } /* else */
        } /* else */
        else
          if (start_ln == 0 && getenv(VAR_START) != NULL)
            start_ln = ln;

      } /* if */

    } /* while */

    fclose(f);

    if ((Ptr = getenv(VAR_MYMSNS)) == NULL) {
      _print_msg("%s: WARNING: Variable `%s' is not set, now is 3!\n", myname, VAR_MYMSNS);
      mymsns = 3;
    }
    else
      mymsns = atoi(Ptr);

    if ((myarea = getenv(VAR_MYAREA)) == NULL)
      _print_msg("%s: WARNING: Variable `%s' is not set!\n", myname, VAR_MYAREA);

    if ((mycountry = getenv(VAR_MYCOUNTRY)) == NULL)
      _print_msg("%s: WARNING: Variable `%s' is not set!\n", myname, VAR_MYCOUNTRY);

    if ((Ptr = getenv(VAR_CURRENCY)) != NULL) {
      currency_factor = atof(Ptr);

      if ((currency = strchr(Ptr, ',')) == NULL)
      _print_msg("%s: WARNING: Syntax error in `CURRENCY' in Line %d, ignored\n", myname, ln);
      else
        currency++;
    }

    if ((Ptr = getenv(VAR_CHARGEMAX)) == NULL)
      _print_msg("%s: WARNING: Variable `%s' is not set, \nperforming no action when chargemax-overflow\n", myname, VAR_CHARGEMAX);
    else
      chargemax = strtod(Ptr, NULL);

    if ((Ptr = getenv(VAR_CONNECTMAX)) == NULL)
      _print_msg("%s: WARNING: Variable `%s' is not set, \nperforming no action when connectmax-overflow\n", myname, VAR_CONNECTMAX);
    else {
      if (sscanf(Ptr, "%lg,%d", &connectmax, &connectmaxmode) != 2)
      _print_msg("%s: WARNING: Syntax error in `%s' in Line %d, ignored\n", Myname, VAR_CONNECTMAX, ln);
    } /* else */

    if ((Ptr = getenv(VAR_BYTEMAX)) == NULL)
      _print_msg("%s: WARNING: Variable `%s' is not set, \nperforming no action when connectmax-overflow\n", myname, VAR_BYTEMAX);
    else {
      if (sscanf(Ptr, "%lg,%d", &bytemax, &bytemaxmode) != 2)
      _print_msg("%s: WARNING: Syntax error in `%s' in Line %d, ignored\n", Myname, VAR_BYTEMAX, ln);
    } /* else */

    if ((Ptr = getenv(VAR_START)) != NULL) {
      ln = start_ln;
      SetFlags(&start_procs, Ptr);
    }

    Set_ILabel(getenv(VAR_ILABEL));
    Set_OLabel(getenv(VAR_OLABEL));

/* Wenn eine unbekannte Varible kommt, stuerzt isdnlog einfach ab  ;-) !!!!*/
    if ((mycountry != NULL && mycountry[0] == '\0') &&
        (myarea != NULL && myarea[0] == '\0')         )
    {
      for (i = 0; i < mymsns; i++) {
        if (known != NULL && known[i]->num != NULL) {
          sprintf(s, "%s%s%s", mycountry, myarea, known[i]->num);
          free(known[i]->num);
          known[i]->num  = strdup(s);
        }
        else
        {
            _print_msg("%s: ERROR: There are only %d MSN's, expected %d!\n",myname, i, mymsns);
          return -1;
        }
      } /* for */
    } /* if */
  }
  else
  {
    _print_msg("%s: WARNING: Can't open ``%s''\n", myname, s);
    return -1;
  }

  return 0;
} /* readoldconfig */

/****************************************************************************/

void discardconfig(void)
{
  register int i,j;

      free_section(conf_dat);
      ClearEnv(&Environment);

  for (i = 0; i < knowns; i++) {
  /* Unnoetig mit neuer readconfig
    free(known[i]->num);
    free(known[i]->who);
    free(known[i]->interface);
  */

      for (j = 0; known[i]->infoargs != NULL && known[i]->infoargs[j] != NULL; j++) {
      /* Unnoetig mit neuer readconfig
      free(known[i]->infoargs[j]->time);
      free(known[i]->infoargs[j]->infoarg);
    */
      free(known[i]->infoargs[j]);
      }

            free(known[i]->infoargs);
    free(known[i]);
  } /* for */

  free(known);

  currency = NULL;
  mycountry   = "";
  myarea = "";

  if (start_procs.infoargs != NULL)
  {
      int j;
    for (j = 0; start_procs.infoargs != NULL && start_procs.infoargs[j] != NULL; j++) {
    /* Unnoetig mit neuer readconfig
      free(start_procs.infoargs[j]->time);
      free(start_procs.infoargs[j]->infoarg);
     */
      free(start_procs.infoargs[j]);
    }
        free(start_procs.infoargs);
      }

} /* discardconfig */

/****************************************************************************/

static int SetEnv(char ****EnvPtr, char *name, char *value)
{
      int elem = 2;
      char ***CurEnvPtr = NULL;


      if (setenv(name,value,1) != 0)
            return -1;

      if (!strcmp(name,CONF_ENT_AREA)    || !strcmp(name,CONF_ENT_CURR)   ||
          !strcmp(name,CONF_ENT_START)   || !strcmp(name,CONF_ENT_ILABEL) ||
          !strcmp(name,CONF_ENT_OLABEL)  || !strcmp(name,VAR_MYMSNS)      ||
          !strcmp(name,CONF_ENT_COUNTRY) || !strcmp(name,CONF_ENT_CHARGE) ||
          !strcmp(name,CONF_ENT_RELOAD)  || !strcmp(name,CONF_ENT_STOP)   ||
          !strcmp(name,CONF_ENT_REBOOT)  || !strcmp(name,CONF_ENT_CONNECT)||
          !strcmp(name,CONF_ENT_AREA)    || !strcmp(name,CONF_ENT_CONNECT)||
          !strcmp(name,CONF_ENT_BYTE)                                       )
            return 0;

      CurEnvPtr = *EnvPtr;

      if (CurEnvPtr != NULL)
            while(*CurEnvPtr != NULL)
            {
                  elem++;
                  CurEnvPtr++;
            }

      CurEnvPtr = NULL;

      if ((*EnvPtr = (char***) realloc(*EnvPtr,sizeof(char**)*elem)) == NULL)
            return -1;

      (*EnvPtr)[elem-1] = NULL;

      if (((*EnvPtr)[elem-2] = (char**) calloc(2,sizeof(char*))) == NULL)
            return -1;

      if (((*EnvPtr)[elem-2][0] = strdup(name)) == NULL)
            return -1;

      if (((*EnvPtr)[elem-2][1] = strdup(value)) == NULL)
            return -1;

      return 0;
}

/****************************************************************************/

static int GetNextEnv(char ***EnvPtr, char **name, char **value)
{
      static char ***CurEnvPtr = NULL;


      if (EnvPtr != NULL)
            CurEnvPtr = EnvPtr;
      else
      {
            if (CurEnvPtr == NULL || CurEnvPtr[0] == NULL)
                  return -1;
            else
                  CurEnvPtr++;
      }


      if (CurEnvPtr[0] == NULL || CurEnvPtr[0][0] == NULL || CurEnvPtr[0][1] == NULL)
            return -1;

      *name  = CurEnvPtr[0][0];
      *value = CurEnvPtr[0][1];

      return 0;
}

/****************************************************************************/

static int ClearEnv(char ****EnvPtr)
{
      char ***CurEnvPtr = NULL;
      CurEnvPtr = *EnvPtr;

      if (CurEnvPtr == NULL)
            return 0;

      while(CurEnvPtr[0] != NULL)
      {
            free(CurEnvPtr[0][0]);
            free(CurEnvPtr[0][1]);
            free(CurEnvPtr[0]);
            CurEnvPtr++;
      }

      free(*EnvPtr);
      *EnvPtr = CurEnvPtr = NULL;

      return 0;
}

/****************************************************************************/

static int Set_ILabel(char *value)
{
            if ((IlabelPtr = value) == NULL)
                  IlabelPtr = "%b %e %T %ICall to tei %t from %N2 on %n2";

            sprintf(ilabel, "%%s%s  %%s%%s", IlabelPtr);

    return 0;
}

/****************************************************************************/

static int Set_OLabel(char *value)
{
            if ((OlabelPtr = value) == NULL)
                  OlabelPtr = "%b %e %T %Itei %t calling %N2 with %n2";

            sprintf(olabel, "%%s%s  %%s%%s", OlabelPtr);

    return 0;
}

/****************************************************************************/

Generated by  Doxygen 1.6.0   Back to index