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

wfconfig.cc

/*
 * WallFire -- a comprehensive firewall administration tool.
 * 
 * Copyright (C) 2001 Hervé Eychenne <rv@wallfire.org>
 * 
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 */

using namespace std;

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string>
#include <algorithm> /* for for_each */

#include "wfconfig.h"
#include "defs.h"


wf_option::wf_option() :
  _type(WF_OPTION_TYPE_NONE),
  _defined(false),
  _short_help(),
  _long_help()
{
}

wf_option::wf_option(enum wf_option_types type) :
  _type(type),
  _defined(false)
{
  if (_type == WF_OPTION_TYPE_STR)
    _val.str = NULL;
}

wf_option::~wf_option() {
  if (_type == WF_OPTION_TYPE_STR && _val.str != NULL)
    free(_val.str);
}

wf_option::wf_option(const wf_option& option) :
  _type(option._type),
  _defined(option._defined),
  _short_help(option._short_help),
  _long_help(option._long_help)
{
  if (_defined == false) {
    if (_type == WF_OPTION_TYPE_STR)
      _val.str = NULL;
    return;
  }

  switch (_type) {
  case WF_OPTION_TYPE_INT:
    _val.integer = option._val.integer;
    break;
  case WF_OPTION_TYPE_STR:
    _val.str = strdup(option._val.str);
    break;
  case WF_OPTION_TYPE_BOOL:
    _val.boolean = option._val.boolean;
    break;
  default:
    break;
  }
}

wf_option&
wf_option::operator=(const wf_option& option) {
  if (this != &option) {
    _type = option._type;
    _defined = option._defined;
    _short_help = option._short_help;
    _long_help = option._long_help;

    if (_defined == false) {
      if (_type == WF_OPTION_TYPE_STR)
      _val.str = NULL;
      return *this;
    }

    switch (_type) {
    case WF_OPTION_TYPE_INT:
      _val.integer = option._val.integer;
      break;
    case WF_OPTION_TYPE_STR:
      _val.str = strdup(option._val.str);
      break;
    case WF_OPTION_TYPE_BOOL:
      _val.boolean = option._val.boolean;
      break;
    default:
      break;
    }
  }
  return *this;
}


bool
wf_option::set(int integer) {
  if (_type != WF_OPTION_TYPE_INT && _type != WF_OPTION_TYPE_BOOL) {
    cerr << "wrong type: integer wanted" << endl;
    return false;
  }
  _defined = true;
  if (_type == WF_OPTION_TYPE_INT)
    _val.integer = integer;
  else /* WF_OPTION_TYPE_BOOL */
    _val.boolean = integer;
  return true;
}

wf_option&
wf_option::operator=(int integer) {
  set(integer);
  return *this;
}

bool
wf_option::set(const char* string) {
  if (_type != WF_OPTION_TYPE_STR) {
    cerr << "wrong type: string wanted" << endl;
    return false;
  }
  _defined = true;
  _val.str = strdup(string);
  return true;
}

wf_option&
wf_option::operator=(const char* string) {
  set(string);
  return *this;
}

bool
wf_option::set(bool boolean) {
  if (_type != WF_OPTION_TYPE_BOOL) {
    cerr << "wrong type: boolean wanted" << endl;
    return false;
  }
  _defined = true;
  _val.boolean = boolean;
  return true;
}

wf_option&
wf_option::operator=(bool boolean) {
  set(boolean);
  return *this;
}


int
wf_option::toint() const {
  if (_defined == true && _type == WF_OPTION_TYPE_INT)
    return _val.integer;
  cerr << "no integer type" << endl;
  exit(20); // RV@@8
  return -1;
}

string
wf_option::tostr() const {
  if (_defined == true && _type == WF_OPTION_TYPE_STR)
    return _val.str;
  cerr << "no string type" << endl;
  exit(20); // RV@@8
  return "wrong_type";
}

bool
wf_option::tobool() const {
  if (_defined == true && _type == WF_OPTION_TYPE_BOOL)
    return _val.boolean;
  cerr << "no boolean type" << endl;
  exit(20); // RV@@8
  return false;
}

enum wf_option_types
wf_option::type() const {
  return _type;
}

string
wf_option::type_tostr() const {
  switch (_type) {  
  case WF_OPTION_TYPE_NONE:
    return "unknown_type";
  case WF_OPTION_TYPE_INT:
    return "integer";
  case WF_OPTION_TYPE_STR:
    return "string";
  case WF_OPTION_TYPE_BOOL:
    return "boolean";
  }
  return "error";
}

ostream&
wf_option::print(ostream& os) const {
  if (_defined == false)
    return os << "undefined";

  switch (_type) {  
  case WF_OPTION_TYPE_NONE:
    return os << "unknown_type";
  case WF_OPTION_TYPE_INT:
    return os << _val.integer;
  case WF_OPTION_TYPE_STR:
    return os << _val.str;
  case WF_OPTION_TYPE_BOOL:
    return os << (_val.boolean ? "yes" : "no");
  }
  return os;
}

void
wf_option::short_help(const string& short_help) {
  _short_help = short_help;
}

void
wf_option::long_help(const string& long_help) {
  _long_help = long_help;
}


string
wf_option::short_help() const {
  return _short_help;
}

string
wf_option::long_help() const {
  if (_long_help.empty())
    return _short_help;
  return _long_help;
}


wf_config::wf_config() :
  _names(),
  long_options(NULL)
{}

wf_config::~wf_config() {
  if (long_options != NULL)
    free(long_options);
}


bool
wf_config::option_add(const char* name, enum wf_option_types type,
                  const string& short_help, const string& long_help) {
  if (_names.find(name) != _names.end())
    return false; /* name already exists */

  if (strchr(name, ' ') != NULL)
    return false; /* name contains space */

  if (long_options != NULL) { /* ensure consistency */
    free(long_options);
    long_options = NULL;
  }

  wf_option myoption(type);
  myoption.short_help(short_help);
  if (long_help.empty())
    myoption.long_help(short_help);
  else
    myoption.long_help(long_help);
  /* myoption._defined == false and myoption._val is undefined */
  _names[name] = myoption;
  return true;
}

bool
wf_config::option_set(const char* name, int integer) {
  if (_names.find(name) == _names.end())
    return false; /* name does not exist */

  if (_names[name].set(integer) == false)
    return false;
  return true;
}

bool
wf_config::option_set(const char* name, bool boolean) {
  if (_names.find(name) == _names.end())
    return false; /* name does not exist */

  if (_names[name].set(boolean) == false)
    return false;
  return true;
}

bool
wf_config::option_set(const char* name, const char* str) {
  if (_names.find(name) == _names.end())
    return false; /* name does not exist */

  if (_names[name].set(str) == false)
    return false;
  return true;
}

wf_option&
wf_config::option_get(const char* name) {
  return (*this)[name];
}

wf_option&
wf_config::operator[](const char* name) {
  if (_names.find(name) == _names.end()) {
    cerr << "ERROR ACCESSING TO " << name << endl;
    debugprint(cerr);
    // throw an exception?
    exit(20); // RV@@8
    return *new wf_option();
  }

  return _names[name];
}

enum wf_config_parse_ret
wf_config::parse(int argc, char* const argv[]) {
  if (long_options == NULL) {
    long_options = (struct option*)malloc(sizeof(struct option) *
                                (_names.size() + 1));
    if (long_options == NULL)
      return WF_CONFIG_PARSE_OTHER;

    int i = 0;
    map<const char*, wf_option>::const_iterator first = _names.begin(),
      last = _names.end();
    for (; first != last; ++first, ++i) {
      long_options[i].name = (*first).first;
      long_options[i].has_arg = optional_argument;
      long_options[i].flag = NULL;
      long_options[i].val = 0;
    }
    /* last option must be all 0 */
    long_options[i].name = 0;
    long_options[i].has_arg = 0;
    long_options[i].flag = 0;
    long_options[i].val = 0;
  }

  int ch;
  int long_index;
  opterr = 0; /* do not let getopt_long display error messages */

  // while ((ch = getopt_long(argc, argv, "", long_options, &long_index)) != EOF)
  ch = getopt_long(argc, argv, "", long_options, &long_index);
  switch (ch) {
  case 0:
    {
      const char* name = long_options[long_index].name;
      wf_option& option = _names[name];
      // cerr << "option " << name << endl;
      switch (option.type()) {
      case WF_OPTION_TYPE_INT:
      if (optarg) {
        // cerr << " with arg " << optarg << endl;
        char* p;
        int num = strtol(optarg, &p, 0);
        if (*p != '\0') {
          cerr << "invalid argument `" << optarg << "' to option `" << name << "': integer wanted" << endl;
          return WF_CONFIG_PARSE_ARG;
        }
        option.set(num);
      }
      else {
        cerr << "option `" << name << "' must take an integer argument" << endl;
        return WF_CONFIG_PARSE_ARG;
      }
      break;
      case WF_OPTION_TYPE_STR:
      if (optarg) {
        // cerr << " with arg " << optarg << endl;
        option.set(optarg);
      }
      else {
        cerr << "option `" << name << "' must take a string argument" << endl;
        return WF_CONFIG_PARSE_ARG;
      }
      break;
      case WF_OPTION_TYPE_BOOL:
      if (optarg) {
        // cerr << " with arg " << optarg << endl;
        if (!strcmp(optarg, "no") || !strcmp(optarg, "false"))
          option.set(false);
        else if (!strcmp(optarg, "yes") || !strcmp(optarg, "true"))
          option.set(true);
        else {
          cerr << "unknown argument `" << optarg << "' to option `" << name << "': only `yes' or `no' is allowed" << endl;
          return WF_CONFIG_PARSE_ARG;
        }
      }
      else
        option.set(true);
      break;
      default: /* to avoid warning */
      return WF_CONFIG_PARSE_ARG;
      }
    }
    break;
  case '?': /* unrecognized option */
    return WF_CONFIG_PARSE_UNKNOWN;
  default:
    cerr << "bizarre value " << ch << endl;
    return WF_CONFIG_PARSE_OTHER;
  }
  
  return WF_CONFIG_PARSE_OK;
}

struct display {
  display(ostream& out) : os(out) {}
  void operator() (const pair<const char*, wf_option>& x) const {
    os << x.first << " ";
    const wf_option& option = x.second;
    os << '(' << option.type_tostr() << "): ";
    option.print(os);
    os << " (" << option.short_help() << ')' << endl;
  }
  ostream& os;
};

ostream&
wf_config::debugprint(ostream& os) const {
  std::for_each(_names.begin(), _names.end(), display(os));
  return os;
}

#if 0
ostream&
wf_config::debugprint(ostream& os) const {
  map<const char*, wf_option>::const_iterator first = _names.begin(),
    last = _names.end();
  for (; first != last; ++first) {
    os << (*first).first << " ";
    const wf_option& option = (*first).second;
    os << '(' << option.type_tostr() << "): ";
    option.print(os);
    os << " (" << option.short_help() << ')' << endl;
  }
  return os;
}
#endif

Generated by  Doxygen 1.6.0   Back to index