summaryrefslogtreecommitdiff
path: root/ape/boot/boot.zc
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-25 18:24:05 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-25 18:24:05 +0000
commite3ab29bb4d7174cae65de2275f19105eb3d93d91 (patch)
tree89970111c1be4c3ddd291b720d4fdf496f10b2d5 /ape/boot/boot.zc
parent489336b2101bf16edeec7bfc4379408eb19b936e (diff)
APE shall never kill APE
Diffstat (limited to 'ape/boot/boot.zc')
-rw-r--r--ape/boot/boot.zc118
1 files changed, 118 insertions, 0 deletions
diff --git a/ape/boot/boot.zc b/ape/boot/boot.zc
new file mode 100644
index 0000000..176f668
--- /dev/null
+++ b/ape/boot/boot.zc
@@ -0,0 +1,118 @@
+#define _COSMO_SOURCE
+#include <libc/cosmo.h>
+#include <string.h>
+#include <stdlib.h>
+
+raw {
+ extern char **environ;
+}
+
+fn normalize_wait(ws: int) -> int {
+ if ws == -1 { return -1 }
+ if WIFEXITED(ws) { return WEXITSTATUS(ws) }
+ if WIFSIGNALED(ws) { return 128 + WTERMSIG(ws) }
+ return -1;
+}
+
+fn run_exec(argv: char**) -> int {
+ fflush(NULL);
+ let ws: int = systemvpe(argv[0], argv, environ);
+ return normalize_wait(ws);
+}
+
+fn needs_quote(s: char*) -> bool {
+ for (let p = s; *p; ++p) {
+ if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '"' || *p == '\'' )
+ return true;
+ }
+ return false;
+}
+
+fn print_quoted(s: char*) {
+ if !needs_quote(s) {
+ print f"{s}";
+ return;
+ }
+
+ print f"'";
+ for (let p = s; *p; ++p) {
+ if (*p == '\'') {
+ print f"'\"'\"'";
+ } else {
+ print f"{*p:c}";
+ }
+ }
+ print f"'";
+}
+
+fn log_cmd(argv: char**) {
+ print f"$ ";
+ let i = 0;
+ while argv[i] != NULL {
+ if i { print f" " }
+ print_quoted(argv[i]);
+ i++;
+ }
+ print f"\n";
+}
+
+fn main(argc: int, argv: string*) {
+ def delim = "::";
+
+ let newargc: int = cosmo_args("/zip/.args", &argv);
+ if newargc != -1 { argc = newargc }
+
+ let i = 1;
+ while i < argc && strcmp(argv[i], delim) { i++ }
+
+ while i < argc {
+ if strcmp(argv[i], delim) {
+ f"Expected '{delim}' before each command, got: {argv[i]}";
+ return 2;
+ }
+ i++;
+
+ let start = i;
+ while i < argc && strcmp(argv[i], delim) { i++ }
+ let cmd_argc = i - start;
+
+ if cmd_argc <= 0 {
+ f"Empty command after '{delim}'";
+ return 2;
+ }
+
+ let rc = 0;
+
+ if !strcmp(argv[start], "system") {
+ if cmd_argc != 3 {
+ !"error: system expects 2 arguments, got {cmd_argc}";
+ return -4;
+ }
+
+ if strcmp(argv[start + 1], "-c") {
+ !"error: system got '{argv[start + 1]}' instead of -c";
+ return -5;
+ }
+
+ "$ {argv[start + 2]}";
+ rc = normalize_wait(system(argv[start + 2]));
+
+ if rc { return rc }
+
+ continue;
+ }
+
+ autofree let cmdv = (char**)malloc((cmd_argc + 1) * sizeof(char*));
+ if !cmdv { return 1 }
+ for (let k = 0; k < cmd_argc; k++) { cmdv[k] = argv[start + k] }
+ cmdv[cmd_argc] = NULL;
+
+ log_cmd(cmdv);
+
+ rc = run_exec(cmdv);
+
+ if rc { return rc }
+ }
+
+ return 0;
+}