commit 570ad8dc58ee32d83fc1108a08ad23cf6876ef38
parent f29bb200c1fb86697c4bbda34fbd96c21c169767
Author: Jan Pobrislo <ccx@te2000.cz>
Date: Tue, 30 Jul 2024 18:18:15 +0000
Add WIP miniroon implementation.
Diffstat:
A | src/miniroon.c | | | 134 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 134 insertions(+), 0 deletions(-)
diff --git a/src/miniroon.c b/src/miniroon.c
@@ -0,0 +1,134 @@
+#include <errno.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+#include <skalibs/types.h>
+#include <skalibs/strerr.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/exec.h>
+#include <skalibs/netstring.h>
+#include <skalibs/uint64.h>
+
+#define USAGE "macrun directory"
+#define PROG "macrun"
+
+#define input_fd 0
+#define payload_size_max 1024*1024
+
+typedef struct {
+ char *data;
+ size_t len;
+} bytebuffer_t;
+
+int netstring_get_chunk (const bytebuffer_t *input, bytebuffer_t *chunk, bytebuffer_t *rest)
+{
+ uint64_t nlen; /* size of payload */
+ size_t pos; /* size of numerical prefix */
+ if (!input->len) {
+ return 0;
+ }
+ pos = uint64_scan(input->start, &nlen) ;
+ if (pos >= input->len) {
+ return 0;
+ }
+ if (input->start[pos] != ':') {
+ return 0;
+ }
+ char const *s = input->start + pos + 1; /* start of payload */
+ if (len <= nlen + pos + 1) {
+ return 0;
+ }
+ if (s[nlen] != ',') {
+ return 0;
+ }
+ if (chunk != NULL) {
+ chunk->data = s;
+ chunk->len = nlen;
+ }
+ if (rest != NULL) {
+ chunk->data = s + 1;
+ chunk->len = input->len - nlen - pos - 2;
+ }
+ return 1;
+}
+
+void fd_block(int fd) {
+ int flags = fcntl(fd, F_GETFL);
+ if(flags == -1) {
+ strerr_dief1sys(111, "fcntl() getfd");
+ }
+ if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ strerr_dief1sys(111, "fcntl() setfd");
+ }
+}
+
+int handle_payload(size_t payload_size) {
+ char payload[payload_size+1];
+ char *read_next = payload;
+ ssize_t read_size;
+ while(read_next - payload < payload_size + 1) {
+ read_size = read(input_fd, read_next, payload_size + 1 - (read_next - payload));
+ if(read_size == 0) {
+ strerr_dief1x(111, "EOF before full netstring payload was read");
+ }
+ if(read_size == -1) {
+ if(errno != EINTR) {
+ strerr_dief1sys(111, "read()");
+ }
+ continue;
+ }
+ read_next += read_size;
+ }
+ if(payload[payload_size] != ',') {
+ strerr_dief1x(111, "Invalid netstring terminator");
+ }
+
+ bytebuffer_t input, chunk, next;
+ next.data = payload;
+ next.len = payload_size;
+
+ while(next.len) {
+ input = next;
+ if(!netstring_get_chunk(&input, &chunk, &next)) {
+ strerr_dief1x(111, "Malformed netstring");
+ }
+
+ }
+}
+
+int main (int argc, char const *const *argv)
+{
+ char read_char;
+ size_t payload_size = 0;
+
+ fd_block(input_fd);
+
+ while(payload_size < payload_size_max) {
+ switch(read(input_fd, &read_char, 1)) {
+ case 0:
+ strerr_dief1x(111, "EOF before netstring size was read");
+ break;
+ case 1:
+ if(read_char == ':') {
+ return handle_payload(payload_size);
+ } else if(size_next >= '0' && size_next <= '9') {
+ payload_size *= 10;
+ payload_size += read_char - '0';
+ } else {
+ strerr_dief1x(111, "Malformed netstring on input");
+ }
+ break;
+ }
+ case -1:
+ if(errno != EINTR) {
+ strerr_dief1sys(111, "read()");
+ }
+ break;
+ default:
+ strerr_dief1x(110, "Unexpected return value from read()");
+ break;
+ }
+
+ strerr_dief1x(111, "Input netstring too big");
+ return 111;
+}