summaryrefslogtreecommitdiff
path: root/appl/cmd/p.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/p.b')
-rw-r--r--appl/cmd/p.b141
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;
+}