diff options
| author | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-12 06:24:08 +0300 |
|---|---|---|
| committer | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-12 06:24:08 +0300 |
| commit | 06c7845f0247e77ed861b85b6c48556f6b6b120d (patch) | |
| tree | 6e9eac0970f97bdae439925772f51f232af5e30f /sh9.b | |
| parent | a40ef1434889babbd88c9d0c5913c70e96ac2774 (diff) | |
Reorganize files according to proper directory structure
Diffstat (limited to 'sh9.b')
| -rw-r--r-- | sh9.b | 857 |
1 files changed, 0 insertions, 857 deletions
@@ -1,857 +0,0 @@ -implement Sh9; - -include "sys.m"; - sys: Sys; - FD: import Sys; - -include "draw.m"; - Context: import Draw; - -include "filepat.m"; - filepat: Filepat; - nofilepat := 0; # true if load Filepat has failed. - -include "bufio.m"; - bufio: Bufio; - Iobuf: import bufio; - -include "env.m"; - env: Env; - -include "hash.m"; - hash: Hash; - HashTable: import hash; - HashVal: import hash; - -include "workdir.m"; - -stdin: ref FD; -stderr: ref FD; -waitfd: ref FD; - -Quoted: con '\uFFF0'; -stringQuoted: con "\uFFF0"; - -Sh9: module -{ - init: fn(ctxt: ref Context, argv: list of string); -}; - -Command: adt -{ - args: list of string; - inf, outf: string; - append: int; -}; - -Async, Seq: con iota; - -Pipeline: adt -{ - cmds: list of ref Command; - term: int; -}; - -usage() -{ - sys->fprint(stderr, "Usage: sh9 [-n] [-c cmd] [file]\n"); -} - -clean_n_chars_seek(sys: Sys, n: int, seek: int) { - for (i:=0; i<(n-seek); i++) { - sys->print("\b"); - } - for (i=0; i<n; i++) { - sys->print(" "); - } - for (i=0; i<n; i++) { - sys->print("\b"); - } -} - -clean_n_chars(sys: Sys, n: int) { - clean_n_chars_seek(sys, n, 0); -} - -init(ctxt: ref Context, argv: list of string) -{ - sys = load Sys Sys->PATH; - env = load Env Env->PATH; - bufio = load Bufio Bufio->PATH; - hash = load Hash Hash->PATH; - - n: int; - arg: list of string; - buf := array[1024] of byte; - - stderr = sys->fildes(2); - - waitfd = sys->open("#p/"+string sys->pctl(0, nil)+"/wait", sys->OREAD); - if(waitfd == nil){ - sys->fprint(stderr, "sh9: open wait: %r\n"); - return; - } - - eflag := nflag := lflag := 0; - cmd: string; - if(argv != nil) { - argv = tl argv; - } - for(; argv != nil && len hd argv && (hd argv)[0]=='-'; argv = tl argv) { - case hd argv { - "-e" => - eflag = 1; - "-n" => - nflag = 1; - "-l" => - lflag = 1; - "-c" => - argv = tl argv; - if(len argv != 1){ - usage(); - return; - } - cmd = hd argv; - * => - usage(); - return; - } - } - - if (lflag) - startup(ctxt); - - if(eflag == 0) - sys->pctl(sys->FORKENV, nil); - if(nflag == 0) - sys->pctl(sys->FORKNS, nil); - if(cmd != nil){ - arg = tokenize(cmd+"\n"); - if(arg != nil) - runit(ctxt, parseit(arg)); - return; - } - if(argv != nil){ - script(ctxt, hd argv); - return; - } - - cctlfd := sys->open("/dev/consctl", sys->OWRITE); - if(cctlfd == nil) - return; - sys->write(cctlfd, array of byte "rawon", 5); - - dfd := sys->open("/dev/cons", sys->OREAD); - if(dfd == nil) - return; - - #stdin = sys->fildes(0); - - prompt := getusername() + "@" + sysname() + ":" + getcwd() + "; "; - offset : int = 0; - temp : int; - last_cmdline := array[1024] of int; - last_cmdline_length : int = 0; - - cmd1 := 0; - ST_NORMAL : con 0; - ST_WAITCMD1 : con 1; - ST_WAITCMD2 : con 2; - state := ST_NORMAL; - history_len := 1; - history_entry_cur := 0; -# history.entries = nil; -# history.entries = ("", "") :: nil; - history := hash->new(1024); - history.insert("0", (0,0.0,"")); - seek := 0; - - bio := bufio->fopen(dfd, sys->OREAD); - - sys->print("SH9 v0\n"); - sys->print("%s", prompt); - for(;;) { - temp = bio.getb(); - # check if escape - case state { - ST_NORMAL => - # check if escape - if (temp == 27) { - state = ST_WAITCMD1; # is escape - } else if (temp == '\t') { - # tab complete rq - sys->print("tab"); - } else if (temp == '\b') { - if (seek == 0) { - if (offset != 0) { - sys->print("\b"); - sys->print(" "); - sys->print("\b"); - offset --; - } - } else { - cur_buf := array[1024] of byte; - cur_buf[0:] = buf[0:offset]; - correction := 0; - for (i:=0;i<offset;i++) { - if ((offset-i-1) == seek) { - correction = 1; - } else { - buf[i-correction] = cur_buf[i]; - } - } - clean_n_chars_seek(sys, offset, seek); - offset --; - for (i=0;i<offset;i++) { - sys->print("%c", int(buf[i])); - } - for (i=0; i<seek; i++) { - sys->print("\b"); - } - } - } else { - buf[offset] = byte(temp); - offset ++; - if ((offset >= len buf) || (buf[offset-1] == byte('\n'))) { - history_entry_cur = 0; - seek = 0; - sys->print("\n"); - arg = tokenize(string buf[0:offset]); - if(arg != nil) { - runit(ctxt, parseit(arg)); - history.insert(sys->sprint("%d", history_len), (0,0.0,string buf[0:offset-1])); - history_len++; - } - offset = 0; - prompt = getusername() + "@" + sysname() + ":" + getcwd() + "; "; - sys->print("%s", prompt); - } else { - sys->print("%c",temp); - } - } - ST_WAITCMD1 => - if (temp == '[') { - state = ST_WAITCMD2; - cmd1 = temp; - } - ST_WAITCMD2 => - state = ST_NORMAL; - case cmd1 { - '[' => - case temp { - 65 => { #up press - seek = 0; - clean_n_chars(sys, offset); - - offset = 0; - he := history_len; - if (history_entry_cur < history_len) { - history_entry_cur ++; - he -= history_entry_cur; - } - cmdline := history.find(sys->sprint("%d", he)); - if (cmdline != nil) { - sys->print("%s", cmdline.s); - offset = len cmdline.s; - for (i:=0; i<len cmdline.s; i++) { - buf[i] = byte(cmdline.s[i]); - } - } - } - 66 => { # down key - seek = 0; - if (history_entry_cur > 0) { - history_entry_cur --; - clean_n_chars(sys, offset); - - offset = 0; - he := history_len; - he -= history_entry_cur; - cmdline := history.find(sys->sprint("%d", he)); - if (cmdline != nil) { - sys->print("%s", cmdline.s); - offset = len cmdline.s; - for (i:=0; i<len cmdline.s; i++) { - buf[i] = byte(cmdline.s[i]); - } - } - } - } - 68 => { # left key - if (seek > offset) { - seek = offset; - } else { - seek ++; - sys->print("\b"); - } - } - 67 => { # right key - clean_n_chars_seek(sys, offset, seek); - for (i:=0; i<offset; i++) { - sys->print("%c", int(buf[i])); - } - if (seek > 0) { - seek --; - } - for (i=0; i<seek; i++) { - sys->print("\b"); - } - } - 70 => { # end key - clean_n_chars_seek(sys, offset, seek); - seek = 0; - for (i:=0; i<offset; i++) { - sys->print("%c", int(buf[i])); - } - } - 72 => { # home key - seek = offset; - for (i:=0; i<seek; i++) { - sys->print("\b"); - } - } - * => { - sys->print("no action bind for %d\n", temp); - } - - } - } - } - } -} - -rev(arg: list of string): list of string -{ - ret: list of string; - - while(arg != nil){ - ret = hd arg :: ret; - arg = tl arg; - } - return ret; -} - -waitfor(pid: int) -{ - if(pid <= 0) - return; - buf := array[sys->WAITLEN] of byte; - status := ""; - for(;;){ - n := sys->read(waitfd, buf, len buf); - if(n < 0){ - sys->fprint(stderr, "sh9: read wait: %r\n"); - return; - } - status = string buf[0:n]; - if(status[len status-1] != ':') - sys->fprint(stderr, "%s\n", status); - who := int status; - if(who != 0){ - if(who == pid){ - return; - } - } - } -} - -mkprog(ctxt: ref Context, arg: list of string, infd, outfd: ref Sys->FD, waitpid: chan of int) -{ - fds := list of {0, 1, 2}; - if(infd != nil) - fds = infd.fd :: fds; - if(outfd != nil) - fds = outfd.fd :: fds; - pid := sys->pctl(sys->NEWFD, fds); - console := sys->fildes(2); - - if(infd != nil){ - sys->dup(infd.fd, 0); - infd = nil; - } - if(outfd != nil){ - sys->dup(outfd.fd, 1); - outfd = nil; - } - - waitpid <-= pid; - - if(pid < 0 || arg == nil) - return; - - { - exec(ctxt, arg, console); - }exception{ - "fail:*" => - #sys->fprint(console, "%s:%s\n", hd arg, e.name[5:]); - exit; - "write on closed pipe" => - #sys->fprint(console, "%s: %s\n", hd arg, e.name); - exit; - } -} - -exec(ctxt: ref Context, args: list of string, console: ref Sys->FD) -{ - if (args == nil) - return; - cmd := hd args; - file := cmd; - - if(len file<4 || file[len file-4:]!=".dis") - file += ".dis"; - - c := load Sh9 file; - if(c == nil) { - err := sys->sprint("%r"); - if(err != "permission denied" && err != "access permission denied" && file[0]!='/' && file[0:2]!="./"){ - c = load Sh9 "/dis/"+file; - if(c == nil) { - err = sys->sprint("%r"); - } - } - if(c == nil){ - sys->fprint(console, "%s: %s\n", cmd, err); - return; - } - } - - c->init(ctxt, args); -} - -script(ctxt: ref Context, src: string) -{ - bufio = load Bufio Bufio->PATH; - if(bufio == nil){ - sys->fprint(stderr, "sh9: load bufio: %r\n"); - return; - } - - f := bufio->open(src, Bufio->OREAD); - if(f == nil){ - sys->fprint(stderr, "sh9: open %s: %r\n", src); - return; - } - for(;;){ - s := f.gets('\n'); - if(s == nil) - break; - arg := tokenize(s); - if(arg != nil) - runit(ctxt, parseit(arg)); - } -} - -sysname(): string -{ - fd := sys->open("#c/sysname", sys->OREAD); - if(fd == nil) - return "anon"; - buf := array[128] of byte; - n := sys->read(fd, buf, len buf); - if(n < 0) - return "anon"; - return string buf[0:n]; -} - -# Lexer. - -tokenize(s: string): list of string -{ - tok: list of string; - token := ""; - instring := 0; - - loop: - for(i:=0; i<len s; i++) { - if(instring) { - if(s[i] != '\'') - token = addchar(token, s[i]); - else if(i == len s-1 || s[i+1] != '\'') { - if(i == len s-1 || s[i+1] == ' ' || s[i+1] == '\t' || s[i+1] == '\n'){ - tok = token :: tok; - token = ""; - } - instring = 0; - } else { - token[len token] = '\''; - i++; - } - continue; - } - case s[i] { - ' ' or '\t' or '\n' or '#' or - '\'' or '|' or '&' or ';' or - '>' or '<' or '\r' => - if(token != "" && s[i]!='\''){ - tok = token :: tok; - token = ""; - } - case s[i] { - '#' => - break loop; - '\'' => - instring = 1; - '>' => - ss := ""; - ss[0] = s[i]; - if(i<len s-1 && s[i+1]==s[i]) - ss[1] = s[i++]; - tok = ss :: tok; - '|' or '&' or ';' or '<' => - ss := ""; - ss[0] = s[i]; - tok = ss :: tok; - } - * => - token[len token] = s[i]; - } - } - if(instring){ - sys->fprint(stderr, "sh9: unmatched quote\n"); - return nil; - } - return rev(tok); -} - -ismeta(char: int): int -{ - case char { - '*' or '[' or '?' or - '#' or '\'' or '|' or - '&' or ';' or '>' or - '<' => - return 1; - } - return 0; -} - -addchar(token: string, char: int): string -{ - if(ismeta(char) && (len token==0 || token[0]!=Quoted)) - token = stringQuoted + token; - token[len token] = char; - return token; -} - -# Parser. - -getcommand(words: list of string): (ref Command, list of string) -{ - args: list of string; - word: string; - si, so: string; - append := 0; - - gather: - do { - word = hd words; - - case word { - ">" or ">>" => - if(so != nil) - return (nil, nil); - - words = tl words; - - if(words == nil) - return (nil, nil); - - so = hd words; - if(len so>0 && so[0]==Quoted) - so = so[1:]; - if(word == ">>") - append = 1; - "<" => - if(si != nil) - return (nil, nil); - - words = tl words; - - if(words == nil) - return (nil, nil); - - si = hd words; - if(len si>0 && si[0]==Quoted) - si = si[1:]; - "|" or ";" or "&" => - break gather; - * => - files := doexpand(word); - while(files != nil){ - args = hd files :: args; - files = tl files; - } - } - - words = tl words; - } while (words != nil); - - return (ref Command(rev(args), si, so, append), words); -} - -doexpand(file: string): list of string -{ - if(file == nil) - return file :: nil; - if(len file>0 && file[0]==Quoted) - return file[1:] :: nil; - if (nofilepat) - return file :: nil; - for(i:=0; i<len file; i++) - { - if (file[i]=='*' || file[i]=='[' || file[i]=='?'){ - if(filepat == nil) { - if ((filepat = load Filepat Filepat->PATH) == nil) { - sys->fprint(stderr, "sh: warning: cannot load %s: %r\n", - Filepat->PATH); - nofilepat = 1; - return file :: nil; - } - } - files := filepat->expand(file); - if(files != nil) - return files; - break; - } - } - return file :: nil; -} - -revc(arg: list of ref Command): list of ref Command -{ - ret: list of ref Command; - while(arg != nil) { - ret = hd arg :: ret; - arg = tl arg; - } - return ret; -} - -getpipe(words: list of string): (ref Pipeline, list of string) -{ - cmds: list of ref Command; - cur: ref Command; - word: string; - - term := Seq; - gather: - while(words != nil) { - word = hd words; - - if(word == "|") - return (nil, nil); - - (cur, words) = getcommand(words); - - if(cur == nil) - return (nil, nil); - - cmds = cur :: cmds; - - if(words == nil) - break gather; - - word = hd words; - words = tl words; - - case word { - ";" => - break gather; - "&" => - term = Async; - break gather; - "|" => - continue gather; - } - return (nil, nil); - } - - if(word == "|") - return (nil, nil); - - return (ref Pipeline(revc(cmds), term), words); -} - -revp(arg: list of ref Pipeline): list of ref Pipeline -{ - ret: list of ref Pipeline; - - while(arg != nil) { - ret = hd arg :: ret; - arg = tl arg; - } - return ret; -} - -parseit(words: list of string): list of ref Pipeline -{ - ret: list of ref Pipeline; - cur: ref Pipeline; - - while(words != nil) { - (cur, words) = getpipe(words); - if(cur == nil){ - sys->fprint(stderr, "sh9: syntax error\n"); - return nil; - } - ret = cur :: ret; - } - return revp(ret); -} - -# Runner. - -runpipeline(ctx: ref Context, pipeline: ref Pipeline) -{ - if(pipeline.term == Async) - sys->pctl(sys->NEWPGRP, nil); - pid := startpipeline(ctx, pipeline); - if(pid < 0) - return; - if(pipeline.term == Seq) - waitfor(pid); -} - -startpipeline(ctx: ref Context, pipeline: ref Pipeline): int -{ - pid := 0; - cmds := pipeline.cmds; - first := 1; - inpipe, outpipe: ref Sys->FD; - while(cmds != nil) { - last := tl cmds == nil; - cmd := hd cmds; - - infd: ref Sys->FD; - if(!first) - infd = inpipe; - else if(cmd.inf != nil){ - infd = sys->open(cmd.inf, Sys->OREAD); - if(infd == nil){ - sys->fprint(stderr, "sh9: can't open %s: %r\n", cmd.inf); - return -1; - } - } - - outfd: ref Sys->FD; - if(!last){ - fds := array[2] of ref Sys->FD; - if(sys->pipe(fds) < 0){ - sys->fprint(stderr, "sh9: can't make pipe: %r\n"); - return -1; - } - outpipe = fds[0]; - outfd = fds[1]; - fds = nil; - }else if(cmd.outf != nil){ - if(cmd.append){ - outfd = sys->open(cmd.outf, Sys->OWRITE); - if(outfd != nil) - sys->seek(outfd, big 0, Sys->SEEKEND); - } - if(outfd == nil) - outfd = sys->create(cmd.outf, Sys->OWRITE, 8r666); - if(outfd == nil){ - sys->fprint(stderr, "sh9: can't open %s: %r\n", cmd.outf); - return -1; - } - } - - rpid := chan of int; - spawn mkprog(ctx, cmd.args, infd, outfd, rpid); - pid = <-rpid; - infd = nil; - outfd = nil; - - inpipe = outpipe; - outpipe = nil; - - first = 0; - cmds = tl cmds; - } - return pid; -} - -runit(ctx: ref Context, pipes: list of ref Pipeline) -{ - while(pipes != nil) { - pipeline := hd pipes; - pipes = tl pipes; - if(pipeline.term == Seq) - runpipeline(ctx, pipeline); - else - spawn runpipeline(ctx, pipeline); - } -} - -strchr(s: string, c: int): int -{ - ln := len s; - for (i := 0; i < ln; i++) - if (s[i] == c) - return i; - return -1; -} - -# PROFILE: con "/lib/profile"; -PROFILE: con "/lib/infernoinit"; - -startup(ctxt: ref Context) -{ - if (env == nil) - return; - # if (env->getenv("home") != nil) - # return; - home := gethome(); - env->setenv("home", home); - escript(ctxt, PROFILE); - escript(ctxt, home + PROFILE); -} - -escript(ctxt: ref Context, file: string) -{ - fd := sys->open(file, Sys->OREAD); - if (fd != nil) - script(ctxt, file); -} - -gethome(): string -{ - fd := sys->open("/dev/user", sys->OREAD); - if(fd == nil) - return "/"; - buf := array[128] of byte; - n := sys->read(fd, buf, len buf); - if(n < 0) - return "/"; - return "/usr/" + string buf[0:n]; -} - -getusername(): string -{ - fd := sys->open("/dev/user", sys->OREAD); - if(fd == nil) - return "/"; - buf := array[128] of byte; - n := sys->read(fd, buf, len buf); - if(n < 0) - return "?"; - return string buf[0:n]; -} - -getcwd(): string -{ - gwd := load Workdir Workdir->PATH; - if (gwd == nil) { - sys->fprint(stderr, "pwd: cannot load %s: %r\n", Workdir->PATH); - raise "fail:bad module"; - } - - wd := gwd->init(); - if(wd == nil) { - sys->fprint(stderr, "pwd: %r\n"); - raise "fail:error"; - } - return wd; -} |
