/*
 * ----------------------------------------------------------------
 * Night Light IRC Proxy - Configuration Functions
 * ----------------------------------------------------------------
 * Copyright (C) 2006-2007 Jonas Kvinge <jonas@night-light.net>
 * All rights reserved.
 *
 * 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 of the License, 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Last modified by:
 * Jonas Kvinge (25.11.2007)
 *
 */

#define CONF_C

#define NEED_SYS_TYPES_H 1		/* Extra types */
#define NEED_SYS_PARAM_H 1		/* Some systems need this */
#define NEED_LIMITS_H 0			/* Kernel limits */
#define NEED_STDARG_H 1			/* va_list, etc */
#define NEED_ERRNO_H 1			/* errno */
#define NEED_CTYPE_H 1			/* isdigit(), etc */
#define NEED_NETINET_IN_H 0		/* in_addr, sockaddr_in, etc */
#define NEED_ARPA_INET_H 0		/* inet_ntoa(), inet_aton(), etc */
#define NEED_STDIO_H 1			/* Standard C UNIX functions */
#define NEED_STDLIB_H 1			/* malloc(), exit(), atoi(), etc */
#define NEED_TIME_H 1			/* time(), etc */
#define NEED_SYSCTL_H 0			/* sysctl(), etc */
#define NEED_SYS_STAT_H 0		/* chmod(), mkdir(), etc */
#define NEED_SYS_UIO_H 0		/* iovec, etc */
#define NEED_FCNTL_H 1			/* open(), creat(), fcntl(), etc */
#define NEED_SYS_IOCTL_H 0		/* ioctl(), etc */
#define NEED_SYS_FILIO_H 0		/* Solaris need this for ioctl(), etc */
#define NEED_UNISTD_H 1			/* Unix standard functions */
#define NEED_STRING_H 1			/* C string functions */
#define NEED_SIGNAL_H 0			/* Signal functions */
#define NEED_SYS_SOCKET_H 0		/* Socket functions */
#define NEED_NETDB_H 0			/* Network database functions */
#define NEED_ARPA_NAMESER_H 0		/* Nameserver definitions */
#define NEED_GETUSERPW_HEADERS 0 	/* Functions to retrive system passwords */

#include "includes.h"

#include "conf.h"

/* VARIABLES - JONAS (15.11.2006) */

struct Conf_Struct ConfS = { 0 };

extern struct PrintFile_Struct PrintFileS[];

/* CONF_READ FUNCTION - JONAS (15.11.2006) */

signed long int conf_read(void) {

  char File[FILELEN+1] = "";
  FILE *FilePT = NULL;
  unsigned short int Count = 0;

  conf_init();

  if (ConfS.File[0] != '/') {
    char *PathPT = NULL;
    PathPT = getenv("HOME");
    if (PathPT != NULL) {
      strncpy(File, PathPT, FILELEN);
      if (File[strlen(File)] != '/') { strncat(File, "/", (FILELEN - strlen(File))); }
      strncat(File, ".ircproxy/", (FILELEN - strlen(File)));
      strncat(File, ConfS.File, (FILELEN - strlen(File)));
      FilePT = fopen(File, "r");
    }
    if (FilePT == NULL) {
      strcpy(File, "/usr/share/ircproxy/");
      strncat(File, ConfS.File, (FILELEN - strlen(File)));
      FilePT = fopen(File, "r");
      if (FilePT == NULL) {
        strcpy(File, "/etc");
        strncat(File, ConfS.File, (FILELEN - strlen(File)));
        FilePT = fopen(File, "r");
        if (FilePT == NULL) {
          printf("Unable to locate configuration file, run ircproxyd -c to specify configuration file.\n");
          exit(1);
        }
      }
    }
    ConfS.File = strrealloc(ConfS.File, File);
  }
  else {
    FilePT = fopen(ConfS.File, "r");
    if (FilePT == NULL) {
      printf("Unable to open configuration file %s: [%d] %s\n", ConfS.File, errno, strerror(errno));
      exit(1);
    }
  }

  FOREVERLOOP {

    char Line[LINELEN+1] = "";
    char *LinePT = NULL;
    char *TempPT = NULL;
    char *EntryPT = NULL;
    char *DataPT = NULL;
    unsigned short int Skip = FALSE;

    memset(&Line, 0, LINELEN+1);
    TempPT = fgets(Line, LINELEN, FilePT);
    if (TempPT == NULL) { break; }
    ++Count;
    LinePT = Line;

    while ((TempPT = strchr(LinePT, '\r')) != NULL) { *TempPT = '\0'; }
    while ((TempPT = strchr(LinePT, '\n')) != NULL) { *TempPT = '\0'; }
    while ((TempPT = strchr(LinePT, '\t')) != NULL) { *TempPT = ' '; }

    while ((LinePT[0] == ' ') || (LinePT[0] == '\t')) { ++LinePT; }
    if ((LinePT[0] == '#') || (LinePT[0] == ';') || (LinePT[0] == '\0')) { continue; }

    if (strchr(LinePT, '=') == NULL) { /* This isn't a main configuration file entry */
      EntryPT = LinePT;
      StrMovePastToken(LinePT, ' ');
      if (strcasecmp(EntryPT, "CONNECTION") == FALSE) { Skip = TRUE; continue; }
      if (EntryPT[0] == '}') { Skip = FALSE; continue; }
      continue;
    }

    if (Skip == TRUE) { continue; }

    EntryPT = LinePT;
    StrMovePastToken(LinePT, '=');
    DataPT = LinePT;

    if ((DataPT == NULL) || (DataPT[0] == '\0')) {
      printf("Configuration error in file %s line %d: Expecting more data.\n", File, Count);
      exit(1);
    }

    while ((TempPT = strchr(DataPT, '\"')) != NULL) {
      if (TempPT == DataPT) { DataPT++; }
      *TempPT = '\0';
    }
    if ((DataPT == NULL) || (DataPT[0] == '\0')) {
      printf("Configuration error in file %s line %d: Expecting more data.\n", File, Count);
      exit(1);
    }

    if (strcasecmp(EntryPT, "EUSER") == FALSE) { ConfS.EUser = strrealloc(ConfS.EUser, DataPT); }
    else if (strcasecmp(EntryPT, "EGROUP") == FALSE) { ConfS.EGroup = strrealloc(ConfS.EGroup, DataPT); }
    else if (strcasecmp(EntryPT, "CHDIR") == FALSE) {
      if ((strcasecmp(DataPT, "y") == FALSE) || (strcasecmp(DataPT, "yes") == FALSE)) { ConfS.ChDir = TRUE; }
      else { ConfS.ChDir = FALSE; }
    }
    else if (strcasecmp(EntryPT, "CHDIRPATH") == FALSE) { ConfS.ChDirPath = strrealloc(ConfS.ChDirPath, DataPT); }
    else if (strcasecmp(EntryPT, "DATAPATH") == FALSE) { ConfS.DataPath = strrealloc(ConfS.DataPath, DataPT); }
    else if (strcasecmp(EntryPT, "LOGPATH") == FALSE) { ConfS.LogPath = strrealloc(ConfS.LogPath, DataPT); }
    else if (strcasecmp(EntryPT, "PIDFILE") == FALSE) { ConfS.PIDFile = strrealloc(ConfS.PIDFile, DataPT); }
    else if (strcasecmp(EntryPT, "MAXCLIENTS") == FALSE) { ConfS.MaxClients = atoi(DataPT); }
    else if (strcasecmp(EntryPT, "CLIENT_SHOWDENYREASON") == FALSE) {
      if ((strcasecmp(DataPT, "y") == FALSE) || (strcasecmp(DataPT, "yes") == FALSE) || (strcasecmp(DataPT, "1") == FALSE)) { ConfS.ClientShowDenyReason = TRUE; }
      else { ConfS.ClientShowDenyReason = FALSE; }
    }
    else if (strcasecmp(EntryPT, "CLIENT_MAXSENDQ") == FALSE) { ConfS.ClientMaxSendQ = atoi(DataPT); }
    else if (strcasecmp(EntryPT, "CLIENT_MAXLINESPERSEC") == FALSE) {
      TempPT = DataPT;
      StrMovePastToken(DataPT, ':');
      if (DataPT == NULL) { DataPT = "10"; } 
      ConfS.ClientMaxLines = atoi(TempPT);
      ConfS.ClientLineFloodTTL = atoi(DataPT);
    }

    else if (strcasecmp(EntryPT, "ACCESS_CONFFILE") == FALSE) { ConfS.AccessConfFile = strrealloc(ConfS.AccessConfFile, DataPT); }
    else if (strcasecmp(EntryPT, "LISTEN_CONFFILE") == FALSE) { ConfS.ListenConfFile = strrealloc(ConfS.ListenConfFile, DataPT); }
    else if (strcasecmp(EntryPT, "USER_CONFFILE") == FALSE) { ConfS.UserConfFile = strrealloc(ConfS.UserConfFile, DataPT); }
    else if (strcasecmp(EntryPT, "CONN_CONFFILE") == FALSE) { ConfS.ConnConfFile = strrealloc(ConfS.ConnConfFile, DataPT); }
    else if (strcasecmp(EntryPT, "AUTOOP_CONFFILE") == FALSE) { ConfS.AutoOPConfFile = strrealloc(ConfS.AutoOPConfFile, DataPT); }
    else if (strcasecmp(EntryPT, "IDENT_CONFFILE") == FALSE) { ConfS.IdentConfFile = strrealloc(ConfS.IdentConfFile, DataPT); }

    else if (strcasecmp(EntryPT, "MAINLOGFILE") == FALSE) { ConfS.MainLogFile = strrealloc(ConfS.MainLogFile, DataPT); }
    else if (strcasecmp(EntryPT, "ERRORLOGFILE") == FALSE) { ConfS.ErrorLogFile = strrealloc(ConfS.ErrorLogFile, DataPT); }
    else if (strcasecmp(EntryPT, "DEBUGLOGFILE") == FALSE) { ConfS.DebugLogFile = strrealloc(ConfS.DebugLogFile, DataPT); }
    else if (strcasecmp(EntryPT, "SSLSUPPORT") == FALSE) {
      if ((strcasecmp(DataPT, "y") == FALSE) || (strcasecmp(DataPT, "yes") == FALSE) || (strcasecmp(DataPT, "1") == FALSE)) {
        ConfS.SSLSupport = TRUE;
#if !SSL_SUPPORT
        printf("Configuration error in file %s line %d: %s is not compiled with SSL support.\n", File, Count, PACKAGE);
        exit(1);
#endif
      }
      else { ConfS.SSLSupport = FALSE; }
    }
    else if (strcasecmp(EntryPT, "SSLSERVERCERTIFICATE") == FALSE) { ConfS.SSLServerCertificate = strrealloc(ConfS. SSLServerCertificate, DataPT); }
    else if (strcasecmp(EntryPT, "SSLSERVERPRIVATEKEY") == FALSE) { ConfS.SSLServerPrivateKey = strrealloc(ConfS.SSLServerPrivateKey, DataPT); }
    else if (strcasecmp(EntryPT, "SSLCLIENTCERTIFICATE") == FALSE) { ConfS.SSLClientCertificate = strrealloc(ConfS. SSLClientCertificate, DataPT); }
    else if (strcasecmp(EntryPT, "SSLCLIENTPRIVATEKEY") == FALSE) { ConfS.SSLClientPrivateKey = strrealloc(ConfS.SSLClientPrivateKey, DataPT); }
    else if (strcasecmp(EntryPT, "SSLSERVERCIPHERS") == FALSE) { ConfS.SSLServerCiphers = strrealloc(ConfS.SSLServerCiphers, DataPT); }
    else if (strcasecmp(EntryPT, "SSLCLIENTCIPHERS") == FALSE) { ConfS.SSLClientCiphers = strrealloc(ConfS.SSLClientCiphers, DataPT); }

    else if (strcasecmp(EntryPT, "CRYPTPASS") == FALSE) {
      if ((strcasecmp(DataPT, "y") == FALSE) || (strcasecmp(DataPT, "yes") == FALSE) || (strcasecmp(DataPT, "1") == FALSE)) { ConfS.CryptPass = TRUE; }
      else { ConfS.CryptPass = FALSE; }
    }
    else if (strcasecmp(EntryPT, "UNIXPASSWD") == FALSE) {
      if ((strcasecmp(DataPT, "y") == FALSE) || (strcasecmp(DataPT, "yes") == FALSE) || (strcasecmp(DataPT, "1") == FALSE)) { ConfS.UnixPasswd = TRUE; }
      else { ConfS.UnixPasswd = FALSE; }
    }
    else { continue; }

  }

  fclose(FilePT);

  PrintFileS[1].Name = strrealloc(PrintFileS[1].Name, ConfS.MainLogFile);
  PrintFileS[2].Name = strrealloc(PrintFileS[2].Name, ConfS.ErrorLogFile);
#if DEBUG
  PrintFileS[3].Name = strrealloc(PrintFileS[3].Name, ConfS.DebugLogFile);
#endif

  return(SUCCESS);

}

/* CONF_INIT FUNCTION - JONAS (15.11.2006) */

void conf_init(void) {

  /* ConfS.File is set in main.c */ 
  if (ConfS.File == NULL) ConfS.File = strdup(CONFFILE);
  ConfS.EUser = strrealloc(ConfS.EUser, EUSER);
  ConfS.EGroup = strrealloc(ConfS.EGroup, EGROUP);
  ConfS.ChDir = FALSE;
  ConfS.ChDirPath = strrealloc(ConfS.ChDirPath, CHDIRPATH);
  ConfS.DataPath = strrealloc(ConfS.DataPath, DATAPATH);
  ConfS.LogPath = strrealloc(ConfS.LogPath, LOGPATH);
  ConfS.PIDFile = strrealloc(ConfS.PIDFile, PIDFILE);
  ConfS.MaxClients = MAXCLIENTS;
  ConfS.ClientShowDenyReason = CLIENT_SHOWDENYREASON;
  ConfS.ClientMaxSendQ = CLIENT_MAXSENDQ;
  ConfS.ClientMaxLines = CLIENT_MAXLINES;
  ConfS.ClientLineFloodTTL = CLIENT_LINEFLOODTTL;
  ConfS.AccessConfFile = strrealloc(ConfS.AccessConfFile, ACCESS_CONFFILE);
  ConfS.ListenConfFile = strrealloc(ConfS.ListenConfFile, LISTEN_CONFFILE);
  ConfS.UserConfFile = strrealloc(ConfS.UserConfFile, USER_CONFFILE);
  ConfS.ConnConfFile = strrealloc(ConfS.ConnConfFile, CONN_CONFFILE);
  ConfS.AutoOPConfFile = strrealloc(ConfS.AutoOPConfFile, AUTOOP_CONFFILE);
  ConfS.IdentConfFile = strrealloc(ConfS.IdentConfFile, IDENT_CONFFILE);
  ConfS.MainLogFile = strrealloc(ConfS.MainLogFile, MAINLOGFILE);
  ConfS.ErrorLogFile = strrealloc(ConfS.ErrorLogFile, ERRORLOGFILE);
  ConfS.DebugLogFile = strrealloc(ConfS.DebugLogFile, DEBUGLOGFILE);
  ConfS.CryptPass = CRYPTPASS;
  ConfS.UnixPasswd = UNIXPASSWD;
  ConfS.SSLSupport = SSLSUPPORT;
  ConfS.SSLServerCertificate = strrealloc(ConfS.SSLServerCertificate, SSLSERVERCERTIFICATE);
  ConfS.SSLServerPrivateKey = strrealloc(ConfS.SSLServerPrivateKey, SSLSERVERPRIVATEKEY);
  ConfS.SSLClientCertificate = strrealloc(ConfS.SSLClientCertificate, SSLCLIENTCERTIFICATE);
  ConfS.SSLClientPrivateKey = strrealloc(ConfS.SSLClientPrivateKey, SSLCLIENTPRIVATEKEY);
  ConfS.SSLServerCiphers = strrealloc(ConfS.SSLServerCiphers, SSLSERVERCIPHERS);
  ConfS.SSLClientCiphers = strrealloc(ConfS.SSLClientCiphers, SSLCLIENTCIPHERS);

}

/* CONF_DESTROY FUNCTION - JONAS (15.11.2006) */

void conf_destroy(void) {

  FREE(ConfS.File);
  FREE(ConfS.EUser);
  FREE(ConfS.EGroup);
  FREE(ConfS.ChDirPath);
  FREE(ConfS.DataPath);
  FREE(ConfS.LogPath);
  FREE(ConfS.PIDFile);
  FREE(ConfS.AccessConfFile);
  FREE(ConfS.ListenConfFile);
  FREE(ConfS.UserConfFile);
  FREE(ConfS.ConnConfFile);
  FREE(ConfS.AutoOPConfFile);
  FREE(ConfS.IdentConfFile);
  FREE(ConfS.MainLogFile);
  FREE(ConfS.ErrorLogFile);
  FREE(ConfS.DebugLogFile);
  FREE(ConfS.SSLServerCertificate);
  FREE(ConfS.SSLServerPrivateKey);
  FREE(ConfS.SSLClientCertificate);
  FREE(ConfS.SSLClientPrivateKey);
  FREE(ConfS.SSLServerCiphers);
  FREE(ConfS.SSLClientCiphers);

}


syntax highlighted by Code2HTML, v. 0.9.1