From 5db22711be64539a678a80d742fca4ba890afe5f Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Wed, 18 Jun 2025 00:44:18 +0200 Subject: [PATCH] The Blog --- baked.c | 16 +++++ baked.h | 6 ++ blog/weird-page.md | 2 + blog/welcome.md | 41 ++++++++++++ build.c | 25 ++++++-- main.c | 18 +++++- routes.c | 135 ++++++++++++++++++++++++++++++++++++--- routes.h | 19 ++++-- tmpls/blog.html | 26 ++++++++ tmpls/home.html | 1 + tmpls/template-blog.html | 22 +++++++ 11 files changed, 286 insertions(+), 25 deletions(-) create mode 100644 blog/weird-page.md create mode 100644 blog/welcome.md create mode 100644 tmpls/blog.html create mode 100644 tmpls/template-blog.html diff --git a/baked.c b/baked.c index 9349a03..15ac836 100644 --- a/baked.c +++ b/baked.c @@ -10,11 +10,16 @@ INCBIN(gpp1, "./gpp1"); INCBIN(home_html, "./tmpls/home.html"); INCBIN(page_missing_html, "./tmpls/page-missing.html"); +INCBIN(template_blog_html, "./tmpls/template-blog.html"); +INCBIN(blog_html, "./tmpls/blog.html"); INCBIN(simple_min_css, "./etc/simple.min.css"); INCBIN(favicon_ico, "./etc/favicon.ico"); INCBIN(hotreload_js, "./etc/hotreload.js"); +INCBIN(blog_welcome_md, "./blog/welcome.md"); +INCBIN(blog_weird_page_md, "./blog/weird-page.md"); + Baked_Resource *baked_resources = NULL; void add_baked_resource(char *key, const uchar *data, size_t size) @@ -32,10 +37,14 @@ void init_baked_resources(void) { add_baked_resource("home.html", home_html_data, home_html_size); add_baked_resource("page-missing.html", page_missing_html_data, page_missing_html_size); + add_baked_resource("template-blog.html", template_blog_html_data, template_blog_html_size); + add_baked_resource("blog.html", blog_html_data, blog_html_size); add_baked_resource("gpp1", gpp1_data, gpp1_size); add_baked_resource("simple.min.css", simple_min_css_data, simple_min_css_size); add_baked_resource("favicon.ico", favicon_ico_data, favicon_ico_size); add_baked_resource("hotreload.js", hotreload_js_data, hotreload_js_size); + add_baked_resource("blog-welcome.md", blog_welcome_md_data, blog_welcome_md_size); + add_baked_resource("blog-weird-page.md", blog_weird_page_md_data, blog_weird_page_md_size); } void free_baked_resources(void) @@ -56,3 +65,10 @@ bool get_baked_resource_path(char *key, char *buf, size_t size) return false; } +void baked_resource_each(void (*f)(Baked_Resource *resource)) +{ + for (size_t i = 0; i < shlen(baked_resources); i++) { + f(&baked_resources[i]); + } +} + diff --git a/baked.h b/baked.h index d41b7e4..c00513c 100644 --- a/baked.h +++ b/baked.h @@ -7,11 +7,16 @@ INCBIN_EXTERN(gpp1); INCBIN_EXTERN(home_html); INCBIN_EXTERN(page_missing_html); +INCBIN_EXTERN(template_blog_html); +INCBIN_EXTERN(blog_html); INCBIN_EXTERN(simple_min_css); INCBIN_EXTERN(favicon_ico); INCBIN_EXTERN(hotreload_js); +INCBIN_EXTERN(blog_welcome_md); +INCBIN_EXTERN(blog_weird_page_md); + typedef struct { char *key; // path int value; // memfd @@ -20,5 +25,6 @@ typedef struct { void init_baked_resources(void); void free_baked_resources(void); bool get_baked_resource_path(char *key, char *buf, size_t size); +void baked_resource_each(void (*f)(Baked_Resource *resource)); #endif // BAKED_H_ diff --git a/blog/weird-page.md b/blog/weird-page.md new file mode 100644 index 0000000..4012247 --- /dev/null +++ b/blog/weird-page.md @@ -0,0 +1,2 @@ +# Hello??? Who's here?? + diff --git a/blog/welcome.md b/blog/welcome.md new file mode 100644 index 0000000..46b447d --- /dev/null +++ b/blog/welcome.md @@ -0,0 +1,41 @@ +# Welcome to my blog! + +## What is it about? + +This blog is about me and my hobbies - recreational coding, lifting weights and other miscellaneous things. +This is pretty much a dumping ground for my thoughts, ideas, opinions and whatever I have on my mind. Don't expect +clean, structured, nice and neutral/unbiased writing. Here I can say what I want. + +## Who am I? + +At time time of writing this post (17.06.2026) I'm 18 years old. I'm from Poland/Warsaw. + +### Coding + +I've started coding in about 6th grade with the help from my dad. I've been through a tough webdev phase +and for the past 4-ish years I've been coding strictly in C (touched some other languages here and there, but nothing special). + +C is what makes coding actually fun for me. With C I can build *almost* anything you can imagine. What draws me to such an old +is that C doesn't hide/abstract away things from you. Everything is on the programmer, from memory management to the build +system and whatnot. I find this type of freedom quite comfortable. I'm not tied to a single build system, package manager or +even compiler. Any moment I can say *"fuck GCC, I'm switching to Clang now!"* and there isn't much that can stop me +(assuming the codebase doesn't rely too much on compiler-specific behaviour). I can build my +projects with Make, but I can always choose CMake, Meson or some other next-gen-trubo-slop build tool. + +**I AM FREE** + +### Lifting + +About 3 years ago I've started going to the gym and lifting weights. For the first year I've been mostly goofing around +without any specific training regimen. I've followed the standard eat big, get big and go heavy advice (which I think is +the best for beginners, honestly). Since the beginning of my journey I've always had a bias towards lower-body exercises +like the leg press, squats, deadlifts etc. + +My best lifts so far are: +- 185kg deadlift x 1 +- 140kg squat x 5 +- 100kg sandbag to shoulder x 1 +- Rowing 100kg for reps +- 80kg x 3 over head press +- 112kg dip x 3 + diff --git a/build.c b/build.c index 8a00c95..7328f35 100644 --- a/build.c +++ b/build.c @@ -17,18 +17,29 @@ int main(int argc, char ** argv) "./main.c", "./routes.c", "./baked.c", + "./mongoose.o", "./gpp1", - "./tmpls/home.t", - "./tmpls/page-missing.t", - "./etc/hotreload.js" + + "./tmpls/home.html", + "./tmpls/page-missing.html", + "./tmpls/template-blog.html", + "./tmpls/blog.html", + + "./etc/hotreload.js", + "./etc/simple.min.css", + + "./blog/welcome.md", + "./blog/weird-page.md" ) { RULE("./mongoose.o", "./mongoose/mongoose.c") { #if DEBUG - CMD("cc", "-ggdb", "-c", "-fPIC", "-D_GNU_SOURCE", "-o", "./mongoose.o", "./mongoose/mongoose.c"); + CMD("cc", "-ggdb", "-c", "-fPIC", "-Wl,-z,execstack", "-D_GNU_SOURCE", + "-o", "./mongoose.o", "./mongoose/mongoose.c"); #else - CMD("cc", "-c", "-fPIC", "-D_GNU_SOURCE", "-o", "./mongoose.o", "./mongoose/mongoose.c"); + CMD("cc", "-c", "-fPIC", "-Wl,-z,exectack", "-D_GNU_SOURCE", "-o", + "./mongoose.o", "./mongoose/mongoose.c"); #endif } @@ -38,13 +49,13 @@ int main(int argc, char ** argv) #if DEBUG CMD("cc", "-fPIC", "-ggdb", "-I.", "-DDEBUG=1", "-D_GNU_SOURCE", "-DGEBS_NO_PREFIX", - "-DINCBIN_PREFIX=", "-DINCBIN_STYLE=INCBIN_STYLE_SNAKE", "-o", "./aboba", + "-DINCBIN_PREFIX=", "-DINCBIN_STYLE=INCBIN_STYLE_SNAKE", "-Wl,-z,execstack", "-o", "./aboba", "./main.c", "./routes.c", "./baked.c", "./mongoose.o", "./cJSON/cJSON.c", "./md5-c/md5.c", "-lpthread"); #else CMD("cc", "-fPIC", "-I.", "-D_GNU_SOURCE", "-DGEBS_NO_PREFIX", - "-DINCBIN_PREFIX=", "-DINCBIN_STYLE=INCBIN_STYLE_SNAKE", "-o", "./aboba", + "-DINCBIN_PREFIX=", "-DINCBIN_STYLE=INCBIN_STYLE_SNAKE", "-Wl,-z,execstack", "-o", "./aboba", "./main.c", "./routes.c", "./baked.c", "./mongoose.o", "./cJSON/cJSON.c", "./md5-c/md5.c", "-lpthread"); diff --git a/main.c b/main.c index 9fd3a6e..82932a9 100644 --- a/main.c +++ b/main.c @@ -37,10 +37,10 @@ void *route_thread_function(void *param) char key[MG_PATH_MAX] = {0}; strncpy(key, http_msg.uri.buf, http_msg.uri.len); - Route_Handler handler = shget(route_hashtable, key); + ssize_t idx = shgeti(route_hashtable, key); Route_Result result = {0}; - handler(&http_msg, &result); + route_hashtable[idx].value(&http_msg, &result, route_hashtable[idx].context_data); mg_wakeup(data->mgr, data->conn_id, &result, sizeof(result)); free(data->message.buf); @@ -91,6 +91,20 @@ void init_route_hashtable(void) shput(route_hashtable, "/hotreload.js", &route_hotreload_js); shput(route_hashtable, "/", &route_home); shput(route_hashtable, "/build-id", &route_build_id); + shput(route_hashtable, "/blog", &route_blog); + + void put_blogs(Baked_Resource *resource) + { + if ((strlen(resource->key) >= strlen("blog-")) + && strncmp(resource->key, "blog-", strlen("blog-")) == 0) { + char *path = malloc(MG_PATH_MAX); + snprintf(path, MG_PATH_MAX, "/%s", resource->key); + shput(route_hashtable, path, &route_generic_blog); + route_hashtable[shgeti(route_hashtable, path)].context_data = (void *)resource; + } + } + + baked_resource_each(&put_blogs); } int main(int argc, char ** argv) diff --git a/routes.c b/routes.c index 25d5416..3dcb438 100644 --- a/routes.c +++ b/routes.c @@ -70,7 +70,7 @@ bool gpp_run(char *path, NString_List *env, String_Builder *out) return cmd_run_collect(&cmd, out) == 0; } -void route_build_id(struct mg_http_message *msg, Route_Result *result) +ROUTE_HANDLER(build_id) { cJSON *root = cJSON_CreateObject(); defer { cJSON_Delete(root); } @@ -81,9 +81,7 @@ void route_build_id(struct mg_http_message *msg, Route_Result *result) String_Builder sb = {0}; defer { sb_free(&sb); } for (size_t i = 0; i < 16; i++) { - char tmp[3]; - snprintf(tmp, sizeof(tmp), "%02x", md5_buf[i]); - sb_append_nstr(&sb, tmp); + sb_append_nstr(&sb, fmt("%02x", md5_buf[i])); } sb_finish(&sb); @@ -92,7 +90,7 @@ void route_build_id(struct mg_http_message *msg, Route_Result *result) make_application_json(result, 200, root); } -void route_page_not_found(struct mg_http_message *msg, Route_Result *result) +ROUTE_HANDLER(page_not_found) { NString_List env = {0}; defer { list_free(&env); } @@ -124,7 +122,7 @@ void route_page_not_found(struct mg_http_message *msg, Route_Result *result) } } -void route_simple_css(struct mg_http_message *msg, Route_Result *result) +ROUTE_HANDLER(simple_css) { char path[PATH_MAX] = {0}; if (!get_baked_resource_path("simple.min.css", path, sizeof(path))) { @@ -143,7 +141,7 @@ void route_simple_css(struct mg_http_message *msg, Route_Result *result) make_text(result, "css", 200, sb.items); } -void route_favicon(struct mg_http_message *msg, Route_Result *result) +ROUTE_HANDLER(favicon) { char path[PATH_MAX] = {0}; if (!get_baked_resource_path("favicon.ico", path, sizeof(path))) { @@ -162,7 +160,7 @@ void route_favicon(struct mg_http_message *msg, Route_Result *result) make_image_xicon(result, 200, sb.items); } -void route_hotreload_js(struct mg_http_message *msg, Route_Result *result) +ROUTE_HANDLER(hotreload_js) { char path[PATH_MAX] = {0}; if (!get_baked_resource_path("hotreload.js", path, sizeof(path))) { @@ -181,7 +179,7 @@ void route_hotreload_js(struct mg_http_message *msg, Route_Result *result) make_text(result, "javascript", 200, sb.items); } -void route_home(struct mg_http_message *msg, Route_Result *result) +ROUTE_HANDLER(home) { NString_List env = {0}; defer { list_free(&env); } @@ -210,3 +208,122 @@ void route_home(struct mg_http_message *msg, Route_Result *result) make_text(result, "html", 200, out.items); } } + +ROUTE_HANDLER(generic_blog) +{ + NString_List env = {0}; + defer { list_free(&env); } + + String_Builder out = {0}; + defer { sb_free(&out); } + + Baked_Resource *resource = (Baked_Resource *)context_data; + + char md_path[PATH_MAX] = {0}; + if (!get_baked_resource_path(resource->key, md_path, sizeof(md_path))) { + make_internal_server_error(result); + return; + } + + #if DEBUG + list_append(&env, "-DHOTRELOAD=1"); + #else + list_append(&env, "-DHOTRELOAD=0"); + #endif + + String_Builder md = {0}; + defer { sb_free(&md); } + if (!sb_read_file(&md, md_path)) { + make_internal_server_error(result); + return; + } + + String_Builder md_prepared = {0}; + defer { sb_free(&md_prepared); } + for (size_t i = 0; i < md.count; i++) { + char c = md.items[i]; + switch (c) { + case '\"': sb_append_nstr(&md_prepared, "\\\""); break; + case '\'': sb_append_nstr(&md_prepared, "\\\'"); break; + case '\\': sb_append_nstr(&md_prepared, "\\\\"); break; + case '\a': sb_append_nstr(&md_prepared, "\\a"); break; + case '\b': sb_append_nstr(&md_prepared, "\\b"); break; + case '\r': sb_append_nstr(&md_prepared, "\\r"); break; + case '\n': sb_append_nstr(&md_prepared, "\\n"); break; + case '\t': sb_append_nstr(&md_prepared, "\\t"); break; + default: + if (iscntrl(md.items[i])) { + sb_append_nstr(&md_prepared, fmt("\\%03o", c)); + } else { + sb_append_char(&md_prepared, c); + } + break; + } + } + sb_finish(&md_prepared); + + list_append(&env, fmt("-DBLOG_POST_TITLE=%s", resource->key)); + list_append(&env, fmt("-DBLOG_POST_MARKDOWN=%s", md_prepared.items)); + + char tmpl_file[PATH_MAX] = {0}; + if (!get_baked_resource_path("template-blog.html", tmpl_file, sizeof(tmpl_file))) { + make_internal_server_error(result); + return; + } + + bool ok = gpp_run(tmpl_file, &env, &out); + sb_finish(&out); + + if (!ok) { + make_internal_server_error(result); + } else { + make_text(result, "html", 200, out.items); + } +} + +ROUTE_HANDLER(blog) +{ + NString_List env = {0}; + defer { list_free(&env); } + + String_Builder out = {0}; + defer { sb_free(&out); } + + Arena tmp = arena_get(); + defer { arena_destroy(&tmp); } + + String_Builder sb = {0}; + void collect_blogs(Baked_Resource *resource) + { + if ((strlen(resource->key) >= strlen("blog-")) + && strncmp(resource->key, "blog-", strlen("blog-")) == 0) { + sb_append_nstr_alloc(&tmp, &sb, fmt("
  • %s
  • ", resource->key, resource->key)); + } + } + + baked_resource_each(&collect_blogs); + sb_finish_alloc(&tmp, &sb); + list_append(&env, fmt("-DBLOG_POSTS=%s", sb.items)); + + char path[PATH_MAX] = {0}; + if (!get_baked_resource_path("blog.html", path, sizeof(path))) { + make_internal_server_error(result); + return; + } + + #if DEBUG + list_append(&env, "-DHOTRELOAD=1"); + #else + list_append(&env, "-DHOTRELOAD=0"); + #endif + + bool ok = gpp_run(path, &env, &out); + sb_finish(&out); + + if (!ok) { + make_internal_server_error(result); + } else { + make_text(result, "html", 200, out.items); + } +} + diff --git a/routes.h b/routes.h index 591a6c2..2d89168 100644 --- a/routes.h +++ b/routes.h @@ -16,18 +16,23 @@ typedef struct { struct mg_str message; } Route_Thread_Data; -typedef void (*Route_Handler)(struct mg_http_message *msg, Route_Result *result); +typedef void (*Route_Handler)(struct mg_http_message *msg, Route_Result *result, void *context_data); typedef struct { char *key; // path Route_Handler value; + void *context_data; } Route; -void route_page_not_found(struct mg_http_message *msg, Route_Result *result); -void route_simple_css(struct mg_http_message *msg, Route_Result *result); -void route_favicon(struct mg_http_message *msg, Route_Result *result); -void route_hotreload_js(struct mg_http_message *msg, Route_Result *result); -void route_home(struct mg_http_message *msg, Route_Result *result); -void route_build_id(struct mg_http_message *msg, Route_Result *result); +#define ROUTE_HANDLER(name) void route_##name(struct mg_http_message *msg, Route_Result *result, void *context_data) + +ROUTE_HANDLER(page_not_found); +ROUTE_HANDLER(simple_css); +ROUTE_HANDLER(favicon); +ROUTE_HANDLER(hotreload_js); +ROUTE_HANDLER(home); +ROUTE_HANDLER(build_id); +ROUTE_HANDLER(generic_blog); +ROUTE_HANDLER(blog); #endif // ROUTES_H_ diff --git a/tmpls/blog.html b/tmpls/blog.html new file mode 100644 index 0000000..6552882 --- /dev/null +++ b/tmpls/blog.html @@ -0,0 +1,26 @@ + + + + Blog + + + + +

    Blog posts

    +

    + This page aggregates all blog posts. + Welcome (or not) post +

    + + + + + <#if HOTRELOAD> + + <#endif> + + diff --git a/tmpls/home.html b/tmpls/home.html index 0b89bb7..8784744 100644 --- a/tmpls/home.html +++ b/tmpls/home.html @@ -10,6 +10,7 @@
    home projects + blog

    Written in C™. Check out the source code here!

    diff --git a/tmpls/template-blog.html b/tmpls/template-blog.html new file mode 100644 index 0000000..d6430c9 --- /dev/null +++ b/tmpls/template-blog.html @@ -0,0 +1,22 @@ + + + + + <#BLOG_POST_TITLE> + + + +
    + + + + + <#if HOTRELOAD> + + <#endif> + +