commit 7158f14634b5d398161e7ec21cbc89364a33f557
parent 88ed74024c05650adefa7cef20a66ae775ee3348
Author: erai <erai@omiltem.net>
Date: Sun, 26 May 2024 11:22:36 -0400
basic commands
Diffstat:
M | as.c | | | 2 | +- |
M | bootstrap.sh | | | 65 | ++++++++++++++++++++++++++++++----------------------------------- |
M | bufio.c | | | 39 | +++++++++++++++++++++++++++++++++++++++ |
M | cmp.c | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | cpio.c | | | 211 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | echo.c | | | 16 | ++++++++++++++++ |
A | init | | | 2 | ++ |
M | ls.c | | | 39 | +++++++++++++++++++++++++++++++++++++++ |
M | pxe.sh | | | 18 | +++++------------- |
M | rm.c | | | 11 | +++++++++++ |
M | sshd.c | | | 1 | - |
M | syscall.c | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | watch.sh | | | 10 | ++++------ |
13 files changed, 473 insertions(+), 56 deletions(-)
diff --git a/as.c b/as.c
@@ -195,7 +195,7 @@ open_output(c: *assembler, filename: *byte) {
unlink(filename);
- fd = open(filename, 64 + 1, (7 << 6) + (7 << 3) +7);
+ fd = open(filename, O_CREAT | O_WRONLY, (7 << 6) + (7 << 3) +7);
if (fd < 0) {
die("failed to open output");
}
diff --git a/bootstrap.sh b/bootstrap.sh
@@ -1,45 +1,40 @@
-#!/bin/bash
-
-set -ue
+#!/bin/sh
LIBS="bufio.c lib.c alloc.c syscall.c"
-SOURCES="cc1.c type.c parse1.c lex1.c as.c ${LIBS}"
-GENLEX_SOURCES="genlex.c ${LIBS}"
+SOURCES="cc1.c type.c parse1.c lex1.c as.c $LIBS"
+GENLEX_SOURCES="genlex.c $LIBS"
-if [ -e cc1 ]; then
- ./cc1 ${SOURCES} -o cc0
-else
- gcc -Wall -Wextra -Wno-unused -pedantic -std=c99 ./cc0.c -o cc0 || { rm -f cc0; echo bootstrap failed; exit 1; }
-fi
+./cc1 $SOURCES -o cc0 || gcc -Wall -Wextra -Wno-unused -pedantic -std=c99 ./cc0.c -o cc0 || exit 1
-./cc0 ${SOURCES} -o cc1 || { rm -f cc1; echo cc0 failed; exit 1; }
+./cc0 $SOURCES -o cc1 || exit 1
-./cc1 ${SOURCES} -o cc2 || { rm -f cc2; echo cc1 failed; exit 1; }
+./cc1 ${SOURCES} -o cc2 || exit 1
-cmp cc1 cc2 || { echo output mismatch; exit 1; }
+cmp cc1 cc2 || echo mismatch
-./cc1 ${GENLEX_SOURCES} -o genlex || { rm -f genlex; echo cc1 failed; exit 1; }
-./genlex < cc3.l > lex3.c || { rm -f lex3.c; echo genlex failed; exit 1; }
+./cc1 ${GENLEX_SOURCES} -o genlex || exit 1
+./genlex < cc3.l > lex3.c || exit 1
-./cc1 ${LIBS} echo.c -o echo || { rm -f echo; echo echo failed; exit 1; }
-./cc1 ${LIBS} cmp.c -o cmp || { rm -f cmp; echo cmp failed; exit 1; }
-./cc1 ${LIBS} rm.c -o rm || { rm -f rm; echo rm failed; exit 1; }
-./cc1 ${LIBS} ls.c -o ls || { rm -f ls; echo ls failed; exit 1; }
-./cc1 ${LIBS} cpio.c -o cpio || { rm -f cpio; echo cpio failed; exit 1; }
-./cc1 ${LIBS} sh.c -o sh || { rm -f sh; echo sh failed; exit 1; }
-./cc1 ${LIBS} sshd.c -o sshd || { rm -f sshd; echo sshd failed; exit 1; }
-./cc1 ${LIBS} vi.c -o vi || { rm -f vi; echo vi failed; exit 1; }
+./cc1 ${LIBS} echo.c -o echo || exit 1
+./cc1 ${LIBS} cmp.c -o cmp || exit 1
+./cc1 ${LIBS} rm.c -o rm || exit 1
+./cc1 ${LIBS} ls.c -o ls || exit 1
+./cc1 ${LIBS} cpio.c -o cpio || exit 1
+./cc1 ${LIBS} sh.c -o sh || exit 1
+./cc1 ${LIBS} sshd.c -o sshd || exit 1
+./cc1 ${LIBS} vi.c -o vi || exit 1
{
- echo echo
- echo cmp
- echo rm
- echo ls
- echo cpio
- echo sh
- echo sshd
- echo vi
- echo cc1
-} | ./cpio > initramfs || { rm -f initramfs; echo initramfs failed; exit 1; }
-
-./cc1 kernel.c -o kernel
+ ./echo echo
+ ./echo cmp
+ ./echo rm
+ ./echo ls
+ ./echo cpio
+ ./echo sh
+ ./echo vi
+ ./echo sshd
+ ./echo init
+ ./echo cc1
+} | ./cpio -o > initramfs || exit 1
+
+./cc1 kernel.c -o kernel || exit 1
diff --git a/bufio.c b/bufio.c
@@ -114,3 +114,42 @@ fgetc(f: *file): int {
return ch;
}
+
+fgets(f: *file, buf: *byte, len: int): int {
+ var i: int;
+ var c: int;
+
+ if len == 1 {
+ buf[0] = 0:byte;
+ return 0;
+ }
+
+ i = 0;
+ loop {
+ if i + 1 == len {
+ buf[i] = 0:byte;
+ return i;
+ }
+
+ c = fgetc(f);
+ if c == -1 || c == '\n' {
+ buf[i] = 0:byte;
+ return i;
+ }
+
+ buf[i] = c:byte;
+ i = i + 1;
+ }
+}
+
+fputs(f: *file, s: *byte) {
+ var i: int;
+ i = 0;
+ loop {
+ if !s[i] {
+ break;
+ }
+ fputc(f, s[i]:int);
+ i = i + 1;
+ }
+}
diff --git a/cmp.c b/cmp.c
@@ -1,2 +1,56 @@
main(argc: int, argv: **byte, envp: **byte) {
+ var a: int;
+ var b: int;
+ var alloc: alloc;
+ var fa: *file;
+ var fb: *file;
+ var c: int;
+ var i: int;
+
+ setup_alloc(&alloc);
+
+ if argc != 3 {
+ die("usage: cmp file1 file2");
+ }
+
+ a = open(argv[1], 0, 0);
+ if a < 0 {
+ fdputs(1, "failed to open: ");
+ fdputs(1, argv[1]);
+ fdputs(1, "\n");
+ exit(2);
+ }
+
+ b = open(argv[2], 0, 0);
+ if b < 0 {
+ fdputs(1, "failed to open: ");
+ fdputs(1, argv[2]);
+ fdputs(1, "\n");
+ exit(2);
+ }
+
+ fa = fopen(a, &alloc);
+ fb = fopen(b, &alloc);
+
+ i = 0;
+ loop {
+ c = fgetc(fa);
+
+ if c != fgetc(fb) {
+ fdputs(1, argv[1]);
+ fdputc(1, ' ');
+ fdputs(1, argv[2]);
+ fdputc(1, ' ');
+ fdputs(1, "differ: byte ");
+ fdputd(1, i);
+ fdputc(1, '\n');
+ exit(1);
+ }
+
+ if c == -1 {
+ break;
+ }
+
+ i = i + 1;
+ }
}
diff --git a/cpio.c b/cpio.c
@@ -1,2 +1,213 @@
+struct stat {
+ dev: int;
+ ino: int;
+ nlink: int;
+ uid_mode: int;
+ gid: int;
+ rdev: int;
+ size: int;
+ blksize: int;
+ blocks: int;
+ atime: int;
+ atime_nsec: int;
+ mtime: int;
+ mtime_nsec: int;
+ ctime: int;
+ ctime_nsec: int;
+ pad0: int;
+ pad1: int;
+ pad2: int;
+}
+
main(argc: int, argv: **byte, envp: **byte) {
+ var opts: int;
+ var i: int;
+ var a: alloc;
+ var fd: int;
+ var name: *byte;
+ var stdin: *file;
+ var stdout: *file;
+ var stat: stat;
+ var buf: *byte;
+ var len: int;
+ var n: int;
+ var m: int;
+ var k: int;
+ var ret: int;
+
+ setup_alloc(&a);
+
+ i = 1;
+ loop {
+ if i >= argc {
+ break;
+ }
+
+ if !strcmp(argv[i], "-o") {
+ opts = opts | 1;
+ } else {
+ die("invalid argument");
+ }
+
+ i = i + 1;
+ }
+
+ stdin = fopen(0, &a);
+ stdout = fopen(1, &a);
+
+ name = alloc(&a, 4096);
+ buf = alloc(&a, 4096);
+
+ loop {
+ if stdin.eof {
+ break;
+ }
+
+ len = fgets(stdin, name, 4096);
+ if len == 0 {
+ continue;
+ }
+
+ if len == 4096 {
+ fflush(stdout);
+ fdputs(2, "name truncated: ");
+ fdputs(2, name);
+ fdputs(2, "\n");
+ exit(1);
+ }
+
+ fd = open(name, 0, 0);
+ if fd < 0 {
+ fflush(stdout);
+ fdputs(2, "failed to open: ");
+ fdputs(2, name);
+ fdputs(2, "\n");
+ exit(1);
+ }
+
+ if fstat(fd, (&stat):*byte) < 0 {
+ fflush(stdout);
+ fdputs(2, "stat failed: ");
+ fdputs(2, name);
+ fdputs(2, "\n");
+ exit(1);
+ }
+
+ // header
+ fputs(stdout, "070701");
+ fputh(stdout, stat.ino);
+ fputh(stdout, stat.uid_mode & (-1 >> 32));
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, stat.nlink);
+ fputh(stdout, stat.mtime);
+ fputh(stdout, stat.size);
+ fputh(stdout, stat.dev >> 8);
+ fputh(stdout, stat.dev & 255);
+ fputh(stdout, stat.rdev >> 8);
+ fputh(stdout, (stat.rdev) & 255);
+ fputh(stdout, len + 1);
+ fputh(stdout, 0);
+
+ fputs(stdout, name);
+ fputc(stdout, 0);
+
+ // align to four bytes
+ falign(stdout, len + 3);
+ fflush(stdout);
+
+ // copy data
+ n = 0;
+ loop {
+ if n == stat.size {
+ break;
+ }
+
+ k = read(fd, buf, 4096);
+ if k <= 0 {
+ die("failed to read");
+ }
+
+ if n + k > stat.size {
+ k = stat.size - n;
+ }
+
+ m = 0;
+ loop {
+ if m == k {
+ break;
+ }
+
+ ret = write(1, &buf[m], k - m);
+ if ret < 0 {
+ die("failed to write");
+ }
+
+ m = m + ret;
+ }
+
+ n = n + k;
+ }
+
+ // align to four bytes
+ falign(stdout, stat.size);
+ fflush(stdout);
+
+ close(fd);
+ }
+
+ // trailer
+ fputs(stdout, "070701");
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 0);
+ fputh(stdout, 11);
+ fputh(stdout, 0);
+ fputs(stdout, "TRAILER!!!");
+ fputc(stdout, 0);
+ falign(stdout, 13);
+
+ fflush(stdout);
+}
+
+fputh(f: *file, x: int) {
+ var i: int;
+
+ if x > (-1 >> 32) {
+ fflush(f);
+ die("too large");
+ }
+
+ i = 32;
+ loop {
+ if i == 0 {
+ break;
+ }
+
+ i = i - 4;
+
+ fputc(f, "0123456789abcdef"[(x >> i) & 15]:int);
+ }
+}
+
+falign(f: *file, n: int) {
+ var len: int;
+ len = (4 - (n & 3)) & 3;
+ loop {
+ if len == 0 {
+ break;
+ }
+
+ fputc(f, 0);
+
+ len = len - 1;
+ }
}
diff --git a/echo.c b/echo.c
@@ -1,2 +1,18 @@
main(argc: int, argv: **byte, envp: **byte) {
+ var i: int;
+ i = 1;
+ loop {
+ if i >= argc {
+ fdputc(1, '\n');
+ return;
+ }
+
+ fdputs(1, argv[i]);
+
+ i = i + 1;
+
+ if i < argc {
+ fdputc(1, ' ');
+ }
+ }
}
diff --git a/init b/init
@@ -0,0 +1,2 @@
+#!/sh
+/sshd
diff --git a/ls.c b/ls.c
@@ -1,2 +1,41 @@
main(argc: int, argv: **byte, envp: **byte) {
+ var fd: int;
+ var i: int;
+ var n: int;
+ var len: int;
+ var a: alloc;
+ var buf: *byte;
+
+ setup_alloc(&a);
+
+ fd = open(".", O_DIRECTORY, 0);
+ if fd < 0 {
+ exit(1);
+ }
+
+ buf = alloc(&a, 4096);
+
+ loop {
+ n = getdirents(fd, buf, 4096);
+ if n == 0 {
+ break;
+ }
+
+ if n < 0 {
+ die("getdirents failed");
+ }
+
+ loop {
+ if i + 20 >= n {
+ break;
+ }
+
+ fdputs(1, &buf[i + 19]);
+ fdputc(1, ' ');
+
+ i = i + ((&buf[i + 16]):*int[0] & 0xffff);
+ }
+ }
+
+ fdputc(1, '\n');
}
diff --git a/pxe.sh b/pxe.sh
@@ -1,13 +1,5 @@
-#!/bin/bash
-
-set -ue
-
-exec 3<>/dev/ttyACM0
-
-./bootstrap.sh
-
-nasm -f bin pxe.asm
-
-cp kernel pxe /srv/tftp/
-
-printf r >&3
+#!/bin/sh
+./bootstrap.sh || exit 1
+nasm -f bin pxe.asm || exit 1
+cp kernel pxe /srv/tftp/ || exit 1
+printf r > /dev/ttyACM0 || exit 1
diff --git a/rm.c b/rm.c
@@ -1,2 +1,13 @@
main(argc: int, argv: **byte, envp: **byte) {
+ var i: int;
+ i = 1;
+ loop {
+ if i >= argc {
+ return;
+ }
+
+ unlink(argv[i]);
+
+ i = i + 1;
+ }
}
diff --git a/sshd.c b/sshd.c
@@ -98,7 +98,6 @@
//<-
//SSH_MSG_USERAUTH_PK_OK
-
_rdrand(): int;
main(argc: int, argv: **byte, envp: **byte) {
exit(_rdrand());
diff --git a/syscall.c b/syscall.c
@@ -1,5 +1,15 @@
syscall(n: int, a1: int, a2: int, a3: int, a4: int, a5: int, a6: int): int;
+enum {
+ O_RDONLY = 0,
+ O_WRONLY = 1,
+ O_RDWR = 2,
+ O_CREAT = 64,
+ O_TRUNC = 0x200,
+ O_APPEND = 0x400,
+ O_DIRECTORY = 0x1000,
+}
+
_start(argc: int, argv: **byte, envp: **byte) {
main(argc, argv, envp);
exit(0);
@@ -21,14 +31,65 @@ close(fd: int): int {
return syscall(3, fd, 0, 0, 0, 0, 0);
}
+fstat(fd: int, buf: *byte): int {
+ return syscall(5, fd, buf:int, 0, 0, 0, 0);
+}
+
mmap(addr: int, len: int, prot: int, flags: int, fd: int, off: int): int {
return syscall(9, addr, len, prot, flags, fd, off);
}
+pipe(fd: *int): int {
+ var buf: int;
+ var ret: int;
+ ret = syscall(22, (&buf):int, 0, 0, 0, 0, 0);
+ if ret == 0 {
+ fd[0] = buf & (-1 >> 32);
+ fd[1] = buf >> 32;
+ }
+ return ret;
+}
+
+dup2(old: int, new: int): int {
+ return syscall(33, old, new, 0, 0, 0, 0);
+}
+
+socket(pf: int, ty: int, pc: int): int {
+ return syscall(41, pf, ty, pc, 0, 0, 0);
+}
+
+accept(fd: int): int {
+ return syscall(43, fd, 0, 0, 0, 0, 0);
+}
+
+bind(fd: int, addr: *byte, len: int): int {
+ return syscall(49, fd, addr:int, len:int, 0, 0, 0);
+}
+
+listen(fd: int, backlog: int): int {
+ return syscall(50, fd, backlog, 0, 0, 0, 0);
+}
+
+fork(): int {
+ return syscall(57, 0, 0, 0, 0, 0, 0);
+}
+
+exec(cmd: *byte, argv: **byte, envp: **byte): int {
+ return syscall(59, cmd:int, argv:int, envp:int, 0, 0, 0);
+}
+
exit(n: int) {
syscall(60, n, 0, 0, 0, 0, 0);
}
+wait(pid: int, status: *int, flags: int): int {
+ return syscall(61, pid, status:int, flags, 0, 0, 0);
+}
+
unlink(name: *byte): int {
return syscall(87, name: int, 0, 0, 0, 0, 0);
}
+
+getdirents(fd: int, buf: *byte, len: int): int {
+ return syscall(217, fd, buf:int, len, 0, 0, 0);
+}
diff --git a/watch.sh b/watch.sh
@@ -1,8 +1,6 @@
-#!/bin/bash
+#!/bin/sh
clear
-cmd="${1:-./pxe.sh}"
-shift
-"${cmd}" "$@"
-date
+./pxe.sh
+echo status $?
: < ~/.post
-exec "$0" "$@"
+exec "$0"