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("
+ This page aggregates all blog posts. + Welcome (or not) post +
+Written in C™. Check out the source code here!