shithub: mc

Download patch

ref: 3384df94db0bc2cd8cb97f5eddbdcabc9b2a2eae
parent: 6ea9b06b98aadfb089b71775deb5be03fec26e72
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Jan 19 20:47:14 EST 2016

Clean up std.dial, and add support for unix socks.

	The code was inflexible and ugly. Let's fix that, and
	add support for a socket that is used frequently.

--- a/lib/std/dial+posixy.myr
+++ b/lib/std/dial+posixy.myr
@@ -11,6 +11,7 @@
 use "resolve.use"
 use "result.use"
 use "sleq.use"
+use "slcp.use"
 use "strfind.use"
 use "syswrap.use"
 use "utf.use"
@@ -29,33 +30,45 @@
 */
 
 /* takes a plan 9 style dial string */
-const dial = {str
-	var proto, host, port
+const dial = {ds
+	match nameseg(ds)
+	/*
+	| `Some ("net", str):	-> guessdial(str)
+	*/
+	| `Some ("tcp", str):	-> dialsock(sys.Sockstream, str)
+	| `Some ("udp", str):	-> dialsock(sys.Sockdgram, str)
+	| `Some ("unix", u):	-> dialunix(u)
+	| `Some (proto, str):	-> `Fail "unknown protocol"
+	| `None:	-> `Fail "missing protocol"
+	;;
+}
+
+const dialsock = {proto, str
 	var sa4 : sys.sockaddr_in
 	var sa6 : sys.sockaddr_in6
 	var sa	: sys.sockaddr#
+	var host, portstr, port
 	var sock, sz
 
-	match parsedial(str)
-	| `Ok val:	(proto, host, port) = val
-	| `Fail m:	-> `Fail m
+	match nameseg(str)
+	| `std.None:	-> `Fail "required host!port for ip dial"
+	| `std.Some ("", _):	-> `Fail "empty host"
+	| `std.Some (_, ""):	-> `Fail "empty host"
+	| `std.Some segs:	(host, portstr) = segs
 	;;
 
+	match parseport(portstr)
+	| `std.Some p:	port = p
+	| `std.None:	-> `Fail("invalid port")
+	;;
+
 	match getaddr(host)
 	| `Ipv4 bits:
-		sa4 = [
-			.fam = sys.Afinet,
-			.addr = bits,
-			.port = hosttonet(port),
-		]
+		sa4=[.fam=sys.Afinet, .addr=bits, .port=hosttonet(port)]
 		sa = &sa4 castto(sys.sockaddr#)
 		sz = sizeof(sys.sockaddr_in)
 	| `Ipv6 bits:
-		sa6 = [
-			.fam = sys.Afinet6,
-			.addr = bits,
-			.port = hosttonet(port),
-		]
+		sa6=[.fam=sys.Afinet6, .addr=bits, .port=hosttonet(port)]
 		sa = &sa6 castto(sys.sockaddr#)
 		sz = sizeof(sys.sockaddr_in6)
 	;;
@@ -62,7 +75,7 @@
 	sock = sys.socket(sa.fam, proto, 0)
 
 	if sock < 0
-		-> `Fail "failed to connect to socket"
+		-> `Fail "failed to create socket"
 	;;
 	var err
 	err = sys.connect(sock, sa, sz)
@@ -74,42 +87,24 @@
 	-> `Ok (sock castto(fd))
 }
 
-const parsedial = {str
-	var proto, host, port
-	var socktype, portnum
-
-	(proto, str) = nameseg(str)
-	(host, str) = nameseg(str)
-	(port, str) = nameseg(str)
-
-	if proto.len == 0
-		-> `Fail "missing proto"
-	elif host.len == 0
-		-> `Fail "missing host"
+const dialunix = {path
+	var sa : sys.sockaddr_un
+	var sock
+	
+	sa = [.fam = sys.Afunix]
+	if path.len >= sa.path.len
+		-> `Fail "path too long"
 	;;
 
-	if sleq(proto, "net")
-		-> `Fail "net wildcard proto not yet supported\n"
-	elif sleq(proto, "unix")
-		-> `Fail "net unix proto not yet supported\n"
-	elif sleq(proto, "tcp")
-		if port.len == 0
-			-> `Fail "missing port"
-		;;
-		socktype = sys.Sockstream
-	elif sleq(proto, "udp")
-		if port.len == 0
-			-> `Fail "missing port"
-		;;
-		socktype = sys.Sockdgram
+	sock = sys.socket(sys.Afunix, sys.Sockstream, 0)
+	if sock < 0
+		-> `Fail "failed to create socket"
 	;;
-
-	match parseport(port)
-	| `Some n:	portnum = n
-	| `None:	-> `Fail "bad port"
+	std.slcp(sa.path[:path.len], path)
+	if sys.bind(sock, &sa castto(sys.sockaddr#), sizeof(sys.sockaddr_un)) < 0
+		-> `Fail "failed to bind address"
 	;;
-
-	-> `Ok (socktype, host, portnum)
+	-> `std.Ok (sock castto(fd))
 }
 
 const parseport = {port
@@ -150,9 +145,9 @@
 const nameseg = {str
 	match strfind(str, "!")
 	| `Some idx:
-		-> (str[:idx], str[idx+1:])
+		-> `Some (str[:idx], str[idx+1:])
 	| `None:
-		-> (str, "")
+		-> `None
 	;;
 }
 
--- a/lib/sys/sys+freebsd-x64.myr
+++ b/lib/sys/sys+freebsd-x64.myr
@@ -118,6 +118,12 @@
 		scope	: uint32
 	;;
 
+	type sockaddr_un = struct
+		len	: byte
+		fam	: sockfam
+		path	: byte[104]
+	;;
+
 	type sockaddr_storage = struct
 		len	: byte
 		fam	: sockfam