From 6c64d97e70984c77be3cd8d4e03e9adf717e02fb Mon Sep 17 00:00:00 2001 From: user Date: Thu, 16 Jul 2026 08:25:35 +0200 Subject: shell: I/O redirection (>/<) and pipes (|); rewrite shell in C - kernel I/O routing: PCB gains PROC_STDIN/PROC_STDOUT (default console $FF), inherited across fork. KGetc/KPutc route read/write/putc to the console or a file fd. New syscalls: putc(16), setin(17), setout(18), lookup(19). read/write now go through the routing; putc/puts/nl use SYS_PUTC. - sys_lookup + NameTable move command-name resolution into the kernel. - shell rewritten in C (c/sh.c): tokenizes a line, parses > / < / |, and drives fork+setin/setout+exec+wait. Pipes run as 'a > __pipe ; b < __pipe' (temp file). asm shell + cmdtab removed; StrEqual/SkipName kept for sys_lookup. - libc: fork/exec/wait/setin/setout/lookup wrappers. - verified: echo>file, cat file, wc read a line (with echo) -> match a command -> fork+exec+wait. +; PROG_SH (bank 3) - the shell, now written in C (c/sh.c): parses >/ system idle - rst $30 - -.eol - ld [hl], 0 ; NUL-terminate - ld de, .crlf - ld b, 2 - ld c, SYS_WRITE - rst $30 - ld a, [SH_LINEBUF] - or a - jp z, .prompt ; empty line - - ; split off the first word: replace the first space with a NUL so command - ; matching sees just the command, and the args survive at SH_LINEBUF+n - ; (inherited by the child through fork, read back via main(char *args)). - ld hl, SH_LINEBUF -.split - ld a, [hl] - or a - jr z, .lookup ; no space -> no args - cp $20 - jr z, .cut - inc hl - jr .split -.cut - ld [hl], 0 ; isolate the command word - -.lookup - ; look the command up in the table - ld de, .cmdtab -.scan - ld a, [de] - or a - jr z, .unknown ; empty name = end of table - push de - ld hl, SH_LINEBUF - call StrEqual ; Z set if equal - pop de - jr z, .match - call SkipName ; DE -> NUL after this name - inc de ; -> program id - inc de ; -> next entry - jr .scan - -.match - call SkipName - inc de ; DE -> program id - ld a, [de] - ld [SH_PROGID], a - ld c, SYS_FORK - rst $30 - or a - jr z, .exec - ld c, SYS_WAIT ; parent: reap the command - rst $30 - jp .prompt -.exec - ld a, [SH_PROGID] - ld b, a - ld c, SYS_EXEC - rst $30 ; child becomes the command - -.unknown - ld de, .huh - ld b, 3 - ld c, SYS_WRITE - rst $30 - jp .prompt - -.ps1 - db "$ " -.crlf - db $0D, $0A -.huh - db "?", $0D, $0A -.cmdtab - db "worker", 0 - db PROG_WORKER - db "hello", 0 - db PROG_HELLO - db "chello", 0 - db PROG_CHELLO - db "echo", 0 - db PROG_ECHO - db "true", 0 - db PROG_TRUE - db "false", 0 - db PROG_FALSE - db "uname", 0 - db PROG_UNAME - db "pid", 0 - db PROG_PID - db "cat", 0 - db PROG_CAT - db "wc", 0 - db PROG_WC - db "head", 0 - db PROG_HEAD - db "args", 0 - db PROG_ARGS - db "ls", 0 - db PROG_LS - db "save", 0 - db PROG_SAVE - db "rm", 0 - db PROG_RM - db 0 ; terminator + INCBIN "c/sh.bin" ; ----------------------------------------------------------------------------- ; Shell string helpers (ROM0, always mapped). @@ -298,3 +162,40 @@ ProgramTable:: dw ProgSave db LOW(BANK(ProgRm)), HIGH(BANK(ProgRm)) dw ProgRm + +; ----------------------------------------------------------------------------- +; NameTable (ROM0) - command name -> program id, searched by sys_lookup. +; ----------------------------------------------------------------------------- +SECTION "nametab", ROM0 +NameTable:: + db "worker", 0 + db PROG_WORKER + db "hello", 0 + db PROG_HELLO + db "chello", 0 + db PROG_CHELLO + db "echo", 0 + db PROG_ECHO + db "true", 0 + db PROG_TRUE + db "false", 0 + db PROG_FALSE + db "uname", 0 + db PROG_UNAME + db "pid", 0 + db PROG_PID + db "cat", 0 + db PROG_CAT + db "wc", 0 + db PROG_WC + db "head", 0 + db PROG_HEAD + db "args", 0 + db PROG_ARGS + db "ls", 0 + db PROG_LS + db "save", 0 + db PROG_SAVE + db "rm", 0 + db PROG_RM + db 0 -- cgit v1.3.1-sl0p