shithub: mc

Download patch

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)}