+
+char *get_hostname(void)
+{
+ int len = 128;
+ char *hostname = NULL;
+ do {
+ len *= 2;
+ hostname = sresize(hostname, len, char);
+ if ((gethostname(hostname, len) < 0) &&
+ (errno != ENAMETOOLONG)) {
+ sfree(hostname);
+ hostname = NULL;
+ break;
+ }
+ } while (strlen(hostname) >= len-1);
+ return hostname;
+}
+
+SockAddr platform_get_x11_unix_address(const char *sockpath, int displaynum)
+{
+ SockAddr ret = snew(struct SockAddr_tag);
+ int n;
+
+ memset(ret, 0, sizeof *ret);
+ ret->superfamily = UNIX;
+ /*
+ * In special circumstances (notably Mac OS X Leopard), we'll
+ * have been passed an explicit Unix socket path.
+ */
+ if (sockpath) {
+ n = snprintf(ret->hostname, sizeof ret->hostname,
+ "%s", sockpath);
+ } else {
+ n = snprintf(ret->hostname, sizeof ret->hostname,
+ "%s%d", X11_UNIX_PATH, displaynum);
+ }
+
+ if (n < 0)
+ ret->error = "snprintf failed";
+ else if (n >= sizeof ret->hostname)
+ ret->error = "X11 UNIX name too long";
+
+#ifndef NO_IPV6
+ ret->ais = NULL;
+#else
+ ret->addresses = NULL;
+ ret->naddresses = 0;
+#endif
+ ret->refcount = 1;
+ return ret;
+}
+
+SockAddr unix_sock_addr(const char *path)
+{
+ SockAddr ret = snew(struct SockAddr_tag);
+ int n;
+
+ memset(ret, 0, sizeof *ret);
+ ret->superfamily = UNIX;
+ n = snprintf(ret->hostname, sizeof ret->hostname, "%s", path);
+
+ if (n < 0)
+ ret->error = "snprintf failed";
+ else if (n >= sizeof ret->hostname)
+ ret->error = "socket pathname too long";
+
+#ifndef NO_IPV6
+ ret->ais = NULL;
+#else
+ ret->addresses = NULL;
+ ret->naddresses = 0;
+#endif
+ ret->refcount = 1;
+ return ret;
+}
+
+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;
+}