Skip to content
options.cc 6.49 KiB
Newer Older
Seblu's avatar
Seblu committed
/*
  This file is part of SLD.
  Copyright (C) 2008 Sebastien LUTTRINGER <contact@seblu.net>

  SLD is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
Seblu's avatar
Seblu committed
  the Free Software Foundation; version 2 of the License.
Seblu's avatar
Seblu committed

  SLD 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 SLD; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

Seblu's avatar
Seblu committed
#include "sld.hh"

Options::Options() {
  port = -1;
  verbose = -1;
  retrydelay = -1;
  daemon = -1;
}

void Options::usage(const char *argv0) const {
  std::cerr
    << "usage: "
    << argv0
    << " [-f conffile] [-d scriptdir] [-h] [-v] [-l login]"
    << " [-p pass] [-H host] [-P port] [-r] [-V]"
    << std::endl
    << "  -f file   : read and load conf file (def: /etc/sldrc)." << std::endl
    << "  -d dir    : Scripts directory." << std::endl
    << "  -h        : Print this usage." << std::endl
    << "  -v        : Verbose mode." << std::endl
    << "  -q        : Quiet mode." << std::endl
    << "  -d        : Daemon mode." << std::endl
Seblu's avatar
Seblu committed
    << "  -h host   : Set login to host (def: check hostname)." << std::endl
    << "  -p secret : Set pass to secret." << std::endl
    << "  -H name   : Set server host to name." << std::endl
    << "  -P number : Set server port to number (def: 18136)." << std::endl
    << "  -r number : Set retry delay to val in seconds (def: 60)." << std::endl
    << "  -F file   : Set file where pid is written." << std::endl
Seblu's avatar
Seblu committed
    << "  -l file   : Write log into file." << std::endl
    << "  -V        : Print version and exit." << std::endl;
Seblu's avatar
Seblu committed
}

void Options::merge(const Options &opt) {
  if (opt.server != "") server = opt.server;
  if (opt.port >= 0) port = opt.port;
  if (opt.login != "") login = opt.login;
  if (opt.pass != "") pass = opt.pass;
  if (opt.verbose >= 0) verbose = opt.verbose;
  if (opt.conffile != "") conffile = opt.conffile;
  if (opt.scriptdir != "") scriptdir = opt.scriptdir;
  if (opt.retrydelay >= 0) retrydelay = opt.retrydelay;
  if (opt.daemon >= 0) daemon = opt.daemon;
  if (opt.pidfile != "") pidfile = opt.pidfile;
Seblu's avatar
Seblu committed
  if (opt.logfile != "") logfile = opt.logfile;
Seblu's avatar
Seblu committed
}

Options &Options::getoptions(int argc, char *argv[]) {
  for (int i = 1; i < argc; ++i) {
    if (!strcmp(argv[i], "-h")) {
      usage(*argv);
      throw Error(ERR_USAGE);
    }
    else if (!strcmp(argv[i], "-v")) {
      this->verbose = 2;
Seblu's avatar
Seblu committed
    }
    else if (!strcmp(argv[i], "-q")) {
      this->verbose = 0;
    }
    else if (!strcmp(argv[i], "-d")) {
      this->daemon = 1;
    }
    else if (!strcmp(argv[i], "-V")) {
      std::cout << "sl daemon version : " << VERSION << std::endl;
Seblu's avatar
Seblu committed
    }
    else if (!strcmp(argv[i], "-H")) {
      if (++i >= argc)
	throw Error(ERR_USAGE, "No enough argument for option -h");
      this->server = string(argv[i]);
    }
    else if (!strcmp(argv[i], "-P")) {
      if (++i >= argc)
	throw Error(ERR_USAGE, "No enough argument for option -p");
      char *endptr;
      this->port = strtol(argv[i], &endptr, 10);
      if (!(*argv[i] != '\0' && *endptr == '\0'))
	throw Error(ERR_USAGE, "Unable to convert port to a number");
    }
    else if (!strcmp(argv[i], "-f")) {
      if (++i >= argc)
	throw Error(ERR_USAGE, "No enough argument for option -f");
      this->conffile = string(argv[i]);
    }
    else if (!strcmp(argv[i], "-d")) {
      if (++i >= argc)
	throw Error(ERR_USAGE, "No enough argument for option -d");
      this->scriptdir = string(argv[i]);
    }
Seblu's avatar
Seblu committed
    else if (!strcmp(argv[i], "-h")) {
Seblu's avatar
Seblu committed
      if (++i >= argc)
Seblu's avatar
Seblu committed
	throw Error(ERR_USAGE, "No enough argument for option -h");
Seblu's avatar
Seblu committed
      this->login = string(argv[i]);
    }
    else if (!strcmp(argv[i], "-p")) {
      if (++i >= argc)
	throw Error(ERR_USAGE, "No enough argument for option -p");
      this->pass = string(argv[i]);
    }
    else if (!strcmp(argv[i], "-r")) {
      if (++i >= argc)
	throw Error(ERR_USAGE, "No enough argument for option -r");
      this->retrydelay = atoi(argv[i]);
    }
    else if (!strcmp(argv[i], "-F")) {
      if (++i >= argc)
	throw Error(ERR_USAGE, "No enough argument for option -F");
      this->pidfile = argv[i];
    }
Seblu's avatar
Seblu committed
    else if (!strcmp(argv[i], "-l")) {
      if (++i >= argc)
	throw Error(ERR_USAGE, "No enough argument for option -l");
      this->pidfile = argv[i];
    }
Seblu's avatar
Seblu committed
    else
      throw Error(ERR_USAGE, (string) "Invalid option : " + argv[i]);
Seblu's avatar
Seblu committed
  }
  return *this;
}

Options Options::getoptions(const string file) {
  ifstream fs;
  char line[MAX_CONF_LINE_SIZE];
  int i=0;
  char name[11], value[MAX_CONF_LINE_SIZE - 10 + 1];

  fs.open(file.c_str(), ifstream::in);

  if (fs.fail())
    throw Error(ERR_FILE, "Unable to open configuration file");

  while (!fs.eof()) {
    fs.getline(line, MAX_CONF_LINE_SIZE);
    if (fs.eof())
      break;
    ++i;

    // jump empty line
    if (*line == '#' || *line == 0)
      continue;

Seblu's avatar
Seblu committed
    sscanf(line, "%10[^=]=%2039s\n", name, value); //TODO: fix magic number

    if (!strcasecmp(name, "host"))
      this->login = value;
    else if (!strcasecmp(name, "pass"))
      this->pass = value;
    else if (!strcasecmp(name, "server"))
      this->server = value;
    else if (!strcasecmp(name, "port"))
      this->port = atoi(value);
    else if (!strcasecmp(name, "scriptdir"))
      this->scriptdir = value;
    else if (!strcasecmp(name, "verbose"))
      this->verbose = atoi(value);
    else if (!strcasecmp(name, "retrydelay"))
      this->retrydelay = atoi(value);
    else if (!strcasecmp(name, "daemon"))
      this->daemon = atoi(value);
    else if (!strcasecmp(name, "pidfile"))
      this->pidfile = value;
Seblu's avatar
Seblu committed
    else if (!strcasecmp(name, "logfile"))
      this->logfile = value;
Seblu's avatar
Seblu committed
    else
Seblu's avatar
Seblu committed
      logerr << "Invalid line " << i << ": " << line << "\n";
Seblu's avatar
Seblu committed
  }

  fs.close();

  return *this;
}

Seblu's avatar
Seblu committed
Logger &operator<< (Logger &s, const Options &o) {
  return s << "server: " << o.server  << "\n"
	   << "port: " << o.port << "\n"
	   << "host login: " << o.login << "\n"
	   << "host pass: " << o.pass << "\n"
	   << "script directory: " << o.scriptdir << "\n"
	   << "configuration file: " << o.conffile << "\n"
	   << "retry delay: " << o.retrydelay << "\n"
	   << "daemon mode: " << o.daemon << "\n"
	   << "log file: " << o.logfile << "\n"
	   << "pid file: " << o.pidfile << "\n"
	   << "verbose level: " << o.verbose << "\n";
Seblu's avatar
Seblu committed
}