aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..99769f2
--- /dev/null
+++ b/main.c
@@ -0,0 +1,182 @@
+/**
+ * part of Hydrilla
+ * Program entry point.
+ *
+ * Copyright (C) 2021 Wojtek Kosior
+ * Redistribution terms are gathered in the `copyright' file.
+ */
+
+#define _POSIX_C_SOURCE 200809L /* S_IFMT, S_IFDIR */
+
+#include <dirent.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <cjson/cJSON.h>
+
+#include "string_buf.h"
+#include "hashtable.h"
+
+#include "scriptbase.h"
+
+#define PRESERVE_ERRNO(call) \
+ do { \
+ int VERY_UNLIKELY_TO_COLLIDE_NAME_$$$$$$$$##__LINE__ = errno; \
+ call; \
+ errno = VERY_UNLIKELY_TO_COLLIDE_NAME_$$$$$$$$##__LINE__; \
+ } while (0)
+
+static const char default_search_path[] = "/var/lib/hydrilla/content/";
+
+static int process_scriptbase_subdir(struct scriptbase *base,
+ struct dirent *subdir,
+ struct stringbuf *path_buf,
+ struct stringbuf *json_buf)
+{
+ struct stat statbuf;
+ cJSON *index_json;
+ int retval = -1;
+ size_t initial_len = path_buf->buf_filled, len_dirname;
+
+ if (sb_string(path_buf, subdir->d_name))
+ return -1;
+
+ len_dirname = path_buf->buf_filled;
+
+ if (stat(path_buf->buf, &statbuf))
+ return -1;
+
+ if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
+ return 0;
+
+ if (sb_string(path_buf, "/index.json"))
+ return -1;
+
+ printf("Reading %s\n", path_buf->buf);
+
+ stringbuf_truncate(json_buf, 0);
+ if (sb_filepath(json_buf, path_buf->buf))
+ return -1;
+
+ index_json = cJSON_Parse(json_buf->buf);
+ if (!index_json) {
+ fprintf(stderr, "Failed to parse json.\n");
+ return -1;
+ }
+
+ stringbuf_truncate(path_buf, len_dirname);
+
+ retval = catalogue_component(path_buf->buf + initial_len,
+ index_json, base);
+
+ PRESERVE_ERRNO(cJSON_Delete(index_json));
+
+ return retval;
+}
+
+static int prepare_scriptbase_from_dir(const char *dir_path,
+ struct scriptbase *base)
+{
+ DIR *maindir;
+ struct dirent *subdir;
+ struct stringbuf path_buf;
+ struct stringbuf json_buf;
+ size_t base_path_len;
+ int retval = -1;
+
+ printf("Searching %s\n", dir_path);
+ stringbuf_init(&path_buf);
+ stringbuf_init(&json_buf);
+
+ maindir = opendir(dir_path);
+ if (!maindir)
+ goto end;
+
+ if (scriptbase_init(base, "https://hydrilla.koszko.org/resources"))
+ goto end;
+
+ if (sb_sprintf(&path_buf, "%s/", dir_path))
+ goto end;
+
+ base_path_len = path_buf.buf_filled;
+
+ while (true) {
+ errno = 0;
+ subdir = readdir(maindir);
+ if (!subdir) {
+ if (!errno)
+ retval = 0;
+ break;
+ }
+
+ if (!strcmp(subdir->d_name, "..") ||
+ !strcmp(subdir->d_name, "."))
+ continue;
+
+ stringbuf_truncate(&path_buf, base_path_len);
+
+ errno = 0;
+ if (process_scriptbase_subdir(base, subdir,
+ &path_buf, &json_buf)) {
+ fprintf(stderr, "Error processing subdirectory %s%s",
+ subdir->d_name, errno ? ": " : ".\n");
+ if (errno)
+ perror(NULL);
+ }
+ }
+
+end:
+ if (errno)
+ perror(NULL);
+ stringbuf_destroy(&path_buf);
+ stringbuf_destroy(&json_buf);
+ if (maindir)
+ closedir(maindir);
+ if (retval)
+ scriptbase_destroy(base);
+
+ printf("Search in %s %s.\n", dir_path, retval ? "failed" : "finished");
+
+ return retval;
+}
+
+static void print_component_name(const void *key, void *val, void *arg)
+{
+ char type = (char) (size_t) arg;
+ bool unfilled;
+
+ unfilled =
+ (type == 's' && !((struct script*) val)->filled) ||
+ (type == 'b' && !((struct bag*) val)->filled);
+
+ printf("%s%s\n", (const char*) key,
+ unfilled ? " (referenced only)" : "");
+}
+
+int serve_scriptbase(struct scriptbase *base);
+
+int main(int argc, char *argv[])
+{
+ struct scriptbase base;
+ const char *search_path = default_search_path;
+
+ if (argc > 1)
+ search_path = argv[1];
+
+ if (prepare_scriptbase_from_dir(search_path, &base))
+ return -1;
+ puts("## LOADED SCRIPTS:");
+ ht_map(&base.scripts, (void*) 's', print_component_name);
+ puts("## LOADED BAGS:");
+ ht_map(&base.bags, (void*) 'b', print_component_name);
+ puts("## LOADED PAGES:");
+ ht_map(&base.pages, (void*) 'p', print_component_name);
+
+ if (serve_scriptbase(&base))
+ fprintf(stderr, "Error serving scriptbase.\n");
+
+ scriptbase_destroy(&base);
+ return 0;
+}