+ struct addrinfo *p;
+
+ if(l1 == NULL)
+ return(l2);
+ for(p = l1; p->ai_next != NULL; p = p->ai_next);
+ p->ai_next = l2;
+ return(l1);
+}
+
+/* This isn't actually correct, in any sense of the word. It only
+ * works on systems whose getaddrinfo implementation saves the
+ * sockaddr in the same malloc block as the struct addrinfo. Those
+ * systems include at least FreeBSD and glibc-based systems, though,
+ * so it should not be any immediate threat, and it allows me to not
+ * implement a getaddrinfo wrapper. It can always be changed, should
+ * the need arise. */
+static struct addrinfo *unixgai(int type, char *path)
+{
+ void *buf;
+ struct addrinfo *ai;
+ struct sockaddr_un *un;
+
+ buf = smalloc(sizeof(*ai) + sizeof(*un));
+ memset(buf, 0, sizeof(*ai) + sizeof(*un));
+ ai = (struct addrinfo *)buf;
+ un = (struct sockaddr_un *)(buf + sizeof(*ai));
+ ai->ai_flags = 0;
+ ai->ai_family = AF_UNIX;
+ ai->ai_socktype = type;
+ ai->ai_protocol = 0;
+ ai->ai_addrlen = sizeof(*un);
+ ai->ai_addr = (struct sockaddr *)un;
+ ai->ai_canonname = NULL;
+ ai->ai_next = NULL;
+ un->sun_family = PF_UNIX;
+ strncpy(un->sun_path, path, sizeof(un->sun_path) - 1);
+ return(ai);
+}
+
+static struct addrinfo *resolvtcp(char *name, int port)
+{
+ struct addrinfo hint, *ret;
+ char tmp[32];