diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/ns.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/cmd/ns.b')
| -rw-r--r-- | appl/cmd/ns.b | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/appl/cmd/ns.b b/appl/cmd/ns.b new file mode 100644 index 00000000..38bb86af --- /dev/null +++ b/appl/cmd/ns.b @@ -0,0 +1,157 @@ +# ns - display the construction of the current namespace (loosely based on plan 9's ns) +implement Ns; + +include "sys.m"; + sys: Sys; + +include "draw.m"; + +include "arg.m"; + +Ns: module +{ + init: fn(nil: ref Draw->Context, argv: list of string); +}; + +SHELLMETA: con "' \t\\$#"; + +usage() +{ + sys->fprint(sys->fildes(2), "usage: ns [-r] [pid]\n"); + raise "fail:usage"; +} + +init(nil: ref Draw->Context, args: list of string) +{ + sys = load Sys Sys->PATH; + + arg := load Arg Arg->PATH; + if(arg == nil){ + sys->fprint(sys->fildes(2), "ns: can't load %s: %r\n", Arg->PATH); + raise "fail:load"; + } + arg->init(args); + pid := sys->pctl(0, nil); + raw := 0; + while((o := arg->opt()) != 0) + case o { + 'r' => + raw = 1; + * => + usage(); + } + args = arg->argv(); + arg = nil; + + if(len args > 1) + usage(); + if(len args > 0) + pid = int hd args; + + nsname := sys->sprint("/prog/%d/ns", pid); + nsfd := sys->open(nsname, Sys->OREAD); + if(nsfd == nil) { + sys->fprint(sys->fildes(2), "ns: can't open %s: %r\n", nsname); + raise "fail:open"; + } + + buf := array[2048] of byte; + while((l := sys->read(nsfd, buf, len buf)) > 0){ + (nstr, lstr) := sys->tokenize(string buf[0:l], " \n"); + if(nstr < 2) + continue; + cmd := hd lstr; + lstr = tl lstr; + if(cmd == "cd" && lstr != nil){ + sys->print("%s %s\n", cmd, quoted(hd lstr)); + continue; + } + + sflag := ""; + if((hd lstr)[0] == '-') { + sflag = hd lstr + " "; + lstr = tl lstr; + } + if(len lstr < 2) + continue; + + src := hd lstr; + lstr = tl lstr; + if(len src >= 3 && (src[0:2] == "#/" || src[0:2] == "#U")) # remove unnecesary #/'s and #U's + src = src[2:]; + + # remove "#." from beginning of destination path + dest := hd lstr; + if(dest == "#M") { + dest = dest[2:]; + if(dest == "") + dest = "/"; + } + + if(cmd == "mount" && !raw) + src = netaddr(src); # optionally rewrite network files to network address + + # quote arguments if "#" found + sys->print("%s %s%s %s\n", cmd, sflag, quoted(src), quoted(dest)); + } + if(l < 0) + sys->fprint(sys->fildes(2), "ns: error reading %s: %r\n", nsname); +} + +netaddr(f: string): string +{ + if(len f < 1 || f[0] != '/') + return f; + (nf, flds) := sys->tokenize(f, "/"); # expect /net[.alt]/proto/2/data + if(nf < 4) + return f; + netdir := hd flds; + if(netdir != "net" && netdir != "net.alt") + return f; + proto := hd tl flds; + d := hd tl tl flds; + if(hd tl tl tl flds != "data") + return f; + fd := sys->open(sys->sprint("/%s/%s/%s/remote", hd flds, proto, d), Sys->OREAD); + if(fd == nil) + return f; + buf := array[256] of byte; + n := sys->read(fd, buf, len buf); + if(n <= 0) + return f; + if(buf[n-1] == byte '\n') + n--; + if(netdir != "net") + proto = "/"+netdir+"/"+proto; + return sys->sprint("%s!%s", proto, string buf[0:n]); +} + +any(c: int, t: string): int +{ + for(j := 0; j < len t; j++) + if(c == t[j]) + return 1; + return 0; +} + +contains(s: string, t: string): int +{ + for(i := 0; i<len s; i++) + if(any(s[i], t)) + return 1; + return 0; +} + +quoted(s: string): string +{ + if(!contains(s, SHELLMETA)) + return s; + r := "'"; + for(i := 0; i < len s; i++){ + if(s[i] == '\'') + r[len r] = '\''; + r[len r] = s[i]; + } + r[len r] = '\''; + return r; +} |
