Skip to content
sld.cc 4.93 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
*/

#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
Seblu's avatar
Seblu committed
#include <unistd.h>
#include <string>
Seblu's avatar
Seblu committed
#include <errno.h>
Seblu's avatar
Seblu committed
#include "sld.hh"

Seblu's avatar
Seblu committed
static Options get_default_options();
static bool register_signals();
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
/*!
** Program entry point
**
** @param argc arg count
** @param argv arg vector
**
** @return program err code
*/
Seblu's avatar
Seblu committed
int main(int argc, char *argv[])
{
  SLDaemon &daemon = SLDaemon::Instance();
Seblu's avatar
Seblu committed
  Options *lineopt = new Options();
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
  try {
Seblu's avatar
Seblu committed
    // Set default options
    daemon.options.merge(get_default_options());

    // Parse and merge line options
    lineopt->getoptions(argc, argv);
    daemon.options.merge(*lineopt);
    // Get and apply options if conffile is specified
Seblu's avatar
Seblu committed
    if (!euidaccess(daemon.options.conffile.c_str(), R_OK)) {
      daemon.options.getoptions(daemon.options.conffile);
Seblu's avatar
Seblu committed
      //apply arg line options
      daemon.options.merge(*lineopt);
    }
Seblu's avatar
Seblu committed
  }
  catch (const Error &e) {
    e.print();
    return e.code();
  }
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
  delete lineopt;

Seblu's avatar
Seblu committed
  // Set a log file if necessary
  if (daemon.options.logfile != "") {
    logout.file(daemon.options.logfile);
    logerr.file(daemon.options.logfile);
  if (!register_signals())
    return ERR_SIGNAL;
Seblu's avatar
Seblu committed
  if (daemon.options.daemon == 1)
Seblu's avatar
Seblu committed
    ::daemon(0, 0);
  // if no daemon, can dup on quiet mode
  else if (daemon.options.verbose == 0) {
    int dn = open("/dev/null", O_RDWR);
    if (dn == -1) {
      logerr << "sld: open(/dev/null, O_RDWR): " << strerror(errno) << ".\n";
      return ERR_UNKNOWN;
    }
    dup2(dn, STDOUT_FILENO);
    dup2(dn, STDERR_FILENO);
    close(dn);
  }

  // Write pid in a file
  if (daemon.options.pidfile != "") {
    FILE *fs = fopen(daemon.options.pidfile.c_str(), "w");
    if (fs) {
      fprintf(fs, "%d", getpid());
      fclose(fs);
Seblu's avatar
Seblu committed
    } else logerr << "sld: fopen: " << strerror(errno) << ".\n";
Seblu's avatar
Seblu committed

  // run daemon
  try { daemon.run(); }
Seblu's avatar
Seblu committed
  catch (const Error &e) {
Seblu's avatar
Seblu committed
    logerr << "sld: error: " << e.message() << ".\n";
Seblu's avatar
Seblu committed
    return e.code();
  }
Seblu's avatar
Seblu committed
  return ERR_UNKNOWN;
Seblu's avatar
Seblu committed
}
Seblu's avatar
Seblu committed

/*!
** Register signals
**
** @return success status
*/
static bool register_signals() {
  // register sigchild handler
  if (signal(SIGCHLD, sigchild) == SIG_ERR) {
    logerr << "sld: error: " << strerror(errno) << ".\n";
    return false;
  }

Seblu's avatar
Seblu committed
  if (SLDaemon::Instance().options.daemon) {
Seblu's avatar
Seblu committed
    // register sigint handler
    if (signal(SIGINT, sigint) == SIG_ERR) {
      logerr << "sld: error: " << strerror(errno) << ".\n";
      return false;
    }
Seblu's avatar
Seblu committed
    // register sigkill handler
    if (signal(SIGTERM, sigint) == SIG_ERR) {
      logerr << "sld: error: " << strerror(errno) << ".\n";
      return false;
    }

    // register sigkill handler
    if (signal(SIGHUP, sigint) == SIG_ERR) {
      logerr << "sld: error: " << strerror(errno) << ".\n";
      return false;
    }
/*!
** Set default options
**
** @param opt option struc to set
**
*/
Seblu's avatar
Seblu committed
static Options get_default_options() {
  char buf[128];
Seblu's avatar
Seblu committed
  Options options;
Seblu's avatar
Seblu committed
  if (gethostname(buf, 128) == 0)
    options.login = buf;
  options.port = 18136;
  options.conffile = "/etc/sldrc";
  options.retrydelay = 60;
Seblu's avatar
Seblu committed
  options.daemon = 0;
  options.verbose = 1;
Seblu's avatar
Seblu committed
/*!
** Retrieve complete path of this executable
**
** @return program path
*/
string getbinpath() {
  int pid = getpid();
Seblu's avatar
Seblu committed
  char buf[PATH_MAX];
  char buf2[PATH_MAX] = "";

  snprintf(buf, PATH_MAX, "/proc/%d/exe", pid);
  if (readlink(buf, buf2, PATH_MAX) == 0) {
Seblu's avatar
Seblu committed
    logerr << "sld: getbinpath: readlink: " << strerror(errno) << ".\n";
    return (string) "";
  }
  return (string) buf2;
}

Seblu's avatar
Seblu committed
/*!
** copy src to dst
**
** @param src copy file src
** @param dst copy file dst
**
** @return true if all is copied
*/
bool cp(const char *src, const char *dst) {
  assert(src);
  assert(dst);

  //open source file
  FILE *fsrc = fopen(src, "r");
  if (!fsrc)
    return false;

  //open destination file
  FILE *fdst = fopen(dst, "w");
  if (!fdst) {
    fclose(fsrc);
    return false;
  }

  //do copy
  char buf[512];
  size_t nread;
  size_t nwrite;
  while ((nread = fread(buf, 1, 512, fsrc)) > 0) {
    nwrite = fwrite(buf, 1, nread, fdst);
    if (nwrite != nread) {
      fclose(fsrc);
      fclose(fdst);
      return false;
    }
  }
  fclose(fsrc);
  fclose(fdst);
  return true;
Seblu's avatar
Seblu committed
}