aboutsummaryrefslogtreecommitdiffstats
path: root/usr/mv.c
diff options
context:
space:
mode:
authoruser <user@clank>2026-09-24 12:48:51 +0200
committeruser <user@clank>2026-09-24 12:48:51 +0200
commit65b53de14dc6918db39b6ee6dc032f805182daad (patch)
tree6af7b52262321a3cbe11e1d472ca2938df2fc37e /usr/mv.c
parentsh: run scripts, and >> redirection (diff)
downloadgbos-65b53de14dc6918db39b6ee6dc032f805182daad.tar.gz
gbos-65b53de14dc6918db39b6ee6dc032f805182daad.tar.xz
gbos-65b53de14dc6918db39b6ee6dc032f805182daad.zip
usr: ls -l, df, mv, tail, tee, sleep, help, poweroff
Filling in the core utilities the box was missing: - ls -l: type, links and size, now that stat() exists. The screen is 40 columns, so it is "d 1 256 name", not the GNU sprawl. Sizes were previously unknowable except one file at a time with wc -c. - df: blocks and inodes, used and free, on the 32 KiB cart disk. - mv: no rename syscall, so it is cp + rm - and the copy has to finish before the source goes, or a failure loses the file. - tail [-n N]: no seek syscall, so it streams the input through a ring of N lines rather than jumping to the end. N is capped by that ring. - tee: the missing half of a pipeline - `cat big | tee copy | wc -l`. - sleep: the thing every script needs; the kernel counts 1/64 s ticks. - help: lists every command the shell knows, walked out of the kernel's own name table. The box previously had no way to tell you what it could do. - poweroff: the only safe way to stop a gbos that has data on it. The cart's battery RAM is written when the emulator exits cleanly, so killing it loses the whole filesystem - it comes back "formatted". Found while testing /rc.
Diffstat (limited to '')
-rw-r--r--usr/mv.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/usr/mv.c b/usr/mv.c
new file mode 100644
index 0000000..76d9e62
--- /dev/null
+++ b/usr/mv.c
@@ -0,0 +1,51 @@
+#include "gbos.h"
+/* mv SRC DST: there is no rename syscall, so this is cp + rm. The copy has to
+ * succeed before the source is removed - a half-copied DST plus a deleted SRC
+ * loses the file. */
+
+static unsigned char streq(const char *a, const char *b) {
+ while (*a && *a == *b) {
+ a++;
+ b++;
+ }
+ return (unsigned char)(*a == *b);
+}
+
+void main(void) {
+ char *argv[4];
+ unsigned char argc = argv_parse(argv, 4);
+ unsigned char in, out;
+ int ch;
+
+ if (argc < 2) {
+ puts("usage: mv SRC DST");
+ nl();
+ sexit(2);
+ }
+ if (streq(argv[0], argv[1])) sexit(0); /* nothing to do */
+
+ in = open(argv[0], O_READ);
+ if (in == EISDIR) {
+ puts("mv: SRC is a directory");
+ nl();
+ sexit(2);
+ }
+ if (in == NOFD) {
+ puts("mv: no such file: ");
+ puts(argv[0]);
+ nl();
+ sexit(2);
+ }
+ out = open(argv[1], O_WRITE);
+ if (out > 3) {
+ puts("mv: cannot create ");
+ puts(argv[1]);
+ nl();
+ close(in);
+ sexit(2);
+ }
+ while ((ch = fgetc(in)) >= 0) fputc(out, (char)ch);
+ close(in);
+ close(out);
+ fremove(argv[0]); /* only now is it safe */
+}