ref: e9d34f76df78e253167157d440c2d1e8b9993836
parent: 54da79816fab4a03e8f6022d6c9764d9099abd60
parent: b194f947b512b1791e614a5941ebc785cdd28730
author: Ori Bernstein <[email protected]>
date: Fri Jan 3 16:21:23 EST 2014
Merge branch 'master' of git+ssh://git.eigenstate.org/git/ori/mc
--- a/libstd/Makefile
+++ b/libstd/Makefile
@@ -4,6 +4,7 @@
blat.myr \
chartype.myr \
cmp.myr \
+ dial.myr \
die.myr \
endian.myr \
env.myr \
--- /dev/null
+++ b/libstd/dial.myr
@@ -1,0 +1,129 @@
+use "alloc.use"
+use "die.use"
+use "error.use"
+use "sys.use"
+use "sleq.use"
+use "option.use"
+use "ipparse.use"
+use "resolve.use"
+use "fmt.use"
+use "endian.use"
+use "intparse.use"
+use "hasprefix.use"
+use "utf.use"
+
+pkg std =
+ const dial : (dialstr : byte[:] -> error(fd, byte[:]))
+;;
+
+/*
+ a map from service name to a list of (port,proto)
+ pairs in order of preference
+*/
+/* FIXME: implement
+var services : htab(byte[:], [int, byte[:]][:])#
+var inited = false
+*/
+
+/* takes a plan 9 style dial string */
+const dial = {str
+ var proto, host, port
+ var socktype, portnum
+ var sa : sockaddr_in /* we only support inet sockets right now.. ugh. */
+ var sock
+
+ (proto, str) = nameseg(str)
+ (host, str) = nameseg(str)
+ (port, str) = nameseg(str)
+
+ if proto.len == 0
+ -> `Failure "missing proto"
+ elif host.len == 0
+ -> `Failure "missing host"
+ elif port.len == 0
+ -> `Failure "missing port"
+ ;;
+
+ if sleq(proto, "net")
+ -> `Failure "net wildcard proto not yet supported\n"
+ elif sleq(proto, "unix")
+ -> `Failure "net unix proto not yet supported\n"
+ elif sleq(proto, "tcp")
+ socktype = Sockstream
+ elif sleq(proto, "udp")
+ socktype = Sockdgram
+ ;;
+
+ match parseport(port)
+ | `Some n: portnum = n
+ | `None: -> `Failure "bad port"
+ ;;
+
+ match getaddr(host)
+ | `Ipv4 bits:
+ sa.fam = Afinet
+ sa.addr = bits
+ sa.port = hosttonet(portnum)
+ | `Ipv6 bits:
+ -> `Failure "ipv6 not yet supported"
+ ;;
+
+ sock = socket(sa.fam, socktype, 0)
+ if sock < 0
+ -> `Failure "failed to connect to socket"
+ ;;
+ var err
+ err = connect(sock, (&sa) castto(sockaddr#), sizeof(sockaddr_in))
+ if err < 0
+ close(sock)
+ -> `Failure "Failed to bind socket"
+ ;;
+
+ -> `Success sock
+}
+
+const parseport = {port
+ match intparse(port)
+ | `Some n: -> `Some n
+ | `None:
+ /* a small number of hardcoded ports */
+ if sleq(port, "http")
+ -> `Some 80
+ elif sleq(port, "https")
+ -> `Some 443
+ elif sleq(port, "ircd")
+ -> `Some 6667
+ elif sleq(port, "dns")
+ -> `Some 53
+ ;;
+ ;;
+ -> `None
+}
+
+const getaddr = {addr
+ var ip
+
+ match ipparse(addr)
+ | `Some a: ip = a
+ | `None:
+ match resolve(addr)
+ | `Success hi:
+ ip = hi[0].addr
+ slfree(hi)
+ | `Failure m:
+ ;;
+ ;;
+ -> ip
+}
+
+const nameseg = {str
+ var len
+
+ for len = 0; len < str.len; len++
+ if str[len] == '!' castto(byte)
+ -> (str[:len], str[len+1:])
+ ;;
+ ;;
+ -> (str[:], str[len:])
+}
+
--- a/libstd/sys-linux.myr
+++ b/libstd/sys-linux.myr
@@ -70,6 +70,12 @@
zero : byte[8]
;;
+ type sockaddr_storage = struct
+ fam : sockfam
+ __align : uint32
+ __pad : byte[112]
+ ;;
+
/* open options */
const Ordonly : fdopt = 0x0
const Owronly : fdopt = 0x1
@@ -462,6 +468,8 @@
const clock_getres : (clk : clock, ts : timespec# -> int32)
const clock_gettime : (clk : clock, ts : timespec# -> int32)
const clock_settime : (clk : clock, ts : timespec# -> int32)
+ const sleep : (time : uint64 -> int32)
+ const nanosleep : (req : timespec#, rem : timespec# -> int32)
/* system information */
const uname : (buf : utsname# -> int)
@@ -497,6 +505,16 @@
const clock_getres = {clk, ts; -> syscall(Sysclock_getres, clockid(clk), ts) castto(int32)}
const clock_gettime = {clk, ts; -> syscall(Sysclock_gettime, clockid(clk), ts) castto(int32)}
const clock_settime = {clk, ts; -> syscall(Sysclock_settime, clockid(clk), ts) castto(int32)}
+
+const sleep = {time
+ var req, rem
+ req = [.sec = time, .nsec = 0]
+ -> nanosleep(&req, &rem)
+}
+
+const nanosleep = {req, rem;
+ -> syscall(Sysnanosleep, req, rem) castto(int32)
+}
/* system information */
const uname = {buf; -> syscall(Sysuname, buf) castto(int)}