diff options
Diffstat (limited to 'appl/cmd/9srvfs.b')
| -rw-r--r-- | appl/cmd/9srvfs.b | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/appl/cmd/9srvfs.b b/appl/cmd/9srvfs.b new file mode 100644 index 00000000..d152d1bb --- /dev/null +++ b/appl/cmd/9srvfs.b @@ -0,0 +1,99 @@ +implement P9srvfs; + +include "sys.m"; + sys: Sys; + +include "draw.m"; + +include "string.m"; + str: String; + +include "sh.m"; + sh: Sh; + +include "arg.m"; + +P9srvfs: module +{ + init: fn(nil: ref Draw->Context, nil: list of string); +}; + +init(ctxt: ref Draw->Context, args: list of string) +{ + sys = load Sys Sys->PATH; + str = load String String->PATH; + if(str == nil) + nomod(String->PATH); + + perm := 8r600; + arg := load Arg Arg->PATH; + if(arg == nil) + nomod(Arg->PATH); + arg->init(args); + arg->setusage("9srvfs [-p perm] name path|{command}"); + while((o := arg->opt()) != 0) + case o { + 'p' => + s := arg->earg(); + if(s == nil) + arg->usage(); + (perm, s) = str->toint(s, 8); + if(s != nil) + arg->usage(); + * => + arg->usage(); + } + args = arg->argv(); + if(len args != 2) + arg->usage(); + arg = nil; + + srvname := hd args; + args = tl args; + dest := hd args; + if(dest == nil) + dest = "."; + iscmd := dest[0] == '{' && dest[len dest-1] == '}'; + if(!iscmd){ # quick check before creating service file + (ok, d) := sys->stat(dest); + if(ok < 0) + error(sys->sprint("can't stat %s: %r", dest)); + if((d.mode & Sys->DMDIR) == 0) + error(sys->sprint("%s: not a directory", dest)); + }else{ + sh = load Sh Sh->PATH; + if(sh == nil) + nomod(Sh->PATH); + } + srvfd := sys->create("/srv/"+srvname, Sys->ORDWR, perm); + if(srvfd == nil) + error(sys->sprint("can't create /srv/%s: %r", srvname)); + if(iscmd){ + sync := chan of int; + spawn runcmd(sh, ctxt, dest :: nil, srvfd, sync); + <-sync; + }else{ + if(sys->export(srvfd, dest, Sys->EXPWAIT) < 0) + error(sys->sprint("export failed: %r")); + } +} + +error(msg: string) +{ + sys->fprint(sys->fildes(2), "9srvfs: %s\n", msg); + raise "fail:error"; +} + +nomod(mod: string) +{ + error(sys->sprint("can't load %s: %r", mod)); +} + +runcmd(sh: Sh, ctxt: ref Draw->Context, argv: list of string, stdin: ref Sys->FD, sync: chan of int) +{ + sys->pctl(Sys->FORKFD, nil); + sys->dup(stdin.fd, 0); + stdin = nil; + sync <-= 0; + sh->run(ctxt, argv); +} |
