diff options
Diffstat (limited to '')
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | wiki.c | 185 |
3 files changed, 125 insertions, 68 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba2906d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +main @@ -6,13 +6,14 @@ CFLAGS = -Wall -pedantic -std=c2x -ggdb \ -D_DEFAULT_SOURCE \ -D_BSD_SORUCE \ -pthread \ - -I/usr/local/include -#### -fsanitize=thread \ + -I/usr/local/include \ + -fsanitize=thread #### -fsanitize=undefined LDFLAGS = -pthread -L/usr/local/lib LDLIBS = -lpthread -wiki: wiki.c +main: wiki.c + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LDLIBS) check: cppcheck --enable=all --suppress=missingIncludeSystem wiki.c @@ -55,6 +55,10 @@ void wake(); #define typeof __typeof__ #endif +/** The ends of pipes created pipe() */ +#define READ_END 0 +#define WRITE_END 1 + /** Calculate length of a static array */ #define ARR_LEN(arr) ((size_t) (sizeof(arr) / sizeof((arr)[0]))) #define ARRAY(x, ...) ((typeof(x)[]) {x, __VA_ARGS__}) @@ -157,10 +161,15 @@ static void *start_thread(void *d) { struct thread_data *data = d; - fprintf(stderr, "%i, %i\n", data->stdout, data->stderr); + fprintf(stderr, "pid=%i, stdout=%i, stderr=%i\n", + getpid(), + data->stdout, + data->stderr); + /* FILE *out = fdopen(data->stdout, "w"); FILE *err = fdopen(data->stderr, "w"); + */ char *line = NULL; size_t linecapp; @@ -172,9 +181,9 @@ static void *start_thread(void *d) { ssize_t len; // kill(data->peer_pid, SIGUSR1); - fprintf(stderr, "We are here\n"); + fprintf(stderr, "'%s' We are here\n", data->wiki); pthread_cond_signal(data->cond); - fprintf(stderr, "Signaled\n"); + fprintf(stderr, "'%s' Signaled\n", data->wiki); munmap(data->cond, sizeof data->cond); // struct timeval timeout = { @@ -184,18 +193,20 @@ static void *start_thread(void *d) { int count; for (;;) { - printf("Running select:\n"); - if ((count = select(2, &fds, NULL, NULL, NULL)) == -1) { - fprintf(stderr, "Error in select: %s\n", strerror(errno)); - write_stderr(data->wiki, "Error in select: %s\n", strerror(errno)); + printf("\n'%s' Running select:\n", data->wiki); + struct timeval timeout = { .tv_sec = 1 }; + if ((count = select(2, &fds, NULL, NULL, &timeout)) == -1) { + fprintf(stderr, " Error in select: %s\n", strerror(errno)); + write_stderr(data->wiki, " Error in select: %s\n", strerror(errno)); continue; } - fprintf(stderr, "Got %i!\n", count); + fprintf(stderr, " Got %i!\n", count); #if 1 if (FD_ISSET(data->stdout, &fds)) { fprintf(stderr, "on stdout\n"); errno = 0; +#if 0 if ((len = getline(&line, &linecapp, out)) == -1) { if (errno) { write_stderr(data->wiki, "Failed reading stdout: %s", strerror(errno)); @@ -205,11 +216,13 @@ static void *start_thread(void *d) { } else { write_stdout(data->wiki, "%s", line); } +#endif } if (FD_ISSET(data->stderr, &fds)) { fprintf(stderr, "on stderr\n"); errno = 0; +#if 0 if ((len = getline(&line, &linecapp, err)) == -1) { if (errno) { write_stderr(data->wiki, "Failed reading stderr: %s", strerror(errno)); @@ -219,6 +232,7 @@ static void *start_thread(void *d) { } else { write_stderr(data->wiki, "%s", line); } +#endif } #endif } @@ -226,24 +240,32 @@ static void *start_thread(void *d) { return NULL; } -int main (int argc, const char *argv[]) { - truncate("/tmp/hugo/log", 0); +struct cmd_args { + /** Number of wikis to work on */ + int wiki_count; + + strlist wiki_list; - printf("pid = %i\n", getpid()); - /* At most every other argument can be a requested wiki */ - strlist wiki_list = malloc(sizeof(*wiki_list) * argc / 2); /** index into wiki_list, pointing at the next empty slot */ - int wiki_list_ptr = 0; - /** Number of wikis to work on */ - int wiki_count = 0; + int wiki_list_ptr; +}; - char *wiki_root = get_wikiroot(); +int parse_commandline( + struct cmd_args *cmd, + int argc, + const char *argv[]) +{ + + /* At most every other argument can be a requested wiki */ + cmd->wiki_list = malloc(sizeof(*cmd->wiki_list) * argc / 2); + /** index into wiki_list, pointing at the next empty slot */ + cmd->wiki_list_ptr = 0; int arg = 1; for (; arg < argc; arg++) { if (cmp("--wiki", argv[arg]) || cmp("-w", argv[arg])) { - wiki_list[wiki_list_ptr++] = (char *) argv[++arg]; - ++wiki_count; + cmd->wiki_list[cmd->wiki_list_ptr++] = (char *) argv[++arg]; + ++cmd->wiki_count; continue; } else if (cmp("--list", argv[arg]) || cmp("-l", argv[arg])) { @@ -258,23 +280,37 @@ int main (int argc, const char *argv[]) { } } - wiki_count = wiki_list_ptr; + cmd->wiki_count = cmd->wiki_list_ptr; + + return arg; +} + +int main (int argc, const char *argv[]) { + syslog(4, "Start"); + // truncate("/tmp/hugo/log", 0); + + printf("pid = %i\n", getpid()); + + struct cmd_args cmd = {}; + int arg = parse_commandline(&cmd, argc, argv); - if (wiki_list_ptr == 0) { - free(wiki_list); + char *wiki_root = get_wikiroot(); - wiki_count = gather_wikis(wiki_root, &wiki_list); + /** If no wikis were given, instead list all available wikis */ + if (cmd.wiki_list_ptr == 0) { + free(cmd.wiki_list); + cmd.wiki_count = gather_wikis(wiki_root, &cmd.wiki_list); } /* If no further arguments are given, edit the given wiki */ if (arg == argc) { char *wiki; - if (wiki_count == 0) { + if (cmd.wiki_count == 0) { fprintf(stderr, "No wikis found\n"); return 1; } - wiki = wiki_list[0]; + wiki = cmd.wiki_list[0]; char *path = malloc(1024); sprintf(path, "%s/%s/index.wiki", @@ -299,23 +335,27 @@ int main (int argc, const char *argv[]) { stderr_lock = NULL; } - int *pids = malloc(sizeof(*pids) * wiki_count); + int *pids = malloc(sizeof(*pids) * cmd.wiki_count); - for (int i = 0; i < wiki_count; i++) { + for (int i = 0; i < cmd.wiki_count; i++) { int stdout_pipes[2], stderr_pipes[2]; if (pipe(stdout_pipes) == -1) { fprintf(stderr, "Failed opening stdout pipe for '%s': %s\n", - wiki_list[i], strerror(errno)); + cmd.wiki_list[i], strerror(errno)); continue; }; if (pipe(stderr_pipes) == -1) { fprintf(stderr, "Failed opening stderr pipe for '%s': %s\n", - wiki_list[i], strerror(errno)); + cmd.wiki_list[i], strerror(errno)); continue; }; + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_cond_t *cond = mmap(NULL, sizeof (pthread_cond_t), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, @@ -326,10 +366,8 @@ int main (int argc, const char *argv[]) { continue; } - pthread_cond_init(cond, NULL); - -#define READ_END 0 -#define WRITE_END 1 + pthread_cond_init(cond, &attr); + pthread_condattr_destroy(&attr); int pid; switch ((pid = fork())) { @@ -340,6 +378,8 @@ int main (int argc, const char *argv[]) { // close(stdout_pipes[READ_END]); // close(stderr_pipes[READ_END]); + printf("From %i to stdout\n", getpid()); + if (dup2(stdout_pipes[WRITE_END], 1) == -1) { fprintf(err, "Failed replacing stdout: %s\n", strerror(errno)); } @@ -348,6 +388,7 @@ int main (int argc, const char *argv[]) { fprintf(err, "Failed replacing stderr: %s\n", strerror(errno)); } + // close(stdout_pipes[WRITE_END]); // close(stderr_pipes[WRITE_END]); @@ -355,22 +396,28 @@ int main (int argc, const char *argv[]) { { pthread_mutex_t cond_mutex; pthread_mutex_init(&cond_mutex, NULL); - syslog(4, "Test of syslog"); - fprintf(err, "Waiting on condition\n"); + syslog(5, "'%s' Waiting on condition", cmd.wiki_list[i]); pthread_cond_wait(cond, &cond_mutex); - fprintf(err, "Awoken from condition\n"); + syslog(5, "'%s' Awoken from condition", cmd.wiki_list[i]); pthread_mutex_unlock(&cond_mutex); pthread_mutex_destroy(&cond_mutex); } + + printf("From %i to pipe\n", getpid()); + pthread_cond_destroy(cond); munmap(cond, sizeof cond); - ret = wiki_do(wiki_root, wiki_list[i], argc - arg, &argv[0] + arg); + ret = wiki_do( + wiki_root, + cmd.wiki_list[i], + argc - arg, + &argv[0] + arg); exit(ret); case -1: fprintf(stderr, "Failed creating process for '%s': %s\n", - wiki_list[i], strerror(errno)); + cmd.wiki_list[i], strerror(errno)); continue; default: @@ -379,16 +426,6 @@ int main (int argc, const char *argv[]) { // close(stdout_pipes[WRITE_END]); // close(stderr_pipes[WRITE_END]); -#if 0 - - // kill(pid, SIGUSR1); - char buf[10]; - ssize_t res = read(stdout_pipes[0], &buf[0], 2); - printf("'%c' (%i)\n", buf[0], res); - // fcntl(stdout_pipes[0], F_GETFD) != -1 || errno != EBADF; -#endif - -#if 1 pthread_t thread; struct thread_data *data = calloc(sizeof *data, 1); @@ -396,7 +433,7 @@ int main (int argc, const char *argv[]) { struct thread_data dat = { .stdout = stdout_pipes[0], .stderr = stderr_pipes[0], - .wiki = wiki_list[i], + .wiki = cmd.wiki_list[i], .peer_pid = pid, .cond = cond, }; @@ -407,15 +444,14 @@ int main (int argc, const char *argv[]) { (void *) data))) { fprintf(stderr, "Failed starting thread: %s\n", strerror(ret)); } -#endif break; } } - sleep(3); + // sleep(3); - for (int i = 0; i < wiki_count; i++) { + for (int i = 0; i < cmd.wiki_count; i++) { fprintf(stderr, "Waiting on %i\n", pids[i]); int status; if (waitpid(pids[i], &status, 0) == -1) { @@ -437,14 +473,14 @@ int main (int argc, const char *argv[]) { } free(wiki_root); - free(wiki_list); + // free(cmd.wiki_list); } int gather_wikis(const char *wiki_root, strlist *wiki_list) { int ret = 0; - glob_t pglob = { 0 }; + glob_t pglob = {}; ret = glob(CALL(strconcat, wiki_root, "/*"), 0, &errfunc, &pglob); @@ -653,8 +689,12 @@ int wiki_do(const char *wiki_root, // FILE *log = fopen("/tmp/hugo/log", "a"); // fprintf(log, "Gonna write!\n"); - /* int count = */printf("-- %s --\n", wiki); - fflush(stdout); + for (;;) { + // syslog(4, "%s Wanting to print", wiki); + int count = printf("-- %s --\n", wiki); + // syslog(4, "%s printed count=%i", wiki, count); + fflush(stdout); + } // fprintf(log, "Wrote %i bytes\n", count); // sprintf(buf, "/proc/%i/fd", getpid()); @@ -673,8 +713,10 @@ int wiki_do(const char *wiki_root, fprintf(log, "%s\n", buf); } closedir(d); -#endif free(buf); +#endif + close(1); + close(2); // :fclose(log); // fflush()q @@ -684,14 +726,14 @@ int wiki_do(const char *wiki_root, return 0; } -char *get_wikiroot() { - { - const char *result = getenv("WIKIROOT"); - if (result != NULL) { - return strdup(result); - } - } - +/** Get home directory of currently logged in user + * Starts by looking at the environment variable HOME, and if that is + * unset, instead get the home directory of the currently logged in + * user, finally defaulting to '/'. + * + * The string returned is valid up until the next call to `getpwuid`. + * */ +const char *get_home() { const char *home = getenv("HOME"); struct passwd *pw; if (home == NULL) { @@ -703,6 +745,19 @@ char *get_wikiroot() { } } + return home; +} + +char *get_wikiroot() { + { + const char *result = getenv("WIKIROOT"); + if (result != NULL) { + return strdup(result); + } + } + + const char *home = getenv("HOME"); + return CALL(strconcat, home, "/wiki"); } |