The Blog
This commit is contained in:
16
baked.c
16
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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
6
baked.h
6
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_
|
||||
|
2
blog/weird-page.md
Normal file
2
blog/weird-page.md
Normal file
@ -0,0 +1,2 @@
|
||||
# Hello??? Who's here??
|
||||
|
41
blog/welcome.md
Normal file
41
blog/welcome.md
Normal 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
25
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");
|
||||
|
18
main.c
18
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)
|
||||
|
135
routes.c
135
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("<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);
|
||||
}
|
||||
}
|
||||
|
||||
|
19
routes.h
19
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_
|
||||
|
26
tmpls/blog.html
Normal file
26
tmpls/blog.html
Normal 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>
|
@ -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
22
tmpls/template-blog.html
Normal 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>
|
Reference in New Issue
Block a user