+
+Socket new_unix_listener(SockAddr listenaddr, Plug plug)
+{
+ int s;
+ union sockaddr_union u;
+ union sockaddr_union *addr;
+ int addrlen;
+ Actual_Socket ret;
+ int retcode;
+
+ /*
+ * Create Socket structure.
+ */
+ ret = snew(struct Socket_tag);
+ ret->fn = &tcp_fn_table;
+ ret->error = NULL;
+ ret->plug = plug;
+ bufchain_init(&ret->output_data);
+ ret->writable = 0; /* to start with */
+ ret->sending_oob = 0;
+ ret->frozen = 0;
+ ret->localhost_only = TRUE;
+ ret->pending_error = 0;
+ ret->parent = ret->child = NULL;
+ ret->oobpending = FALSE;
+ ret->outgoingeof = EOF_NO;
+ ret->incomingeof = FALSE;
+ ret->listener = 1;
+ ret->addr = listenaddr;
+ ret->s = -1;
+
+ assert(listenaddr->superfamily == UNIX);
+
+ /*
+ * Open socket.
+ */
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0) {
+ ret->error = strerror(errno);
+ return (Socket) ret;
+ }
+
+ cloexec(s);
+
+ ret->oobinline = 0;
+
+ memset(&u, '\0', sizeof(u));
+ u.su.sun_family = AF_UNIX;
+ strncpy(u.su.sun_path, listenaddr->hostname, sizeof(u.su.sun_path)-1);
+ addr = &u;
+ addrlen = sizeof(u.su);
+
+ if (unlink(u.su.sun_path) < 0 && errno != ENOENT) {
+ close(s);
+ ret->error = strerror(errno);
+ return (Socket) ret;
+ }
+
+ retcode = bind(s, &addr->sa, addrlen);
+ if (retcode < 0) {
+ close(s);
+ ret->error = strerror(errno);
+ return (Socket) ret;
+ }
+
+ if (listen(s, SOMAXCONN) < 0) {
+ close(s);
+ ret->error = strerror(errno);
+ return (Socket) ret;
+ }
+
+ ret->s = s;
+
+ uxsel_tell(ret);
+ add234(sktree, ret);
+
+ return (Socket) ret;
+}