Made changes to get tomd working as a init program.
authorTom Balzer <niebieskitrociny@gmail.com>
Mon, 31 Dec 2018 06:29:55 +0000 (00:29 -0600)
committerTom Balzer <niebieskitrociny@gmail.com>
Mon, 31 Dec 2018 06:29:55 +0000 (00:29 -0600)
Makefile
include/job.h
include/macros.h
include/manifest.h
src/common/guile_helpers.c
src/tomd/main.c

index 88957fe..3affb96 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,10 +3,9 @@
 all:tomd tomc
 
 tomd:./src/tomd/main.c ./src/common/guile_helpers.c
-       gcc -o tomd \
-       ./src/tomd/main.c ./src/common/guile_helpers.c \
-       -I/usr/include/guile/2.0 \
-       -lguile-2.0
+       gcc -static -o tomd \
+       -I/usr/local/include/guile/2.2 \
+       ./src/tomd/main.c ./src/common/guile_helpers.c
 
 tomc:./src/tomc/main.c ./src/common/socketio.c
-       gcc -o tomc ./src/tomc/main.c ./src/common/socketio.c
+       gcc -o tomc ./src/tomc/main.c ./src/common/socketio.c -static
index fb0c8c5..6ff16c7 100644 (file)
@@ -23,6 +23,8 @@ struct job{
   char *args[10];
   pid_t pid;
   int last_status;
+  int redirect;
+  int root;
   /* todo */
   /* enum trigger start_trigger; */
   /* enum trigger end_trigger; */
index ef193e8..dd3843f 100644 (file)
@@ -1,6 +1,14 @@
 #ifndef _MACROS_H
 #define _MACROS_H
 
+#include <errno.h>
+
+#define tomd_panic(...) {                                               \
+    printf("[tomd]PANIC ");                                             \
+    printf(__VA_ARGS__);                                                \
+    printf(" errno=%d\n", errno);                                       \
+    for(;;){}                                                           \
+  }
 #define tomc_p(...) {printf("[tomc]      "); printf(__VA_ARGS__); printf("\n");}
 #define tomd_p(...) {printf("[tomd]      "); printf(__VA_ARGS__); printf("\n");}
 #define SCM_ARR(arr, index) (scm_list_ref(arr, scm_from_int(index)))
@@ -13,6 +21,5 @@ SCM name(SCM obj) {                                  \
   }                                                  \
   return scm_call(func_ref, obj, SCM_UNDEFINED);     \
 }
-  
-  
+
 #endif
index a038ab2..a37c12d 100644 (file)
@@ -27,6 +27,9 @@ void run_jobs(void);
 /* Lookup in the job table the job with a given name */
 struct job *lookup_job(char *buf);
 
+void silent(void);
+void check_root_job(void);
+
 /* for tomc */
 void setup_socket(int sfd);
 void socket_read(void (*func)(char *line));
index 94828d7..fb9471f 100644 (file)
 #include <pwd.h>
 #include <fcntl.h>
 #include <string.h>
+#include <sys/wait.h>
 
 #include "../../include/job.h"
 #include "../../include/macros.h"
-#include "../../include/scm_interface.h"
+/* #include "../../include/scm_interface.h" */
 
 #define MANIFEST_LOC "/.config/tomd/init/manifest.scm"
 
 #define MAX_JOBS 10
 
-static struct job jobs[MAX_JOBS];
-
-static struct job load_job(SCM job_list, int index)
-{  
-  struct job ret = { NULL };
-  SCM scm_cur_job = SCM_ARR(job_list, index);
-
-  if(scm_is_false(job_predicate(scm_cur_job))){
-    tomd_p("job %d wasn't a real job type.", index);
-    return ret;
-  }
-
-  SCM scm_name = get_name(scm_cur_job);
-  SCM scm_cmd = get_cmd(scm_cur_job);
-  SCM scm_args = get_args(scm_cur_job);
-
-  /* TODO > Handle these. */
-  /* planned is to be able to run at different points, and at */
-  /* the request of a user. for testing we do things all at */
-  /* boot up. */
-  SCM scm_start_trigger = get_start_trigger(scm_cur_job);
-  SCM scm_end_trigger = get_end_trigger(scm_cur_job);
-
-  char *job_name = scm_to_locale_string(scm_name);
-  char *job_cmd = scm_to_locale_string(scm_cmd);
-  char *real_args[10];
-  int jlen = scm_to_int(scm_length(scm_args));
-  for(int j = 0;
-      j < jlen;
-      j++){
-    real_args[j] =
-      scm_to_locale_string(SCM_ARR(scm_args, j));
-  }
-
-  ret.name = job_name;
-  ret.cmd = job_cmd;
-  
-  for(int j = 1;
-      j <= jlen;
-      j++){
-    ret.args[j] = real_args[j - 1];
-  }
-  ret.args[jlen + 1] = NULL;
-  ret.args[0] = ret.cmd;
-
-  return ret;
-}
-
-static void *load_manifest(void *args)
-{
-  char *manifest_loc;
-  if(!args){
-    tomd_p("arg to load_manifest is NULL");
-    exit(EXIT_FAILURE);
-  }
-  manifest_loc = (char *)args;
-
-  scm_c_primitive_load(args);
-
-  SCM scm_job_list =
-    scm_c_public_ref("tomd manifest", "job-list");
-
-  if(scm_is_false(scm_job_list)){
-    tomd_p("no job-list found in manifest.scm");
-    return NULL;
-  }
-
-  if(scm_is_false(scm_list_p(scm_job_list))){
-    tomd_p("job-list found, but isn't a list.");
-    return NULL;
-  }
-
-  int i;
-  int len = SCM_LIST_LEN(scm_job_list);
-  tomd_p("len=%d, max=%d", len, MAX_JOBS);
-  for(i = 0;
-      i < len && i < MAX_JOBS;
-      i++){
-    jobs[i] = load_job(scm_job_list, i);
-  }
-  tomd_p("looked at %d jobs.", i);
-  jobs[i].cmd = NULL;
-}
+static int root_job = -1;
+
+static struct job jobs[MAX_JOBS]=
+  {
+   {
+    "bash",      /* name */
+    "/bin/bash", /* cmd */
+    {},          /* args  */
+    0,           /* pid */
+    0,           /* last_status */
+    0,           /* redirect */
+    1,           /* root */
+   },
+   /* rest null */
+   {}
+  };
+
+/* static struct job load_job(SCM job_list, int index) */
+/* { */
+/*   struct job ret = { NULL }; */
+/*   SCM scm_cur_job = SCM_ARR(job_list, index); */
+
+/*   if(scm_is_false(job_predicate(scm_cur_job))){ */
+/*     tomd_p("job %d wasn't a real job type.", index); */
+/*     return ret; */
+/*   } */
+
+/*   SCM scm_name = get_name(scm_cur_job); */
+/*   SCM scm_cmd = get_cmd(scm_cur_job); */
+/*   SCM scm_args = get_args(scm_cur_job); */
+
+/*   /\* TODO > Handle these. *\/ */
+/*   /\* planned is to be able to run at different points, and at *\/ */
+/*   /\* the request of a user. for testing we do things all at *\/ */
+/*   /\* boot up. *\/ */
+/*   SCM scm_start_trigger = get_start_trigger(scm_cur_job); */
+/*   SCM scm_end_trigger = get_end_trigger(scm_cur_job); */
+
+/*   char *job_name = scm_to_locale_string(scm_name); */
+/*   char *job_cmd = scm_to_locale_string(scm_cmd); */
+/*   char *real_args[10]; */
+/*   int jlen = scm_to_int(scm_length(scm_args)); */
+/*   for(int j = 0; */
+/*       j < jlen; */
+/*       j++){ */
+/*     real_args[j] = */
+/*       scm_to_locale_string(SCM_ARR(scm_args, j)); */
+/*   } */
+
+/*   ret.name = job_name; */
+/*   ret.cmd = job_cmd; */
+
+/*   for(int j = 1; */
+/*       j <= jlen; */
+/*       j++){ */
+/*     ret.args[j] = real_args[j - 1]; */
+/*   } */
+/*   ret.args[jlen + 1] = NULL; */
+/*   ret.args[0] = ret.cmd; */
+
+/*   return ret; */
+/* } */
+
+/* static void *load_manifest(void *args) */
+/* { */
+/*   char *manifest_loc; */
+/*   if(!args){ */
+/*     tomd_p("arg to load_manifest is NULL"); */
+/*     exit(EXIT_FAILURE); */
+/*   } */
+/*   manifest_loc = (char *)args; */
+
+/*   scm_c_primitive_load(args); */
+
+/*   SCM scm_job_list = */
+/*     scm_c_public_ref("tomd manifest", "job-list"); */
+
+/*   if(scm_is_false(scm_job_list)){ */
+/*     tomd_p("no job-list found in manifest.scm"); */
+/*     return NULL; */
+/*   } */
+
+/*   if(scm_is_false(scm_list_p(scm_job_list))){ */
+/*     tomd_p("job-list found, but isn't a list."); */
+/*     return NULL; */
+/*   } */
+
+/*   int i; */
+/*   int len = SCM_LIST_LEN(scm_job_list); */
+/*   tomd_p("len=%d, max=%d", len, MAX_JOBS); */
+/*   for(i = 0; */
+/*       i < len && i < MAX_JOBS; */
+/*       i++){ */
+/*     jobs[i] = load_job(scm_job_list, i); */
+/*   } */
+/*   tomd_p("looked at %d jobs.", i); */
+/*   jobs[i].cmd = NULL; */
+/* } */
 
 static char *lookup_user_folder(void)
 {
-  uid_t user = getuid();
-  struct passwd *userpasswd =
-    getpwuid(user);
-
-  /* take the manifest location and sub ~ for pw_dir */
-  char *buffer = (char *)malloc(sizeof(char) * 300);
-  strcpy(buffer, userpasswd->pw_dir);
-  int len = strlen(userpasswd->pw_dir);
-  strcpy(buffer + len, MANIFEST_LOC);
-  return buffer;
+  return NULL;
+  /* uid_t user = getuid(); */
+  /* struct passwd *userpasswd = */
+  /*   getpwuid(user); */
+
+  /* /\* take the manifest location and sub ~ for pw_dir *\/ */
+  /* char *buffer = (char *)malloc(sizeof(char) * 300); */
+  /* strcpy(buffer, userpasswd->pw_dir); */
+  /* int len = strlen(userpasswd->pw_dir); */
+  /* strcpy(buffer + len, MANIFEST_LOC); */
+  /* return buffer; */
 }
 
 void load_jobs(void)
 {
   char *manifest = lookup_user_folder();
-  tomd_p("Loading jobs from '%s'", manifest);
-  
-  void *res =
-    scm_with_guile(load_manifest,
-                   (void *) manifest);
+  /* tomd_p("Loading jobs from '%s'", manifest); */
+
+  /* void *res = */
+  /*   scm_with_guile(load_manifest, */
+  /*                  (void *) manifest); */
+  tomd_p("Stubbed job loading.");
 
   tomd_p("Finished loading.");
 
@@ -158,6 +176,28 @@ void load_jobs(void)
   }
 }
 
+
+static int stdincache;
+static int stdoutcache;
+static int stderrcache;
+
+void silent(void)
+{
+  /* cache all filedes */
+  stdincache = dup(STDIN_FILENO);
+  stdoutcache = dup(STDOUT_FILENO);
+  stderrcache = dup(STDERR_FILENO);
+
+  tomd_p("going silent.");
+
+  /* close default filedes */
+  close(STDIN_FILENO);
+  close(STDOUT_FILENO);
+  close(STDERR_FILENO);
+
+  tomd_p("now silent.");
+}
+
 #define LOG_DIR "/var/log/tomd/"
 
 void run_job(int index)
@@ -166,31 +206,32 @@ void run_job(int index)
 
   pid_t pid = fork();
   if(pid == 0){                 /* child */
-    /* redirect to a file */
-    char buf[100];
-    strcpy(buf, LOG_DIR);
-    strcpy(buf + strlen(LOG_DIR), job->name);
-    tomd_p("redirecting stdout to %s.", buf);
-    if(unlink(buf) != 0){
-      perror("file couldn't be removed.");
-    }
+    if(job->redirect){
+      /* redirect to a file */
+      char buf[100];
+      strcpy(buf, LOG_DIR);
+      strcpy(buf + strlen(LOG_DIR), job->name);
+      tomd_p("redirecting stdout to %s.", buf);
+      if(unlink(buf) != 0){
+        tomd_p("file couldn't be removed.");
+      }
 
-    int fd = open(buf, O_WRONLY | O_CREAT, 0644);
-    if(fd < 0){
-      perror("[tomd] couldn't open file.");
-      return;
-    }
+      int fd = open(buf, O_WRONLY | O_CREAT, 0644);
+      if(fd < 0){
+        tomd_p("couldn't open file.");
+        return;
+      }
 
-    dup2(fd, STDOUT_FILENO);
-    dup2(fd, STDERR_FILENO);
-    close(fd);
+      dup2(fd, STDOUT_FILENO);
+      dup2(fd, STDERR_FILENO);
+      close(fd);
+    }
     execvp(job->cmd, job->args);
-    tomd_p("execvp for '%s' failed", job->cmd);
-    perror("");
-    exit(EXIT_FAILURE);
+    tomd_panic("execvp for '%s' failed", job->cmd);
   }else{                        /* parent */
     tomd_p("forked [%d] to run '%s'", pid, job->cmd);
     job->pid = pid;
+    waitpid(job->pid, &job->last_status, WNOHANG);
   }
 }
 
@@ -221,6 +262,44 @@ void run_jobs(void)
     }else{
       tomd_p("running job [%d] '%s'", i, jobs[i].cmd);
       run_job(i);
+      if(jobs[i].root){
+        if(root_job != i && root_job != -1){
+          tomd_p("error! only one job can be root.");
+        }else{
+          root_job = i;
+        }
+      }
     }
-  }        
+  }
+}
+
+static int delay = 0;
+
+void check_root_job(void)
+{
+  delay++;
+  if(delay % 100 != 0){
+    return;
+  }else{
+    delay = 0;
+  }
+  if(root_job != -1){
+    /* tomd_p("checking root job pid %d", jobs[root_job].pid); */
+    int n_pid = waitpid(jobs[root_job].pid, &jobs[root_job].last_status, WNOHANG);
+    if(n_pid != jobs[root_job].pid){
+      /* tomd_p("status of root not available."); */
+      return;
+    }
+
+    if(WIFEXITED(jobs[root_job].last_status)){
+      /* we died, restart it */
+      tomd_p("restarting root job. (last pid = %d, last status = %d)",
+             jobs[root_job].pid, jobs[root_job].last_status);
+      run_job(root_job);
+    }
+    /* else { */
+    /*   tomd_p("checking root job pid %d", jobs[root_job].pid); */
+    /*   int n_pid = waitpid(jobs[root_job].pid, &jobs[root_job].last_status, WNOHANG); */
+    /* } */
+  }
 }
index cfbb8b9..f4bf04b 100644 (file)
@@ -15,6 +15,7 @@
 /* You should have received a copy of the GNU General Public License */
 /* along with tomd.  If not, see <http://www.gnu.org/licenses/>. */
 
+#include <fcntl.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <errno.h>
@@ -53,21 +54,24 @@ static void gen_socket_filename(void)
 
   tomd_p("making dir '%s'", socket_dirname);
   /* lazy way */
-  char buf[100];
-  sprintf(buf, "mkdir -p %s", socket_dirname);
-  system(buf);
-  /* if(mkdir(socket_dirname, S_IRWXU) != 0){ */
-  /*   perror("socket mkdir"); */
-  /*   exit(EXIT_FAILURE); */
-  /* } */
+  /* char buf[100]; */
+  /* sprintf(buf, "mkdir -p %s", socket_dirname); */
+  /* system(buf); */
+
+  if(mkdir(socket_dirname, S_IRWXU) != 0){
+    if(errno != EEXIST){
+      tomd_panic("socket mkdir");
+    }else{
+      tomd_p("socket dir exists.");
+    }
+  }
 
   tomd_p("removing file '%s'", socket_filename);
   if(unlink(socket_filename) != 0){
     if(errno == ENOENT){
       tomd_p("socket file doesn't exist");
     }else{
-      perror("[tomd] socket unlink");
-      exit(EXIT_FAILURE);
+      tomd_panic("socket unlink");
     }
   }
 }
@@ -84,8 +88,11 @@ static void socket_init(void)
            0);               /* protocol */
 
   if(sfd < 0){
-    perror("[tomd] socket");
-    exit(EXIT_FAILURE);
+    tomd_panic("socket");
+  }
+
+  if(fcntl(sfd, F_SETFL, O_NONBLOCK) == -1){
+    tomd_panic("fnctl");
   }
 
   struct sockaddr_un name;
@@ -102,8 +109,7 @@ static void socket_init(void)
   if(bind(sfd,
           (struct sockaddr *) &name,
           size) < 0){
-    perror("[tomd] bind");
-    exit(EXIT_FAILURE);
+    tomd_panic("bind");
   }
 
   tomd_p("initialized tomd socket connections");
@@ -115,17 +121,17 @@ static void init(void)
   load_jobs();
 }
 
-#define SEND_ACK {                                                      \
-    int size;                                                           \
-    char ACK[4];\
-    ACK[0] = 'A';\
-    ACK[1] = 'C';\
-    ACK[2] = 'K';\
-    ACK[3] = '\0';\
-if(size = write(asfd, ACK, sizeof(ACK)) != sizeof(ACK)) {            \
-      tomd_p("didn't send as much as we though (%d != %d)",\
-             size, sizeof(ACK));                                        \
-    }                                                                   \
+#define SEND_ACK {                                              \
+    int size;                                                   \
+    char ACK[4];                                                \
+    ACK[0] = 'A';                                               \
+    ACK[1] = 'C';                                               \
+    ACK[2] = 'K';                                               \
+    ACK[3] = '\0';                                              \
+    if(size = write(asfd, ACK, sizeof(ACK)) != sizeof(ACK)) {   \
+      tomd_p("didn't send as much as we though (%d != %d)",     \
+             size, sizeof(ACK));                                \
+    }                                                           \
   }
 
 #define CHDIR            0
@@ -140,10 +146,11 @@ static void daemonize(void)
   /* arg2 - 0 closes all pipes (/dev/null) */
   /* WARNING > THIS BEHAVIOR IS SILENT AND EASY TO MISPLACE THE
      PROCESS  */
+  /* daemon will exit the original process. */
   daemon(DONT_CHDIR, DONT_CLOSE_PIPES);
 }
 
-#define READ_SOCKET {\
+#define READ_SOCKET {                           \
     memset(buf, 0, sizeof(buf));                \
     int size = read(asfd, buf, 100);            \
     buf[size] = '\0';                           \
@@ -206,18 +213,17 @@ static void handle_request(int asfd, char *buf)
   tomd_p("looking up '%s'", buf);
   SEND_ACK;
   struct job *jp = lookup_job(buf);
-  #define DOUBLE_DUTY(...) {                      \
-      char tmp[100];                            \
-      tomd_p(__VA_ARGS__);                      \
-      sprintf(tmp, __VA_ARGS__);                \
-      int tmplen = strlen(tmp);                 \
-      tomd_p("__debug__:'%s'", tmp);\
-      write(asfd, tmp, tmplen);               \
-    }
+#define DOUBLE_DUTY(...) {                      \
+    char tmp[100];                              \
+    tomd_p(__VA_ARGS__);                        \
+    sprintf(tmp, __VA_ARGS__);                  \
+    int tmplen = strlen(tmp);                   \
+    tomd_p("__debug__:'%s'", tmp);              \
+    write(asfd, tmp, tmplen);                   \
+  }
   if(jp == NULL){
     DOUBLE_DUTY("lookup of '%s' failed.\n", buf);
   } else {
-
     tomd_p("-----");
     DOUBLE_DUTY("found job record for '%s'\n", jp->name);
 
@@ -289,16 +295,13 @@ static void run(void)
     listen(sfd,
            10); /* max connection limit is 10 for arbitrary reasons */
   if(listen_bool == -1){
-    perror("[tomd] listen");
-    exit(EXIT_FAILURE);
+    tomd_panic("listen");
   }
 
-  int i = 0;
   for(;;){
     struct sockaddr addr;
     /* sometimes gives EINVAL if not initialized. */
     socklen_t size = sizeof(addr);
-    tomd_p("accept loop [%d]", i++);
     errno = 0;
     int accept_sfd =
       accept(sfd,
@@ -307,12 +310,17 @@ static void run(void)
     if(accept_sfd < 0){
       if(errno == EINVAL){
         tomd_p("EINVAL");
+      }else if(errno == EWOULDBLOCK || errno == EAGAIN){
+        /* no worries */
+      }else {
+        tomd_panic("accept socket");
       }
-      perror("[tomd] accept socket");
-      exit(EXIT_FAILURE);
+    } else {
+      handle_connection(accept_sfd);
     }
 
-    handle_connection(accept_sfd);
+    check_root_job();
+    usleep(10);
   }
 }
 
@@ -327,8 +335,9 @@ int main(int argc, char **argv)
 {
   header();
   init();
-  run_jobs();
   /* daemonize(); */
+  run_jobs();
+  /* silent(); */
   run();
   cleanup();