coreutils

custom mini coreutils
git clone git@git.evenfri.pw:coreutils.git
Log | Files | Refs | README

commit 9d44184892f36ff0ccb45f417d4f321955247f65
Author: evenfri <evenfri256@gmail.com>
Date:   Mon, 27 Jul 2026 17:39:44 +0800

initial commit

Diffstat:
A.gitignore | 4++++
AREADME | 17+++++++++++++++++
Acat.c | 30++++++++++++++++++++++++++++++
Acc | 11+++++++++++
Aecho.c | 12++++++++++++
Afree.c | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainit.c | 40++++++++++++++++++++++++++++++++++++++++
Als.c | 31+++++++++++++++++++++++++++++++
Amkfile | 18++++++++++++++++++
Apwd.c | 11+++++++++++
Ash/main.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ash/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