This commit is contained in:
kamkow1
2025-06-18 00:44:18 +02:00
parent 9bb248ee03
commit 5db22711be
11 changed files with 286 additions and 25 deletions

16
baked.c
View File

@ -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]);
}
}

View File

@ -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_

2
blog/weird-page.md Normal file
View File

@ -0,0 +1,2 @@
# Hello??? Who's here??

41
blog/welcome.md Normal file
View File

@ -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

25
build.c
View File

@ -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");

18
main.c
View File

@ -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)

135
routes.c
View File

@ -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("<li><a href=\"/%s\">%s</a></li>", 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);
}
}

View File

@ -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_

26
tmpls/blog.html Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>Blog</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/simple.min.css" />
</head>
<body>
<h1>Blog posts</h1>
<p>
This page aggregates all blog posts.
<a href="/blog-welcome.md">Welcome (or not) post</a>
</p>
<ul>
<#BLOG_POSTS>
</ul>
<footer>
<a href="/">HOME</a>
</footer>
<#if HOTRELOAD>
<script src="/hotreload.js"></script>
<#endif>
</body>
</html>

View File

@ -10,6 +10,7 @@
<div style="float: left;">
<a class="button" href="/">home</a>
<a class="button" href="/#projects">projects</a>
<a class="button" href="/blog">blog</a>
</div>
<p>Written in C™. <a href="https://gitlab.com/kamkow1/aboba" target="_blank">Check out the source code here!</a></p>
<section id="projects">

22
tmpls/template-blog.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title><#BLOG_POST_TITLE></title>
<link rel="stylesheet" href="/simple.min.css" />
</head>
<body>
<div id="content"></div>
<footer>
<a href="/">HOME</a>
</footer>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
document.getElementById("content").innerHTML = marked.parse(`<#BLOG_POST_MARKDOWN>`);
</script>
<#if HOTRELOAD>
<script src="/hotreload.js"></script>
<#endif>
</body>
</html>