ref: bd25454011010946b91c21e8af737d86505c4041
parent: 59d49a9789ad8fae0d464e3e60e1196d7d861d18
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Sep 11 19:27:16 EDT 2017
Add missing listen implementation on plan9.
--- a/lib/std/bld.sub
+++ b/lib/std/bld.sub
@@ -108,6 +108,7 @@
env+posixy.myr
errno+plan9.myr
listen+posixy.myr
+ listen+plan9.myr
resolve+plan9.myr
resolve+posixy.myr
wait+plan9.myr
--- /dev/null
+++ b/lib/std/listen+plan9.myr
@@ -1,0 +1,171 @@
+use sys
+
+use "alloc"
+use "die"
+use "dirname"
+use "fmt"
+use "option"
+use "result"
+use "strfind"
+use "syswrap"
+use "cstrconv"
+use "utf"
+
+pkg std =
+ const announce : (ds : byte[:] -> result(fd, byte[:]))
+ const accept : (lfd : fd -> result(fd, byte[:]))
+;;
+
+const Maxpath = 256
+
+const announce = {ds
+ var a, abuf : byte[Maxpath]
+ var f, fbuf : byte[Maxpath]
+ var l, lbuf : byte[Maxpath]
+ var nbuf : byte[32]
+ var dir, ctl, lfd, n
+
+ /* announce */
+ match translate(ds, abuf[:], fbuf[:])
+ | `Err _: -> `Err "invalid dial string"
+ | `Ok (addr, file):
+ put("addr: {}, file: {}\n", addr, file)
+ a = addr
+ f = file
+ match strrfind(f, "/")
+ | `Some i: dir = i
+ | `None: -> `Err "invalid net dir"
+ ;;
+ ;;
+
+ match open(f, Ordwr)
+ | `Ok fd: ctl = fd
+ | `Err e: -> `Err "could not open ctl fd"
+ ;;
+
+ match read(ctl, nbuf[:])
+ | `Err e: ->`Err "unable to read ctl fd"
+ | `Ok nn: l = bfmt(lbuf[:], "{}/{}/listen", f[:dir], nbuf[:nn])
+ ;;
+
+ put("announce {}\n", a)
+ n = fput(ctl, "announce {}", a)
+ if n <= 0
+ close(ctl)
+ -> `Err "writing announce"
+ ;;
+
+ /* listen */
+ match open(l, Ordwr)
+ | `Err e:
+ close(ctl)
+ -> `Err "could not open ctl"
+ | `Ok fd:
+ lfd = fd
+ ;;
+ close(ctl)
+
+ -> `Ok lfd
+}
+
+const accept = {lfd -> result(fd, byte[:])
+ var dir, dirbuf : byte[40]
+ var num, numbuf : byte[40]
+ var dat, datbuf : byte[Maxpath]
+
+
+
+ match read(lfd, numbuf[:])
+ | `Ok n: num = numbuf[:n]
+ | `Err e: -> `Err "could not accept"
+ ;;
+ fput(lfd, "accept {}", num)
+
+ sys.fd2path((lfd : sys.fd), dirbuf[:])
+ dir = dirname(cstrconv(dirbuf[:]))
+ match strrfind(dir, "/")
+ | `None: dat = bfmt(datbuf[:], "{}/{}/data", dir, num)
+ | `Some i: dat = bfmt(datbuf[:], "{}/{}/data", dir[:i], num)
+ ;;
+
+ put("data fd: {}\n", dat)
+ match open(dat, Ordwr)
+ | `Ok fd: -> `Ok fd
+ | `Err e: -> `Err "could not open data fd"
+ ;;
+}
+
+const translate = {ds, addrbuf, filebuf
+ var cs, csbuf : byte[Maxpath]
+ var r, rbuf : byte[Maxpath]
+ var netdir, rest
+ var addr, file
+
+ match strfind(ds, "!")
+ | `None: -> `Err void
+ | `Some sep:
+ if decode(ds[:sep]) == '#' || decode(ds[:sep]) == '/'
+ match strrfind(ds[:sep], "/")
+ | `None: -> `Err void
+ | `Some idx:
+ netdir = ds[:idx]
+ rest = ds[idx+1:]
+ ;;
+ else
+ netdir = "/net"
+ addr = ds
+ ;;
+ ;;
+
+ cs = bfmt(csbuf[:], "{}/cs", netdir)
+ match open(cs, Ordwr)
+ | `Err e: -> identtrans(rest, netdir, addrbuf, filebuf)
+ | `Ok fd:
+ match write(fd, addr)
+ | `Err e:
+ close(fd)
+ -> `Err void
+ | `Ok _:
+ ;;
+
+ seek(fd, 0, Seekset)
+ match read(fd, rbuf[:])
+ | `Err e:
+ close(fd)
+ -> `Err void
+ | `Ok n:
+ r = rbuf[:n]
+ ;;
+ close(fd)
+ ;;
+
+ put("cs returned: {}\n", r)
+ match strfind(r, " ")
+ | `None: -> `Err void
+ | `Some i:
+ addr = bfmt(addrbuf, "{}", r[i+1:])
+ if decode(r) == '/'
+ match strfind(r[:i], "/")
+ | `None: -> `Err void
+ | `Some 0: file = bfmt(filebuf, "{}{}", netdir, r[:i])
+ | `Some n: file = bfmt(filebuf, "{}{}", netdir, r[n+1:])
+ ;;
+ else
+ file = bfmt(filebuf, "{}/{}", netdir, r[:i])
+ ;;
+ ;;
+ -> `Ok (addr, file)
+}
+
+const identtrans = {ds, netdir, addrbuf, filebuf
+ var a, f
+
+ match strfind(ds, "!")
+ | `None:
+ -> `Err void
+ | `Some sep:
+ a = bfmt(addrbuf, "{}", ds[sep + 1:])
+ f = bfmt(filebuf, "{}/{}/clone", netdir, ds[:sep])
+ -> `Ok (a, f)
+ ;;
+}