diff options
Diffstat (limited to 'appl/cmd/p.b')
| -rw-r--r-- | appl/cmd/p.b | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/appl/cmd/p.b b/appl/cmd/p.b new file mode 100644 index 00000000..519797a9 --- /dev/null +++ b/appl/cmd/p.b @@ -0,0 +1,141 @@ +implement P; +# Original by Steve Arons, based on Plan 9 p + +include "sys.m"; + sys: Sys; + FD: import Sys; +include "draw.m"; +include "string.m"; + str: String; +include "bufio.m"; + bufio: Bufio; + Iobuf: import bufio; +include "sh.m"; + +stderr: ref FD; +outb, cons: ref Iobuf; +drawctxt: ref Draw->Context; + +nlines := 22; # 1/3rd 66-line nroff page (!) +progname := "p"; + +P: module +{ + init: fn(ctxt: ref Draw->Context, argv: list of string); +}; + +usage() +{ + sys->fprint(stderr, "Usage: p [-number] [file...]\n"); + raise "fail:usage"; +} + +init(ctxt: ref Draw->Context, argv: list of string) +{ + sys = load Sys Sys->PATH; + bufio = load Bufio Bufio->PATH; + if(bufio == nil) + nomod(Bufio->PATH); + str = load String String->PATH; + if(str == nil) + nomod(String->PATH); + sys->pctl(Sys->FORKFD, nil); + drawctxt = ctxt; + + stderr = sys->fildes(2); + + if((stdout := sys->fildes(1)) != nil) + outb = bufio->fopen(stdout, bufio->OWRITE); + if(outb == nil){ + sys->fprint(stderr, "p: can't open stdout: %r\n"); + raise "fail:stdout"; + } + cons = bufio->open("/dev/cons", bufio->OREAD); + if(cons == nil){ + sys->fprint(stderr, "p: can't open /dev/cons: %r\n"); + raise "fail:cons"; + } + + if(argv != nil){ + progname = hd argv; + argv = tl argv; + if(argv != nil){ + s := hd argv; + if(len s > 1 && s[0] == '-'){ + (x, y) := str->toint(s[1:],10); + if(y == "" && x > 0) + nlines = x; + else + usage(); + argv = tl argv; + } + } + } + if(argv == nil) + argv = "-" :: nil; + for(; argv != nil; argv = tl argv){ + file := hd argv; + fd: ref Sys->FD; + if(file == "-"){ + file = "stdin"; + fd = sys->fildes(0); + }else + fd = sys->open(file, Sys->OREAD); + if(fd == nil){ + sys->fprint(stderr, "%s: can't open %s: %r\n", progname, file); + continue; + } + page(fd); + fd = nil; + } +} + +nomod(m: string) +{ + sys->fprint(sys->fildes(2), "%s: can't load %s: %r\n", progname, m); + raise "fail:load"; +} + +page(fd: ref Sys->FD) +{ + inb := bufio->fopen(fd, bufio->OREAD); + nl := nlines; + while((line := inb.gets('\n')) != nil){ + outb.puts(line); + if(--nl == 0){ + outb.flush(); + nl = nlines; + pause(); + } + } + outb.flush(); +} + +pause() +{ + for(;;){ + cmdline := cons.gets('\n'); + if(cmdline == nil || cmdline[0] == 'q') # catch ^d + exit; + else if(cmdline[0] == '!') { + done := chan of int; + spawn command(cmdline[1:], done); + <-done; + }else + break; + } +} + +command(cmdline: string, done: chan of int) +{ + sh := load Sh Sh->PATH; + if(sh == nil) { + sys->fprint(stderr, "%s: can't load %s: %r\n", progname, Sh->PATH); + done <-= 0; + return; + } + sys->pctl(Sys->FORKFD, nil); + sys->dup(cons.fd.fd, 0); + sh->system(drawctxt, cmdline); + done <-= 1; +} |
