commit 9d44184892f36ff0ccb45f417d4f321955247f65
Author: evenfri <evenfri256@gmail.com>
Date: Mon, 27 Jul 2026 17:39:44 +0800
initial commit
Diffstat:
| A | .gitignore | | | 4 | ++++ |
| A | README | | | 17 | +++++++++++++++++ |
| A | cat.c | | | 30 | ++++++++++++++++++++++++++++++ |
| A | cc | | | 11 | +++++++++++ |
| A | echo.c | | | 12 | ++++++++++++ |
| A | free.c | | | 112 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | init.c | | | 40 | ++++++++++++++++++++++++++++++++++++++++ |
| A | ls.c | | | 31 | +++++++++++++++++++++++++++++++ |
| A | mkfile | | | 18 | ++++++++++++++++++ |
| A | pwd.c | | | 11 | +++++++++++ |
| A | sh/main.c | | | 70 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | sh/mkfile | | | 12 | ++++++++++++ |
12 files changed, 368 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,4 @@
+**/*.o
+**/o.*
+mk-standalone/
+libc/
diff --git a/README b/README
@@ -0,0 +1,17 @@
+coreutils
+=========
+
+my custom mini coreutils with my libc
+
+start
+=====
+
+ git clone https://codeberg.org/evenfri/mk-standalone.git
+ cd mk-standalone
+ ./install
+ cd ..
+ git clone https://codeberg.org/evenfri/libc.git
+ cd libc
+ mk
+ cd ..
+ mk
diff --git a/cat.c b/cat.c
@@ -0,0 +1,30 @@
+#include <libc.h>
+
+#define buf_size 1024
+
+int main(int argc, char *argv[]) {
+ if (argc < 2) {
+ write(stderr, "usage: cat <file> [file] ...\n", 29);
+ return 1;
+ }
+
+ char buf[buf_size];
+ ssize_t n;
+
+ for (int i = 1; i < argc; i++) {
+ int fd = open(argv[i], o_rdonly, 0);
+ if (fd < 0) {
+ write(stderr, "cat: cannot open file: ", 23);
+ write(stderr, argv[i], strlen(argv[i]));
+ write(stderr, "\n", 1);
+ continue;
+ }
+
+ while ((n = read(fd, buf, sizeof(buf))) > 0) {
+ write(stdout, buf, n);
+ }
+
+ close(fd);
+ }
+ return 0;
+}
diff --git a/cc b/cc
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+INC=$(cc -print-file-name=include)
+exec cc -fstack-protector-all \
+ -mstack-protector-guard=global \
+ -nostdlib \
+ -nostdinc \
+ -ffreestanding \
+ -fno-builtin \
+ -isystem "$INC" \
+ "$@"
diff --git a/echo.c b/echo.c
@@ -0,0 +1,12 @@
+#include <libc.h>
+
+int main(int argc, char *argv[]) {
+
+ for (int i = 1; i < argc; i++) {
+ write(stdout, argv[i], strlen(argv[i]));
+ write(stdout, " ", 1);
+ }
+
+ write(stdout, "\n", 1);
+ return 0;
+}
diff --git a/free.c b/free.c
@@ -0,0 +1,112 @@
+#include <libc.h>
+
+#define buf_size 2048
+
+static int str_starts_with(const char *str, const char *prefix) {
+ while (*prefix) {
+ if (*str++ != *prefix++) return 0;
+ }
+ return 1;
+}
+
+static unsigned long parse_key(const char *buf, const char *key) {
+ int key_len = strlen(key);
+ for (int i = 0; buf[i] != '\0'; i++) {
+ if (str_starts_with(&buf[i], key)) {
+ i += key_len;
+ while (buf[i] == ' ' || buf[i] == '\t') i++;
+
+ unsigned long val = 0;
+ while (buf[i] >= '0' && buf[i] <= '9') {
+ val = val * 10 + (buf[i] - '0');
+ i++;
+ }
+ return val;
+ }
+ }
+ return 0;
+}
+
+static void print_str(const char *s) {
+ write(stdout, s, strlen(s));
+}
+
+static void print_num_padded(unsigned long val, int width) {
+ char buf[32];
+ int pos = 0;
+
+ if (val == 0) {
+ buf[pos++] = '0';
+ } else {
+ char temp[32];
+ int tpos = 0;
+ while (val > 0) {
+ temp[tpos++] = '0' + (val % 10);
+ val /= 10;
+ }
+ while (tpos > 0) {
+ buf[pos++] = temp[--tpos];
+ }
+ }
+ buf[pos] = '\0';
+
+ int spaces = width - pos;
+ while (spaces-- > 0) {
+ write(stdout, " ", 1);
+ }
+ write(stdout, buf, pos);
+}
+
+int main(void) {
+ int fd = open("/proc/meminfo", o_rdonly, 0);
+ if (fd < 0) {
+ write(stderr, "free: cannot open /proc/meminfo\n", 32);
+ return 1;
+ }
+
+ char buf[buf_size];
+ ssize_t n = read(fd, buf, sizeof(buf) - 1);
+ close(fd);
+
+ if (n <= 0) {
+ write(stderr, "free: failed to read /proc/meminfo\n", 35);
+ return 1;
+ }
+ buf[n] = '\0';
+
+ unsigned long mem_total = parse_key(buf, "MemTotal:");
+ unsigned long mem_free = parse_key(buf, "MemFree:");
+ unsigned long mem_avail = parse_key(buf, "MemAvailable:");
+ unsigned long buffers = parse_key(buf, "Buffers:");
+ unsigned long cached = parse_key(buf, "Cached:");
+ unsigned long swap_total = parse_key(buf, "SwapTotal:");
+ unsigned long swap_free = parse_key(buf, "SwapFree:");
+
+ unsigned long buff_cache = buffers + cached;
+
+ unsigned long mem_used = 0;
+ if (mem_total > (mem_free + buff_cache)) {
+ mem_used = mem_total - mem_free - buff_cache;
+ }
+
+ unsigned long swap_used = (swap_total > swap_free) ? (swap_total - swap_free) : 0;
+
+ print_str(" total used free shared buff/cache available\n");
+
+ print_str("Mem: ");
+ print_num_padded(mem_total, 12);
+ print_num_padded(mem_used, 12);
+ print_num_padded(mem_free, 12);
+ print_num_padded(0, 12); /* shared */
+ print_num_padded(buff_cache, 12);
+ print_num_padded(mem_avail, 12);
+ print_str("\n");
+
+ print_str("Swap: ");
+ print_num_padded(swap_total, 12);
+ print_num_padded(swap_used, 12);
+ print_num_padded(swap_free, 12);
+ print_str("\n");
+
+ return 0;
+}
diff --git a/init.c b/init.c
@@ -0,0 +1,40 @@
+#include <libc.h>
+
+#define msg_clear "\033[2J\033[H"
+
+#define msg_welcome "[init] starting...\n"
+#define msg_proc "[init] mouting /proc...\n"
+#define msg_sys "[init] mouting /sys...\n"
+#define msg_dev "[init] mouting /dev...\n"
+
+int main(void) {
+ write(stdout, msg_clear, strlen(msg_clear));
+
+ write(stdout, msg_welcome, strlen(msg_welcome));
+
+ write(stdout, msg_proc, strlen(msg_proc));
+ mount("proc", "/proc", "proc", 0, NULL);
+
+ write(stdout, msg_sys, strlen(msg_sys));
+ mount("sysfs", "/sys", "sysfs", 0, NULL);
+
+ write(stdout, msg_dev, strlen(msg_dev));
+ mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);
+
+ int pid = fork();
+ if (pid == 0) {
+ char *argv[] = { "/bin/sh", NULL };
+ char *envp[] = { "PATH=/bin:/sbin", NULL };
+
+ execve("/bin/sh", argv, envp);
+
+ write(stderr, "[init] Failed to exec /bin/sh!\n", 31);
+ exit(1);
+ }
+
+ while (1) {
+ int status;
+ waitpid(-1, &status, 0);
+ }
+ return 0;
+}
diff --git a/ls.c b/ls.c
@@ -0,0 +1,31 @@
+#include <libc.h>
+
+int main(int argc, char *argv[]) {
+ const char *path = (argc > 1) ? argv[1] : ".";
+
+ int fd = open(path, o_rdonly | o_directory, 0);
+ if (fd < 0) {
+ write(stderr, "ls: cannot open directory\n", 26);
+ return 1;
+ }
+
+ char buf[1024];
+ int nread;
+
+ while ((nread = getdents64(fd, (struct linux_dirent64 *)buf, sizeof(buf))) > 0) {
+ int bpos = 0;
+ while (bpos < nread) {
+ struct linux_dirent64 *d = (struct linux_dirent64 *)(buf + bpos);
+
+ if (d->d_name[0] != '.') {
+ write(stdout, d->d_name, strlen(d->d_name));
+ write(stdout, "\n", 1);
+ }
+
+ bpos += d->d_reclen;
+ }
+ }
+
+ close(fd);
+ return 0;
+}
diff --git a/mkfile b/mkfile
@@ -0,0 +1,18 @@
+<$LPLAN9/src/mkhdr
+
+cc = ./cc
+ld = ld
+cflags = -I./libc
+lib = libc/libc.a
+
+targ = init \
+ echo \
+ cat \
+ pwd \
+ ls \
+ free \
+
+dirs = sh \
+
+<$LPLAN9/src/mkmany
+<$LPLAN9/src/mkdirs
diff --git a/pwd.c b/pwd.c
@@ -0,0 +1,11 @@
+#include <libc.h>
+
+int main(void) {
+ char buf[1024];
+ if (getcwd(buf, sizeof(buf))) {
+ write(1, buf, strlen(buf));
+ write(1, "\n", 1);
+ return 0;
+ }
+ return 1;
+}
diff --git a/sh/main.c b/sh/main.c
@@ -0,0 +1,70 @@
+#include <libc.h>
+
+#define msg_clear "\033[2J\033[H"
+
+#define max_line 256
+#define max_args 16
+#define max_cwd 256
+
+static char prompt[] = "; ";
+
+void execcd(const char *path) {
+ chdir(path);
+}
+
+int main(void) {
+ char line[max_line];
+ char *argv[max_args];
+
+ while (1) {
+ write(stdout, prompt, 2);
+
+ ssize_t n = read(stdin, line, max_line - 1);
+ if (n <= 0) continue;
+
+ line[n] = '\0';
+ if (line[n - 1] == '\n') line[n - 1] = '\0';
+
+ if (strlen(line) == 0) continue;
+
+ if (strcmp(line, "clear") == 0) {
+ write(stdout, msg_clear, strlen(msg_clear));
+ continue;
+ }
+
+ if (strcmp(line, "exit") == 0) {
+ break;
+ }
+
+ int argc = 0;
+ char *token = strtok(line, " ");
+ while (token != NULL && argc < max_args - 1) {
+ argv[argc++] = token;
+ token = strtok(NULL, " ");
+ }
+ argv[argc] = NULL;
+
+ if (argc == 0) continue;
+
+ if (strcmp(line, "cd") == 0) {
+ execcd(argv[1]);
+ continue;
+ }
+
+ int pid = fork();
+ if (pid == 0) {
+ /* child */
+ execvp(argv[0], argv);
+
+ write(stderr, "sh: command not found: ", 23);
+ write(stderr, argv[0], strlen(argv[0]));
+ write(stderr, "\n", 1);
+ exit(127);
+ } else if (pid > 0) {
+ /* parent */
+ int status;
+ waitpid(pid, &status, 0);
+ }
+ }
+ return 0;
+}
diff --git a/sh/mkfile b/sh/mkfile
@@ -0,0 +1,12 @@
+<$LPLAN9/src/mkhdr
+
+cc = ../cc
+ld = ld
+cflags = -I../libc
+lib = ../libc/libc.a
+
+ofiles = main.$o \
+
+targ = sh
+
+<$LPLAN9/src/mkone