diff options
| author | Markus Mittendrein <git@maxmitti.tk> | 2015-09-09 18:00:01 +0200 |
|---|---|---|
| committer | Markus Mittendrein <git@maxmitti.tk> | 2015-09-09 18:00:32 +0200 |
| commit | 6a86d936e8823f0e86969bc88b68dafd5fd3b973 (patch) | |
| tree | 0be0654c5d14e611e918cac9bc6e107eef37939d /main.c | |
| download | processmanager-6a86d936e8823f0e86969bc88b68dafd5fd3b973.tar.gz processmanager-6a86d936e8823f0e86969bc88b68dafd5fd3b973.zip | |
Initial commit
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 475 |
1 files changed, 475 insertions, 0 deletions
@@ -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; +} + |
