diff --git a/.gitignore b/.gitignore index b8e5b53..8cb2683 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,4 @@ Mkfile.old dkms.conf bin/ +zig-cache/ diff --git a/README.md b/README.md index c514988..c08ad5f 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,10 @@ source is open, data is closed, this is for my own personal use ## depedencies - a robot girl to use those utils - - posix compliant make - - a c compiler + - the zig compiler https://ziglang.org ``` -make - -# or just remove PREFIX for /usr/local -make PREFIX=$HOME/.local install +zig build install --prefix ~/.local/ ``` ## using diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..4327cde --- /dev/null +++ b/build.zig @@ -0,0 +1,31 @@ +const Builder = @import("std").build.Builder; + +pub fn build(b: *Builder) void { + const mode = b.standardReleaseOptions(); + const exe = b.addExecutable("journal", null); + exe.setBuildMode(mode); + exe.linkSystemLibrary("c"); + + const source_files = [_][]const u8{"src/journal/main.c"}; + + for (source_files) |source| { + exe.addCSourceFile(source, [_][]const u8{"-Wall"}); + } + + const zig_sources = [_][]const u8{"src/journal/journal.zig"}; + + for (zig_sources) |source| { + const obj = b.addObject("journal", source); + obj.linkSystemLibrary("c"); + exe.addObject(obj); + } + + // enable us to run the main journal executable via + // the build system + const run_cmd = exe.run(); + const run_step = b.step("run", "Run journal"); + run_step.dependOn(&run_cmd.step); + + b.default_step.dependOn(&exe.step); + b.installArtifact(exe); +} diff --git a/src/journal/format.h b/src/journal/format.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/journal/journal.c b/src/journal/journal.c deleted file mode 100644 index fa8137f..0000000 --- a/src/journal/journal.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include - -// functions to deal with the journal file - - -FILE *journal_open(char *topic) -{ - char *home_path = getenv("HOME"); - - // combine w/ home path - char *journal_dir = (char*)malloc(1024); - snprintf(journal_dir, 1024, "%s/.lunabot", home_path); - - // construct a 744 - mkdir(journal_dir, S_IRWXU | S_IRGRP | S_IROTH); - - char *journal_path = (char*)malloc(1024); - snprintf(journal_path, 1024, "%s/%s", journal_dir, topic); - - FILE* res = fopen(journal_path, "a"); - - free(journal_path); - free(journal_dir); - - return res; -} - -void journal_write(FILE* journal_fd, char* message) -{ - // TODO: strlen()? - fwrite(message, strlen(message), 1, journal_fd); -} - -void journal_close(FILE* journal_fd) -{ - fclose(journal_fd); -} - -void journal_write_topic(FILE *journal_fd, char *topic, char *message) -{ - char *tstamp = malloc(128 * sizeof(char)); - char fmt_msg[512]; - - time_t rawtime; - time(&rawtime); - const struct tm *cur_time = gmtime(&rawtime); - strftime(tstamp, 128, "%c", cur_time); - - sprintf(fmt_msg, "[%s] [%s]: %s\n", tstamp, topic, message); - free(tstamp); - - journal_write(journal_fd, fmt_msg); -} diff --git a/src/journal/journal.h b/src/journal/journal.h index 63ffe95..f6cf8bb 100644 --- a/src/journal/journal.h +++ b/src/journal/journal.h @@ -8,9 +8,9 @@ #define STREQ(a, b) strcmp(a, b) == 0 -FILE *journal_open(char *topic); -void journal_write(FILE*, char* message); -void journal_write_topic(FILE*, char *topic, char *message); -void journal_close(FILE*); +int journal_open(char *topic); +void journal_write(int, char* message); +void journal_write_topic(int, char *topic, char *message); +void journal_close(int); #endif diff --git a/src/journal/journal.zig b/src/journal/journal.zig new file mode 100644 index 0000000..d320aa0 --- /dev/null +++ b/src/journal/journal.zig @@ -0,0 +1,119 @@ +const std = @import("std"); +const os = std.os; + +const c = @cImport({ + @cInclude("stdio.h"); + @cInclude("stdlib.h"); + @cInclude("sys/stat.h"); + @cInclude("string.h"); + @cInclude("time.h"); +}); + +const warn = std.debug.warn; +const allocator = std.heap.c_allocator; + +fn sliceify(ptr: [*]u8) []u8 { + return ptr[0..c.strlen(ptr)]; +} + +fn sliceifyKnown(slice: []u8) []u8 { + return slice[0..c.strlen(slice.ptr)]; +} + +export fn journal_open(topic_cptr: ?[*]u8) os.fd_t { + const topic = sliceify(topic_cptr.?); + + const journal_dir = std.fs.path.resolve(allocator, [_][]const u8{ + std.os.getenvC(c"HOME").?, + ".lunabot", + }) catch |err| { + warn("failed to resolve paths: {}\n", err); + return -1; + }; + + warn("journal_dir = {}\n", journal_dir); + + std.fs.makeDir(journal_dir) catch |err| { + if (err != error.PathAlreadyExists) { + warn("failed to create journal dir {}: {}\n", journal_dir, err); + return -1; + } + }; + + const journal_path = std.fmt.allocPrint(allocator, "{}/{}", journal_dir, topic) catch |err| { + warn("failed to allocprint journal path: {}\n", err); + return -1; + }; + defer allocator.free(journal_path); + + warn("journal_path = {}\n", journal_path); + + const fd = std.os.open( + journal_path, + std.os.O_WRONLY | std.os.O_CREAT | std.os.O_APPEND, + 0o755, + ) catch |err| { + warn("failed to open {}: {}\n", journal_path, err); + return -1; + }; + + return fd; +} + +export fn journal_write(journal: os.fd_t, message_cptr: ?[*]u8) void { + std.os.write( + journal, + sliceify(message_cptr.?), + ) catch |err| { + std.debug.warn("Error while writing to file: {}\n", err); + return; + }; +} + +export fn journal_close(journal: os.fd_t) void { + std.os.close(journal); +} + +export fn journal_write_topic( + journal: os.fd_t, + topic_cptr: ?[*]u8, + message_cptr: ?[*]u8, +) void { + var topic = sliceify(topic_cptr.?); + var message = sliceify(message_cptr.?); + + var tstamp_total = allocator.alloc(u8, 128) catch |err| { + warn("failed to allocate string for timestamp\n"); + return; + }; + defer allocator.free(tstamp_total); + + var rawtime: c.time_t = undefined; + + _ = c.time(&rawtime); + var cur_time: [*c]const c.struct_tm = c.gmtime(&rawtime); + _ = c.strftime(tstamp_total.ptr, usize(128), c"%c", cur_time); + + var tstamp = sliceifyKnown(tstamp_total); + + std.debug.warn("tstamp: {}\ntopic: {}\nmsg: {}\n", tstamp, topic, message); + + var fmt_msg = std.fmt.allocPrint( + allocator, + "[{}] [{}]: {}\n", + tstamp, + topic, + message, + ) catch |err| { + warn("Failed to make formatted message: {}\n", err); + return; + }; + + // catch unreachable is intended. + var fmt_msg_cstr = std.cstr.addNullByte( + allocator, + fmt_msg, + ) catch unreachable; + + journal_write(journal, fmt_msg_cstr.ptr); +} diff --git a/src/journal/main.c b/src/journal/main.c index da0d023..d145905 100644 --- a/src/journal/main.c +++ b/src/journal/main.c @@ -63,7 +63,7 @@ int main(int argc, char** argv) // default handling by journal_write_topic is marked // as the NULL values in this array. - void (*handlers[])(FILE*, char*) = { + void (*handlers[])(int, char*) = { NULL, NULL, NULL }; @@ -91,9 +91,13 @@ int main(int argc, char** argv) if(strcmp(topic, cur_topic) == 0) { - void (*fun_ptr)(FILE*, char*) = handlers[i]; + void (*fun_ptr)(int, char*) = handlers[i]; - FILE* journal_file = journal_open(topic); + int journal_file = journal_open(topic); + if(journal_file == -1) { + printf("failed to open journal file.\n"); + return 1; + } char *handler_message = extract_handler_msg(argc, argv); printf("[%s] said '%s'\n", topic, handler_message);