diff --git a/ares/CHANGES b/ares/CHANGES
index 551693f4642e5855cc9602da8d39d98ce3bdc3f6..056c6d6774a5434ea339ca123e6515f049c23a64 100644
--- a/ares/CHANGES
+++ b/ares/CHANGES
@@ -1,3 +1,10 @@
+* March 30, 2004
+- Dominick Meglio's new ares_expand_string. A helper function when decoding
+  incoming DNS packages.
+
+- Daniel Stenberg modified the Makefile.in to use a for loop for the man page
+  installation to improve overview and make it easier to add man pages.
+
 * March 9, 2004
 - Gisle Vanem improved build on Windows.
 
diff --git a/ares/Makefile.in b/ares/Makefile.in
index 290050694a8ef12d591a52a486a79bd090d63613..eac25cf944f6919e1222c2107944aec1b6b1710c 100644
--- a/ares/Makefile.in
+++ b/ares/Makefile.in
@@ -25,7 +25,16 @@ OBJS=	ares__close_sockets.o ares__get_hostent.o ares__read_line.o \
 	ares_free_hostent.o ares_free_string.o ares_gethostbyaddr.o \
 	ares_gethostbyname.o ares_init.o ares_mkquery.o ares_parse_a_reply.o \
 	ares_parse_ptr_reply.o ares_process.o ares_query.o ares_search.o \
-	ares_send.o ares_strerror.o ares_timeout.o ares_version.o
+	ares_send.o ares_strerror.o ares_timeout.o ares_version.o \
+	ares_expand_string.o
+
+MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3   \
+        ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3	      \
+        ares_gethostbyname.3 ares_init.3 ares_init_options.3 ares_mkquery.3   \
+        ares_parse_a_reply.3 ares_parse_ptr_reply.3 ares_process.3	      \
+        ares_query.3 ares_search.3 ares_send.3 ares_strerror.3 ares_timeout.3 \
+        ares_version.3
+
 
 $(LIB): ${OBJS}
 	ar cru $@ ${OBJS}
@@ -60,31 +69,9 @@ install:
 	chmod u-w ${DESTDIR}${libdir}/$(LIB)
 	${INSTALL} -m 444 ${srcdir}/ares.h ${DESTDIR}${includedir}
 	${INSTALL} -m 444 ${srcdir}/ares_version.h ${DESTDIR}${includedir}
-	${INSTALL} -m 444 ${srcdir}/ares_destroy.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_expand_name.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_fds.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_free_hostent.3 \
-		${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_free_string.3 \
-		${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_gethostbyaddr.3 \
-		${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_gethostbyname.3 \
-		${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_init.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_init_options.3 \
-		${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_mkquery.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_parse_a_reply.3 \
-		${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_parse_ptr_reply.3 \
-		${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_process.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_query.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_search.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_send.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_strerror.3 ${DESTDIR}${mandir}/man3
-	${INSTALL} -m 444 ${srcdir}/ares_timeout.3 ${DESTDIR}${mandir}/man3
+	(for man in $(MANPAGES); do \
+	   ${INSTALL} -m 444 ${srcdir}/$${man} ${DESTDIR}${mandir}/man3; \
+	done)
 
 clean:
 	rm -f ${OBJS} $(LIB) adig.o adig ahost.o ahost
diff --git a/ares/ares.h b/ares/ares.h
index 09efa133fc2742638a79479ba69a870dbad4032f..0dea2ff9998c63ef09d02ed6c4ab73be2f4db5b9 100644
--- a/ares/ares.h
+++ b/ares/ares.h
@@ -55,6 +55,7 @@
 #define ARES_EFILE		14
 #define ARES_ENOMEM		15
 #define ARES_EDESTRUCTION	16
+#define ARES_EBADSTR		17
 
 /* Flag values */
 #define ARES_FLAG_USEVC		(1 << 0)
@@ -125,6 +126,8 @@ int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id,
 		 int rd, unsigned char **buf, int *buflen);
 int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
 		     int alen, char **s, long *enclen);
+int ares_expand_string(const unsigned char *encoded, const unsigned char *abuf,
+		     int alen, unsigned char **s, long *enclen);
 int ares_parse_a_reply(const unsigned char *abuf, int alen,
 		       struct hostent **host);
 int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
diff --git a/ares/ares_expand_string.3 b/ares/ares_expand_string.3
new file mode 100644
index 0000000000000000000000000000000000000000..6f501885e93abcb780e21b12e71bbd362887a5fe
--- /dev/null
+++ b/ares/ares_expand_string.3
@@ -0,0 +1,62 @@
+.\" $Id$
+.\"
+.\" Copyright 1998 by the Massachusetts Institute of Technology.
+.\"
+.\" Permission to use, copy, modify, and distribute this
+.\" software and its documentation for any purpose and without
+.\" fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright
+.\" notice and this permission notice appear in supporting
+.\" documentation, and that the name of M.I.T. not be used in
+.\" advertising or publicity pertaining to distribution of the
+.\" software without specific, written prior permission.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose.  It is provided "as is"
+.\" without express or implied warranty.
+.\"
+.TH ARES_EXPAND_NAME 3 "23 July 1998"
+.SH NAME
+ares_expand_string \- Expand a length encoded string
+.SH SYNOPSIS
+.nf
+.B #include <ares.h>
+.PP
+.B int ares_expand_string(const unsigned char *\fIencoded\fP,
+.B      const unsigned char *\fIabuf\fP, int \fIalen\fP, unsigned char **\fIs\fP,
+.B 	int *\fIenclen\fP)
+.fi
+.SH DESCRIPTION
+The
+.B ares_expand_string
+function converts a length encoded string to a NULL terminated C
+string.  The argument
+.I encoded
+gives the beginning of the encoded string, and the arguments
+.I abuf
+and
+.I alen
+give the containing message buffer (necessary for the processing of
+indirection pointers within the encoded domain name).  The result is
+placed in a NUL-terminated allocated buffer, a pointer to which is
+stored in the variable pointed to by
+.IR s .
+The length of the encoded string is stored in the variable pointed to by
+.I enclen
+so that the caller can advance past the encoded string to read
+further data in the message.
+.SH RETURN VALUES
+.B ares_expand_string
+can return any of the following values:
+.TP 15
+.B ARES_SUCCESS
+Expansion of the encoded string succeeded.
+.TP 15
+.B ARES_EBADSTR
+The encoded string was malformed and could not be expanded.
+.TP 15
+.B ARES_ENOMEM
+Memory was exhausted.
+.SH SEE ALSO
+.BR ares_free_string (3)
+.SH AUTHOR
+Dominick Meglio
diff --git a/ares/ares_expand_string.c b/ares/ares_expand_string.c
new file mode 100644
index 0000000000000000000000000000000000000000..135a8d9dc8293d7e863c82b48879487517991e04
--- /dev/null
+++ b/ares/ares_expand_string.c
@@ -0,0 +1,65 @@
+/* Copyright 1998 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ */
+
+#include <sys/types.h>
+
+#ifdef WIN32
+#include "nameser.h"
+#else
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include "ares.h"
+#include "ares_private.h" /* for the memdebug */
+
+/* Simply decodes a length-encoded character string. The first byte of the
+ * input is the length of the string to be returned and the bytes thereafter
+ * are the characters of the string. The returned result will be NULL
+ * terminated.
+ */
+int ares_expand_string(const unsigned char *encoded,
+                       const unsigned char *abuf,
+                       int alen,
+                       unsigned char **s,
+                       long *enclen)
+{
+  unsigned char *q;
+  long len;
+  if (encoded == abuf+alen)
+    return ARES_EBADSTR;
+
+  len = *encoded;
+  if (encoded+len+1 > abuf+alen)
+    return ARES_EBADSTR;
+
+  encoded++;
+
+  *s = malloc(len+1);
+  if (*s == NULL)
+    return ARES_ENOMEM;
+  q = *s; 
+  strncpy((char *)q, (char *)encoded, len);
+  q[len] = '\0';
+
+  *s = q;
+
+  *enclen = len+1; 
+
+  return ARES_SUCCESS;
+}
+
diff --git a/ares/ares_free_string.3 b/ares/ares_free_string.3
index 58f73d4981cba9389244769d6a9140687ba7334b..c60b92a3242fa3a7f5fa23acbd2102fb6e20829b 100644
--- a/ares/ares_free_string.3
+++ b/ares/ares_free_string.3
@@ -26,11 +26,10 @@ ares_free_string \- Free strings allocated by ares functions
 .SH DESCRIPTION
 The
 .I ares_free_string
-function frees a string allocated by the
-.I ares_mkquery
-function.
+function frees a string allocated by an ares function.
 .SH SEE ALSO
 .BR ares_mkquery (3)
+.BR ares_expand_string (3)
 .SH AUTHOR
 Greg Hudson, MIT Information Systems
 .br
diff --git a/ares/ares_strerror.c b/ares/ares_strerror.c
index 5c285eb2cecfd763cc27d45a4a468613715ed2c9..f994fc35844e61cadabb9631d681c668b595e7b6 100644
--- a/ares/ares_strerror.c
+++ b/ares/ares_strerror.c
@@ -36,6 +36,8 @@ const char *ares_strerror(int code)
     "End of file",
     "Error reading file",
     "Out of memory"
+    "Channel is being destroyed",
+    "Misformatted string"
   };
 
   assert(code >= 0 && code < (int)(sizeof(errtext) / sizeof(*errtext)));