Commit 85966783 authored by Seblu's avatar Seblu
Browse files

Commande exec avec execution en //

command kill
command status
command killall
parent 5dd3ee55
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
Improvments
Commande exec avec execution en //
command clean
command status
command reload
command update

+185 −65
Original line number Diff line number Diff line

#include <stdlib.h>
#include <errno.h>
#include <string.h>
@@ -19,9 +18,17 @@

#include "sld.hh"

SLDaemon::SLDaemon() : socket_fs_(NULL) {}
SLDaemon *SLDaemon::instance_ = 0;

SLDaemon::SLDaemon() : socket_fs_(0) {}

SLDaemon &SLDaemon::Instance() {
  if (instance_ == 0)
    instance_ = new SLDaemon();
  return *instance_;
}

SLDaemon::options::options() {
SLDaemon::Options::Options() {
  this->port = 0;
  this->verbose = 3;
}
@@ -44,8 +51,8 @@ void SLDaemon::usage(const char *argv0) const {

}

SLDaemon::options *SLDaemon::getoptions(int argc, char *argv[]) const {
  options opt, *mopt;
SLDaemon::Options *SLDaemon::getoptions(int argc, char *argv[]) const {
  Options opt, *mopt;

  if (argc == 1) {
    usage(*argv);
@@ -103,19 +110,19 @@ SLDaemon::options *SLDaemon::getoptions(int argc, char *argv[]) const {
      throw *err;
    }
  }
  mopt = new options();
  mopt = new Options();
  *mopt = opt;
  return mopt;
}

SLDaemon::options *SLDaemon::getoptions(const string file) const {
SLDaemon::Options *SLDaemon::getoptions(const string file) const {
  if (file == "")
    throw Error(ERR_BADPARAM, "Conf file not implemented");
  throw Error(ERR_BADPARAM, "Conf file not implemented");
  return NULL;
  return 0;
}

void SLDaemon::applyoptions(const options *opt) {
void SLDaemon::applyoptions(const Options *opt) {
  assert(opt);
  if (opt->server != "") options_.server = opt->server;
  if (opt->port != 0) options_.port = opt->port;
@@ -170,12 +177,16 @@ void SLDaemon::run() {
	cmd_reload();
      else if (!strcmp(line, "VERSION\n"))
	cmd_version();
      else if (!strcmp(line, "CLEAN\n"))
	cmd_clean();
      else if (!strcmp(line, "STATUS\n"))
	cmd_status();
      else if (!strcmp(line, "LIST\n"))
	cmd_list();
      else if (!strncmp(line, "EXEC ", 5))
	cmd_exec(line);
      else if (!strcmp(line, "KILLALL\n"))
	cmd_killall();
      else if (!strcmp(line, "KILL\n"))
	cmd_kill(line);
      else if (!strncmp(line, "JOB ", 5))
	cmd_job(line);
      else if (!strncmp(line, "FILE ", 5))
	cmd_file(line);
      else if (!strncmp(line, "UPDATE ", 6))
@@ -201,12 +212,12 @@ void SLDaemon::connect() {
  struct hostent *h;

  // close existing connexion
  if (socket_fs_ == NULL)
  if (socket_fs_ == 0)
    disconnect();

  // retrieve remote host info
  h = gethostbyname(options_.server.c_str());
  if (h == NULL)
  if (h == 0)
    throw Error(ERR_NET, hstrerror(h_errno));

  // create socket
@@ -224,16 +235,20 @@ void SLDaemon::connect() {
    throw Error(ERR_NET, strerror(errno));

  // initialize socket stream
  if ((socket_fs_ = fdopen(socket_fd_, "r+")) == NULL)
  if ((socket_fs_ = fdopen(socket_fd_, "r+")) == 0)
    throw Error(ERR_NET, strerror(errno));
}

void SLDaemon::disconnect() {
  if (socket_fs_ == NULL)
  if (socket_fs_ == 0)
    return;
  if (fclose(socket_fs_))
    throw Error(ERR_NET, strerror(errno));
  socket_fs_ = NULL;
  socket_fs_ = 0;
}

void SLDaemon::send(long int i) {
  fprintf(socket_fs_, "%li", i);
}

void SLDaemon::send(const string str, bool buf) {
@@ -262,20 +277,20 @@ char *SLDaemon::recv(size_t size) {
void SLDaemon::recv(size_t size, const string filename) {
  char *data = recv(size);
  FILE *fs = fopen(filename.c_str(), "w");
  if (fs == NULL)
    throw Error(ERR_FILE, strerror(errno));
  if (fs == 0)
    throw Error(ERR_FILE, (string) "recv: " + strerror(errno));
  if (fwrite(data, 1, size, fs) != size)
    throw Error(ERR_FILE, strerror(errno));
    throw Error(ERR_FILE, (string) "recv: " + strerror(errno));
  if (fclose(fs))
    throw Error(ERR_FILE, strerror(errno));
    throw Error(ERR_FILE, (string) "recv: " + strerror(errno));
}

char *SLDaemon::recvln() {
  char *line = new char[MAX_LINE_SIZE];

  if (fgets(line, MAX_LINE_SIZE, socket_fs_) == NULL) {
  if (fgets(line, MAX_LINE_SIZE, socket_fs_) == 0) {
    delete line;
    throw Error(ERR_FILE, strerror(errno));
    throw Error(ERR_FILE, (string) "recvln: " + strerror(errno));
  }
  return line;
}
@@ -309,7 +324,7 @@ void SLDaemon::auth() {

  BIO_free_all(b64);

  send("USER ");
  send("HOST ");
  send(options_.login);
  send("\n");

@@ -321,33 +336,21 @@ void SLDaemon::auth() {

  delete buff;

  char *line = recvln();
  if (strcmp(line, "OK\n")) {
    delete line;
    throw Error(ERR_AUTH, "Authentification failed !");
  }
  delete line;
  return;
}

void SLDaemon::tee(const string msg) {
  if (verbose())
    std::cout << msg << std::endl;
  if (verbose()) std::cout << msg;
  send(msg);
  send("\n");
}

void SLDaemon::proto_ok() {
  send("OK\n");
}

void SLDaemon::proto_ko() {
  send("KO\n");
void SLDaemon::tee(long int i) {
  if (verbose()) std::cout << i;
  send(i);
}

void SLDaemon::proto_violation() {
  std::cerr << "Protocol Violation." << std::endl;
  send((string) "Protocol Violation.\n", false);  
  tee("sld: Protocol violation.\n");
}


@@ -370,31 +373,43 @@ void SLDaemon::cmd_version() {
  send("\n");
}

void SLDaemon::cmd_exec(const char *line) {
void SLDaemon::cmd_job(const char *line) {
  assert(line);
  char *p = strchr(line, ' ');
  if (p == NULL) {
    proto_violation();

  // build path
  //FIXME: Bad static magic number
  char filename[512];
  sscanf(line, "JOB %s\n", filename);
  string path = options_.scriptdir + "/" +  filename;

  // Check if file exist and exec flag
  struct stat buf;
  int ret = lstat(path.c_str(), &buf);
  if (ret == ENOENT || errno == EACCES) {
    tee(strerror(errno));
    return;
  }
  string path = options_.scriptdir + "/" +  string(p + 1);
  send(">> EXEC " + path + "\n");
  if (verbose())
    std::cout << ">> EXEC " << path << std::endl;

  // fork
  // Create new process
  flush();
  pid_t pid = fork();
  if (pid == -1)
    throw Error(ERR_NET, "Unable to fork");

  // Father job
  if (pid > 0) {
    int status;
    char buf[10];
    waitpid(pid, &status, 0);
    status = WEXITSTATUS(status);
    snprintf(buf, 10, "%d", status);    
    send((string) ">> EXEC return " + buf + "\n");
  }
    // reg job
    SLDaemon::Job j(pid, filename, time(0));
    jobs_.insert(j);
    
    // show job info
    tee((string) "EXEC " + filename + ", pid: ");
    tee(pid);
    tee(", start at: ");
    tee(j.start_time);
    tee("\n");
  }
  // Son job
  else if (pid == 0) {
    if (dup2(socket_fd_, STDOUT_FILENO) == -1) {
      perror(">> dup2");
@@ -404,12 +419,12 @@ void SLDaemon::cmd_exec(const char *line) {
      perror(">> dup2");
      exit(ERR_UNKNOWN);
    }
    if (execl(path.c_str(), path.c_str(), NULL) == -1) {
      perror(">> execl");
    execl(path.c_str(), basename(path.c_str()), 0);
    printf("\"%s\"\n", path.c_str());
    perror("sld: execl");
    exit(ERR_UNKNOWN);
  }
}
}

void SLDaemon::cmd_file(const char *line) {
  char *buf;
@@ -499,7 +514,7 @@ void SLDaemon::cmd_list() {
  if (verbose())
    std::cout << "LIST requested." << std::endl;
  FILE *fls = popen(string("ls -1A " + options_.scriptdir).c_str(), "r");
  if (fls == NULL) {
  if (fls == 0) {
    tee("Unable to list " + options_.scriptdir + ".");
    return;
  }
@@ -517,9 +532,77 @@ void SLDaemon::cmd_list() {
  }
}

void SLDaemon::cmd_clean() {
void SLDaemon::cmd_status() {
  t_job::iterator i;

  if (verbose())
    std::cout << "STATUS requested." << std::endl;
  time_t t = time(0);
  for (i = jobs_.begin(); i != jobs_.end(); ++i) {
    send("EXEC: ");
    send(i->name);
    send(", pid: ");
    send(i->pid);
    send(", start at: ");
    send(i->start_time);
    send(", since: ");
    send(t - i->start_time);
    send(" seconds.\n");
  }
  flush();   
}

void SLDaemon::cmd_kill(const char *line) {
  t_job::iterator i;

  // retrieve pid
  int pid;
  if (sscanf(line, "KILL %i\n", &pid) != 1) {
    proto_violation();
    return;
  }

  if (verbose())
    std::cout << "KILL " << pid
	      <<" requested." << std::endl;

  for (i = jobs_.begin(); i != jobs_.end(); ++i)
    if (pid == i->pid) {
      int ret = kill(i->pid, SIGKILL);
      send("kill -SIGKILL ");
      send(i->pid);
      send(" (");
      send(i->name);
      send(") => ");
      if (ret == -1)
	send(strerror(errno));
      else
	send("0");
      send("\n");
    }
  flush();
}

void SLDaemon::cmd_killall() {
  t_job::iterator i;

  if (verbose())
    std::cout << "CLEAN requested." << std::endl;
    std::cout << "KILLALL requested." << std::endl;

  for (i = jobs_.begin(); i != jobs_.end(); ++i) {
    int ret = kill(i->pid, SIGKILL);
    send("kill -SIGKILL ");
    send(i->pid);
    send(" (");
    send(i->name);
    send(") => ");
    if (ret == -1)
      send(strerror(errno));
    else
      send("0");
    send("\n");
  }
  flush();
}

void SLDaemon::cmd_reload() {
@@ -541,7 +624,7 @@ string SLDaemon::md5(const string file) const {

  if (!MD5_Init(&ctx))
    return "";
  if ((fs = fopen(file.c_str(), "r")) == NULL)
  if ((fs = fopen(file.c_str(), "r")) == 0)
    return "";
  while ((len = fread(buf, 1, 512, fs)) > 0)
    if (!MD5_Update(&ctx, buf, len))
@@ -554,3 +637,40 @@ string SLDaemon::md5(const string file) const {
  digest[MD5_DIGEST_LENGTH * 2] = 0;
  return string(digest);
}

void sigchild(int) {
  int status;
  SLDaemon &d = SLDaemon::Instance();
  typedef SLDaemon::t_job t_job;
  t_job::iterator i;
  t_job &jobs_ = d.jobs_;
  pid_t pid;
  
  // Retrieve a pid
  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
    time_t t = time(0);
    for (i = jobs_.begin(); i != jobs_.end(); ++i) {
      if (i->pid == pid) {
	char buf[MAX_LINE_SIZE];
    
	snprintf(buf, MAX_LINE_SIZE,
		 "JOB: %s, pid: %d, end at: %ld, since: %ld, return: %d\n",
		 i->name.c_str(), i->pid,  t, t - i->start_time,
		 WEXITSTATUS(status));
	write(d.socket_fd_, buf, strlen(buf));
	jobs_.erase(i);
	break;
      }
    }
  }
}

//******************************************************************************
// Class Job functions
//******************************************************************************

SLDaemon::Job::Job(int p, string s, time_t t) : pid(p), name(s), start_time(t) {}

bool SLDaemon::Job::operator()(const SLDaemon::Job &a, const SLDaemon::Job &b) {
  return a.pid < b.pid;
}
+11 −3
Original line number Diff line number Diff line
@@ -8,13 +8,15 @@
// Last update Fri Jun  1 02:10:49 2007 Seblu
//

#include <signal.h>

#include "sld.hh"

int main(int argc, char *argv[])
{
  SLDaemon daemon;
  SLDaemon::options *lineopt;
  SLDaemon::options *fileopt = NULL;
  SLDaemon &daemon = SLDaemon::Instance();
  SLDaemon::Options *lineopt;
  SLDaemon::Options *fileopt = NULL;

  try {
    //parse arg line options
@@ -38,6 +40,12 @@ int main(int argc, char *argv[])
    //apply parsed option
    daemon.applyoptions(lineopt);

    // register sigchild handler
    if (signal(SIGCHLD, sigchild) == SIG_ERR) {
      perror("sld: error");
      return ERR_UNKNOWN;
    }

    //execute receive command
    daemon.run();
  }
+41 −12
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@
# include <fstream>
# include <sstream>
# include <map>
# include <time.h>
# include <set>

# include "error.hh"

@@ -36,6 +38,8 @@ enum {
const string VERSION = "1";
const int MAX_LINE_SIZE = 512;

void sigchild(int);

// -----------------------------------------------------------------------------
// SLDAEMON CLASS
// -----------------------------------------------------------------------------
@@ -46,10 +50,10 @@ public:

  static const string version;
  
  SLDaemon();
  static SLDaemon &Instance();

  struct options {
    options();
  struct Options {
    Options();
    string server;
    int port;
    string login;
@@ -59,22 +63,35 @@ public:
    string conffile;
  };

  struct Job {
    Job() {}
    Job(int, string, time_t);
    int pid;
    string name;
    time_t start_time;
    bool operator()(const Job &a, const Job &b);
  };

  inline bool verbose() const { return options_.verbose == 1; }

  options *getoptions(int argc, char *argv[]) const;
  options *getoptions(const string file) const;
  void applyoptions(const options *opt);
  Options *getoptions(int argc, char *argv[]) const;
  Options *getoptions(const string file) const;
  void applyoptions(const Options *opt);
  void run();

  friend void sigchild(int);

protected:
  // parsed options
  options options_;
  Options options_;

  // current socket
  int socket_fd_;
  FILE* socket_fs_;

  // pid list
  std::set<int> jobs;
  typedef std::set<Job, Job> t_job;
  t_job jobs_;

  // Options functions
  void usage(const char *argv0) const;
@@ -85,6 +102,7 @@ protected:
  void disconnect();  
  void send(const char *data, size_t len, bool buf = true);
  void send(const string str, bool buf = true);
  void send(long int i);
  char *recv(size_t size);
  void recv(size_t size, const string filename);
  char *recvln();
@@ -93,22 +111,33 @@ protected:
  // protocol functions
  void auth();
  void tee(const string msg);
  void proto_ok();
  void proto_ko();
  void tee(long int);
  void proto_violation();
  
  // commmand functions
  void cmd_exit();
  void cmd_version();
  void cmd_clean();
  void cmd_list();
  void cmd_reload();
  void cmd_status();
  void cmd_killall();
  void cmd_kill(const char *line);
  void cmd_update(const char *line);
  void cmd_exec(const char *line);
  void cmd_job(const char *line);
  void cmd_file(const char *line);

  // others functions
  string md5(const string file) const;
  
private:
  static SLDaemon *instance_;

  SLDaemon();
  ~SLDaemon() {}
  SLDaemon(const SLDaemon &) { assert(true); }
  SLDaemon &operator=(const SLDaemon &) { assert(true); return *instance_; }
};



#endif