diff --git a/src/ChangeLog b/src/ChangeLog
index fdd0a879..20180453 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
+2005-03-18  Hrvoje Niksic  <hniksic@xemacs.org>
+
+	* init.c (cmd_file): Use concat_strings.
+
+	* http.c (basic_authentication_encode): Use concat_strings.
+
+	* ftp-ls.c (ftp_index): Use concat_strings.
+
+	* ftp-basic.c (ftp_request): Use concat_strings.
+
+	* utils.c (concat_strings): New function.
+
 2005-03-12  Hrvoje Niksic  <hniksic@xemacs.org>
 
 	* init.c (simple_atof): Handle negative numbers; skip whitespace
diff --git a/src/ftp-basic.c b/src/ftp-basic.c
index 011268b2..5960ade6 100644
--- a/src/ftp-basic.c
+++ b/src/ftp-basic.c
@@ -93,10 +93,11 @@ ftp_response (int fd, char **ret_line)
 static char *
 ftp_request (const char *command, const char *value)
 {
-  char *res = (char *)xmalloc (strlen (command)
-                               + (value ? (1 + strlen (value)) : 0)
-                               + 2 + 1);
-  sprintf (res, "%s%s%s\r\n", command, value ? " " : "", value ? value : "");
+  char *res;
+  if (value)
+    res = concat_strings (command, " ", value, "\r\n", (char *) 0);
+  else
+    res = concat_strings (command, "\r\n", (char *) 0);
   if (opt.server_response)
     {
       /* Hack: don't print out password.  */
diff --git a/src/ftp-ls.c b/src/ftp-ls.c
index d2dde2ec..71d8e837 100644
--- a/src/ftp-ls.c
+++ b/src/ftp-ls.c
@@ -872,9 +872,10 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
 
       tmpu = url_escape (u->user);
       tmpp = u->passwd ? url_escape (u->passwd) : NULL;
-      upwd = (char *)xmalloc (strlen (tmpu)
-			     + (tmpp ? (1 + strlen (tmpp)) : 0) + 2);
-      sprintf (upwd, "%s%s%s@", tmpu, tmpp ? ":" : "", tmpp ? tmpp : "");
+      if (tmpp)
+	upwd = concat_strings (tmpu, ":", tmpp, "@", (char *) 0);
+      else
+	upwd = concat_strings (tmpu, "@", (char *) 0);
       xfree (tmpu);
       xfree_null (tmpp);
     }
diff --git a/src/ftp.c b/src/ftp.c
index a95e8389..d2e031e7 100644
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -271,8 +271,7 @@ getftp (struct url *u, wgint *len, wgint restval, ccon *con)
       if (con->proxy)
 	{
 	  /* If proxy is in use, log in as username@target-site. */
-	  logname = xmalloc (strlen (user) + 1 + strlen (u->host) + 1);
-	  sprintf (logname, "%s@%s", user, u->host);
+	  logname = concat_strings (user, "@", u->host, (char *) 0);
 	}
 
       /* Login to the server: */
diff --git a/src/http.c b/src/http.c
index ea61911f..646a031e 100644
--- a/src/http.c
+++ b/src/http.c
@@ -2583,7 +2583,7 @@ base64_encode (const char *s, char *store, int length)
 static char *
 basic_authentication_encode (const char *user, const char *passwd)
 {
-  char *t1, *t2, *res;
+  char *t1, *t2;
   int len1 = strlen (user) + 1 + strlen (passwd);
   int len2 = BASE64_LENGTH (len1);
 
@@ -2593,10 +2593,7 @@ basic_authentication_encode (const char *user, const char *passwd)
   t2 = (char *)alloca (len2 + 1);
   base64_encode (t1, t2, len1);
 
-  res = (char *)xmalloc (6 + len2 + 1);
-  sprintf (res, "Basic %s", t2);
-
-  return res;
+  return concat_strings ("Basic ", t2, (char *) 0);
 }
 
 #define SKIP_WS(x) do {				\
diff --git a/src/init.c b/src/init.c
index b504a27b..14abdec0 100644
--- a/src/init.c
+++ b/src/init.c
@@ -748,7 +748,6 @@ cmd_file (const char *com, const char *val, void *closure)
     }
   else
     {
-      char *result;
       int homelen;
       char *home = home_dir ();
       if (!home)
@@ -762,12 +761,7 @@ cmd_file (const char *com, const char *val, void *closure)
       for (++val; ISSEP (*val); val++)
 	;
 
-      result = xmalloc (homelen + 1 + strlen (val) + 1);
-      memcpy (result, home, homelen);
-      result[homelen] = '/';
-      strcpy (result + homelen + 1, val);
-
-      *pstring = result;
+      *pstring = concat_strings (home, "/", val, (char *) 0);
     }
 
 #ifdef WINDOWS
diff --git a/src/url.c b/src/url.c
index 35ae5f81..56d5d9f9 100644
--- a/src/url.c
+++ b/src/url.c
@@ -1009,7 +1009,7 @@ char *
 url_full_path (const struct url *url)
 {
   int length = full_path_length (url);
-  char *full_path = (char *)xmalloc(length + 1);
+  char *full_path = (char *) xmalloc (length + 1);
 
   full_path_write (url, full_path);
   full_path[length] = '\0';
diff --git a/src/utils.c b/src/utils.c
index 1c6f0b06..e5098be3 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -226,6 +226,54 @@ aprintf (const char *fmt, ...)
     }
   return NULL;			/* unreached */
 }
+
+/* Concatenate the NULL-terminated list of string arguments into
+   freshly allocated space.  */
+
+char *
+concat_strings (const char *str0, ...)
+{
+  va_list args;
+  int saved_lengths[5];		/* inspired by Apache's apr_pstrcat */
+  char *ret, *p;
+
+  const char *next_str;
+  int total_length = 0;
+  int argcount;
+
+  /* Calculate the length of and allocate the resulting string. */
+
+  argcount = 0;
+  VA_START (args, str0);
+  for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
+    {
+      int len = strlen (next_str);
+      if (argcount < countof (saved_lengths))
+	saved_lengths[argcount++] = len;
+      total_length += len;
+    }
+  va_end (args);
+  p = ret = xmalloc (total_length + 1);
+
+  /* Copy the strings into the allocated space. */
+
+  argcount = 0;
+  VA_START (args, str0);
+  for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
+    {
+      int len;
+      if (argcount < countof (saved_lengths))
+	len = saved_lengths[argcount++];
+      else
+	len = strlen (next_str);
+      memcpy (p, next_str, len);
+      p += len;
+    }
+  va_end (args);
+  *p = '\0';
+
+  return ret;
+}
 
 /* Return pointer to a static char[] buffer in which zero-terminated
    string-representation of TM (in form hh:mm:ss) is printed.
diff --git a/src/utils.h b/src/utils.h
index be2b0d9c..d6a118d2 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -68,12 +68,14 @@ char **sepstring PARAMS ((const char *));
 int frontcmp PARAMS ((const char *, const char *));
 void fork_to_background PARAMS ((void));
 
-#ifdef HAVE_STDARG_H
+#ifdef WGET_USE_STDARG
 char *aprintf PARAMS ((const char *, ...))
      GCC_FORMAT_ATTR (1, 2);
-#else  /* not HAVE_STDARG_H */
+char *concat_strings PARAMS ((const char *, ...));
+#else  /* not WGET_USE_STDARG */
 char *aprintf ();
-#endif /* not HAVE_STDARG_H */
+char *concat_strings ();
+#endif /* not WGET_USE_STDARG */
 
 void touch PARAMS ((const char *, time_t));
 int remove_link PARAMS ((const char *));