aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2023-10-14 13:30:16 +0200
committerHugo Hörnquist <hugo@lysator.liu.se>2023-10-14 13:30:16 +0200
commit072173228aaab17be2a2600d4ad93052d1b609e1 (patch)
treef193cb093013d7e00fa27ff9338cd03289b5d40c
parenttor 5 okt 2023 16:37:35 CEST (diff)
downloadwiki-public-072173228aaab17be2a2600d4ad93052d1b609e1.tar.gz
wiki-public-072173228aaab17be2a2600d4ad93052d1b609e1.tar.xz
lör 14 okt 2023 13:30:16 CEST
-rw-r--r--.gitignore1
-rw-r--r--Makefile7
-rw-r--r--wiki.c185
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
diff --git a/Makefile b/Makefile
index 9d93ccd..436ab9b 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/wiki.c b/wiki.c
index eae2ae1..ac41ba4 100644
--- a/wiki.c
+++ b/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");
}