summaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
authorMarkus Mittendrein <git@maxmitti.tk>2015-09-09 18:00:01 +0200
committerMarkus Mittendrein <git@maxmitti.tk>2015-09-09 18:00:32 +0200
commit6a86d936e8823f0e86969bc88b68dafd5fd3b973 (patch)
tree0be0654c5d14e611e918cac9bc6e107eef37939d /main.c
downloadprocessmanager-6a86d936e8823f0e86969bc88b68dafd5fd3b973.tar.gz
processmanager-6a86d936e8823f0e86969bc88b68dafd5fd3b973.zip
Initial commit
Diffstat (limited to 'main.c')
-rw-r--r--main.c475
1 files changed, 475 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..84367b0
--- /dev/null
+++ b/main.c
@@ -0,0 +1,475 @@
+#define _POSIX_C_SOURCE 200809L
+#define _DEFAULT_SOURCE
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <limits.h>
+
+char stdinName[PATH_MAX];
+char stdoutName[PATH_MAX];
+char stderrName[PATH_MAX];
+char ctrlinName[PATH_MAX];
+char ctrloutName[PATH_MAX];
+
+char progRunning = 0;
+char progQuit = 0;
+sig_atomic_t progStatus = 0;
+
+pid_t child = 0;
+
+char * normalize_path(const char * src, char * res)
+{
+ size_t src_len = strlen(src);
+ size_t res_len;
+
+ const char * ptr = src;
+ const char * end = &src[src_len];
+ const char * next;
+
+ if (src_len == 0 || src[0] != '/')
+ {
+ // relative path
+
+ char pwd[PATH_MAX];
+ size_t pwd_len;
+
+ if (getcwd(pwd, sizeof(pwd)) == NULL) {
+ return NULL;
+ }
+
+ pwd_len = strlen(pwd);
+ //res = malloc(pwd_len + 1 + src_len + 1);
+ memcpy(res, pwd, pwd_len);
+ res_len = pwd_len;
+ }
+ else
+ {
+ //res = malloc((src_len > 0 ? src_len : 1) + 1);
+ res_len = 0;
+ }
+
+ for (ptr = src; ptr < end; ptr=next+1)
+ {
+ size_t len;
+ next = memchr(ptr, '/', end-ptr);
+ if (next == NULL)
+ {
+ next = end;
+ }
+ len = next-ptr;
+ switch(len)
+ {
+ case 2:
+ if (ptr[0] == '.' && ptr[1] == '.')
+ {
+ const char * slash = memrchr(res, '/', res_len);
+ if (slash != NULL)
+ {
+ res_len = slash - res;
+ }
+ continue;
+ }
+ break;
+ case 1:
+ if (ptr[0] == '.')
+ {
+ continue;
+ }
+ break;
+ case 0:
+ continue;
+ }
+ res[res_len++] = '/';
+ memcpy(&res[res_len], ptr, len);
+ res_len += len;
+ }
+
+ if (res_len == 0)
+ {
+ res[res_len++] = '/';
+ }
+ res[res_len] = '\0';
+ return res;
+}
+
+void cleanup(void)
+{
+ if(stdinName != 0)
+ {
+ remove(stdinName);
+ }
+ if(stdoutName != 0)
+ {
+ remove(stdoutName);
+ }
+ if(stderrName != 0)
+ {
+ remove(stderrName);
+ }
+ if(ctrlinName != 0)
+ {
+ remove(ctrlinName);
+ }
+ if(ctrloutName != 0)
+ {
+ remove(ctrloutName);
+ }
+}
+
+void sigchld_handler(int sig)
+{
+ (void)sig;
+ wait(&progStatus);
+ if(WIFEXITED(progStatus) || WIFSIGNALED(progStatus) || WTERMSIG(progStatus))
+ {
+ progQuit = 1;
+ }
+}
+
+void exitHandler(int sig)
+{
+ (void)sig;
+
+ cleanup();
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ if(argc != 2)
+ {
+ fprintf(stderr, "Usage: %s FIFONAME_PREFIX\n", argv[0]);
+ return 1;
+ }
+
+ const char* fifonamePrefix = argv[1];
+
+ char tempstdinName[PATH_MAX];
+ char tempstdoutName[PATH_MAX];
+ char tempstderrName[PATH_MAX];
+ char tempctrlinName[PATH_MAX];
+ char tempctrloutName[PATH_MAX];
+
+ sprintf(tempstdinName, "%sstdin", fifonamePrefix);
+ realpath(tempstdinName, stdinName);
+ sprintf(tempstdoutName, "%sstdout", fifonamePrefix);
+ realpath(tempstdoutName, stdoutName);
+ sprintf(tempstderrName, "%sstderr", fifonamePrefix);
+ realpath(tempstderrName, stderrName);
+ sprintf(tempctrlinName, "%sctrlin", fifonamePrefix);
+ realpath(tempctrlinName, ctrlinName);
+ sprintf(tempctrloutName, "%sctrlout", fifonamePrefix);
+ realpath(tempctrloutName, ctrloutName);
+
+ cleanup();
+
+ //signal(SIGCHLD, sigchld_hanlder);
+ struct sigaction sa;
+ sa.sa_handler = sigchld_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ if(sigaction(SIGCHLD, &sa, 0) == -1)
+ {
+ perror("sigaction");
+ cleanup();
+ return 1;
+ }
+
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGUSR1, SIG_IGN);
+ signal(SIGUSR2, SIG_IGN);
+ signal(SIGINT, exitHandler);
+ signal(SIGHUP, exitHandler);
+ signal(SIGQUIT, exitHandler);
+ signal(SIGTERM, exitHandler);
+ signal(SIGTERM, exitHandler);
+
+ mode_t origMask = umask(0000);
+
+ if(mkfifo(stdinName, 0666) == -1)
+ {
+ perror("stdinfifo");
+ cleanup();
+ return 1;
+ }
+ int stdinFifo = -1; // = open(stdinName, O_RDONLY | O_NONBLOCK);
+ if(mkfifo(stdoutName, 0666) == -1)
+ {
+ perror("stdoutfifo");
+ cleanup();
+ return 1;
+ }
+ int stdoutFifo = -1;// = open(stdoutName, O_WRONLY);
+ if(mkfifo(stderrName, 0666) == -1)
+ {
+ perror("stdoutfifo");
+ cleanup();
+ return 1;
+ }
+ int stderrFifo = -1;// = open(stderrName, O_WRONLY);
+ if(mkfifo(ctrlinName, 0666) == -1)
+ {
+ perror("ctrlinfifo");
+ cleanup();
+ return 1;
+ }
+ if(mkfifo(ctrloutName, 0666) == -1)
+ {
+ perror("ctrloutfifo");
+ cleanup();
+ return 1;
+ }
+
+ umask(origMask);
+
+ int ctrlinFifo = open(ctrlinName, O_RDONLY);
+ int ctrloutFifo = open(ctrloutName, O_WRONLY);
+ if(ctrloutFifo == -1 || ctrlinFifo == -1)
+ {
+ perror("open");
+ cleanup();
+ return 1;
+ }
+ FILE* ctrloutFile = fdopen(ctrloutFifo, "w");
+ setlinebuf(ctrloutFile);
+ open(ctrloutName, O_RDONLY);
+
+ char* buf = (char*)malloc(4096 * sizeof(char));
+ if(buf == 0)
+ {
+ perror("malloc");
+ cleanup();
+ return 1;
+ }
+ int bufSize = 4096, curPos = 0;
+ char shouldExit = 0;
+ for(;!shouldExit;)
+ {
+ char* newlinePos = 0;
+ if(progQuit && progRunning)
+ {
+ progRunning = 0;
+ progQuit = 0;
+ fprintf(ctrloutFile, "QUIT: %d\n", WEXITSTATUS(progStatus));
+ close(stdinFifo);
+ close(stdoutFifo);
+ close(stderrFifo);
+ }
+ int count = read(ctrlinFifo, (void*)buf, 4096);
+ if(count == 0 || count == -1)
+ {
+ close(ctrlinFifo);
+ ctrlinFifo = open(ctrlinName, O_RDONLY);
+ }
+ else
+ {
+ buf[count] = '\0';
+ do
+ {
+ if(strcmp("HELLO\n", buf) == 0)
+ {
+ fputs("HELLO\n", ctrloutFile);
+ }
+ else if(strcmp("STATUS\n", buf) == 0)
+ {
+ if(progRunning)
+ {
+ fprintf(ctrloutFile, "RUNNING: %d\n", child);
+ }
+ else
+ {
+ fputs("NOTRUNNING\n", ctrloutFile);
+ }
+ }
+ else if(strncmp("START ", buf, 6) == 0)
+ {
+ if(progRunning && ctrloutFile != 0)
+ {
+ fputs("ALREADY\n", ctrloutFile);
+ }
+ else
+ {
+ char* prog = buf + 6;
+ while((newlinePos = strchr(prog, '\n')) == 0)
+ {
+ bufSize += count;
+
+ buf = (char*)realloc((void*)buf, bufSize);
+ if(buf == 0)
+ {
+ perror("realloc");
+ cleanup();
+ return 1;
+ }
+ count = read(ctrlinFifo, (void*)(buf+curPos), 4096);
+ if(count == 0)
+ {
+ close(ctrlinFifo);
+ ctrlinFifo = open(ctrlinName, O_RDONLY);
+ break;
+ }
+ curPos += count;
+ }
+ *newlinePos = '\0';
+ char** nargv = (char**)malloc(2 * sizeof(char*));
+ if(nargv == 0)
+ {
+ perror("malloc");
+ cleanup();
+ return 1;
+ }
+ nargv[0] = prog;
+ int nargc = 1;
+ unsigned int len = strlen(prog);
+ for(unsigned int i = 0; i < len; ++i)
+ {
+ if(prog[i] == '\\' && (prog[i+1] == '\\' || prog[i+1] == ' '))
+ {
+ memmove(prog + i, prog + i + 1, strlen(prog + i));
+ --len;
+ }
+ else if(prog[i] == ' ')
+ {
+ prog[i] = '\0';
+ nargv = (char**)realloc((void*)nargv, (++nargc + 1) * sizeof(char*));
+ if(nargv == 0)
+ {
+ perror("realloc");
+ cleanup();
+ return 1;
+ }
+ nargv[nargc - 1] = prog + i + 1;
+ }
+ }
+ nargv[nargc] = 0;
+
+ char absPath[PATH_MAX];
+ nargv[0] = normalize_path(nargv[0], absPath);
+
+ if(nargv[0] == 0)
+ {
+ fprintf(ctrloutFile, "STARTFAIL: %s\n", strerror(errno));
+ }
+
+ progRunning = 1;
+
+ child = fork();
+ if(child == -1)
+ {
+ perror("fork");
+ cleanup();
+ return 1;
+ }
+ if(child == 0)
+ {
+ stdinFifo = open(stdinName, O_RDONLY);
+ if(stdinFifo == -1)
+ {
+ perror("open");
+ }
+ stdoutFifo = open(stdoutName, O_WRONLY);
+ if(stdoutFifo == -1)
+ {
+ perror("open");
+ }
+ stderrFifo = open(stderrName, O_WRONLY);
+ if(stderrFifo == -1)
+ {
+ perror("open");
+ }
+ dup2(stdinFifo, STDIN_FILENO);
+ dup2(stdoutFifo, STDOUT_FILENO);
+ dup2(stderrFifo, STDERR_FILENO);
+ if(execvp(nargv[0], nargv) == -1)
+ {
+ perror("execvp");
+ exit(1);
+ }
+ }
+ else
+ {
+ stdinFifo = open(stdinName, O_WRONLY);
+ stdoutFifo = open(stdoutName, O_RDONLY);
+ stderrFifo = open(stderrName, O_RDONLY);
+ fprintf(ctrloutFile, "RUNNING: %d\n", child);
+ }
+
+ bufSize = 4096;
+ buf = (char*)realloc((void*)buf, bufSize);
+ if(buf == 0)
+ {
+ perror("realloc");
+ cleanup();
+ return 1;
+ }
+ }
+ }
+ else if(strncmp(buf, "CD ", 3) == 0)
+ {
+ char* dir = buf + 3;
+ if((newlinePos = strchr(dir, '\n')) != 0)
+ {
+ *newlinePos = '\0';
+ }
+ char tempDir[PATH_MAX];
+ realpath(dir, tempDir);
+ if(chdir(tempDir) == 0)
+ {
+ fputs("CHANGED\n", ctrloutFile);
+ }
+ else
+ {
+ fprintf(ctrloutFile, "CD FAILED: %s\n", strerror(errno));
+ }
+ }
+ else if(strcmp(buf, "EXIT\n") == 0)
+ {
+ shouldExit = 1;
+ break;
+ }
+ else if(strcmp(buf, "CLOSE\n") == 0)
+ {
+ close(stdinFifo);
+ close(stdoutFifo);
+ close(stderrFifo);
+ fputs("CLOSED\n", ctrloutFile);
+ }
+ else if(strcmp(buf, "KILL\n") == 0)
+ {
+ if(!progRunning)
+ {
+ fputs("NOTRUNNING\n", ctrloutFile);
+ }
+ else
+ {
+ kill(child, SIGTERM);
+ fputs("KILLED\n", ctrloutFile);
+ }
+ }
+ if(newlinePos != 0)
+ {
+ strcpy(buf, newlinePos + 1);
+ }
+ else
+ {
+ buf[0] = '\0';
+ }
+ }
+ while(buf[0] != '\0');
+ }
+ }
+
+ cleanup();
+
+ return 0;
+}
+