/* $Id: missing.c,v 1.2 2002/12/09 05:28:09 selinger Exp $ */
/* replacements for missing library functions */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

#include "missing.h"

#ifndef HAVE_HSTRERROR
#include <netdb.h>
const char *hstrerror(int err)
{
	switch(err) {
	 case HOST_NOT_FOUND:	return "host not found";
#if NO_ADDRESS != NO_DATA
	 case NO_ADDRESS:
#endif
	 case NO_DATA:		return "no A record";
	 case NO_RECOVERY:	return "non-recoverable error";
	 case TRY_AGAIN:	return "temporary failure";
	 default:		return "nap's hstrerror.c: unknown error code";
	}
}
#endif

#ifndef HAVE_STRCASESTR
/* Case insensitive strstr() */
char *strcasestr(const char *haystack, const char *needle)
{
  const char *p, *q;
  for (; *haystack; haystack++) {
    p = haystack;
    q = needle;

    /* note: tolower() is locale dependent, just like strcasecmp() */
    while (*p && tolower(*p) == tolower(*q)) { 
      p++; 
      q++; 
    }	/* compare */
    if (!*q) {
      return (char *)haystack;		/* got match */
    }
  }

  return NULL;				/* not found */
}
#endif

#ifndef HAVE_STRSEP
/* extract token from string */
char *strsep(char **stringp, const char *delim)
{
  char *p;
  
  p = *stringp;
  if (p) {
    *stringp = strpbrk(*stringp, delim);
    if (*stringp) {
      **stringp = 0;
      *stringp++;
    }
  }
  return p;
}
#endif

#ifndef HAVE_VASPRINTF
/* print to a newly allocated string *str. This replaces the libc6
   function of the same name, where it is missing. */
int vasprintf(char **str, const char *fmt, va_list args)
{
  int size, r;
  va_list workargs;

  size = 100;
  *str = malloc(size);

  while (1) {
    va_copy(workargs, args); /* work copy of args */

    /* can this really be called more than once without resetting args? */

    /* MVB: Only if the va_list is a simple type (i.e. (void *) on Linux)
       because it gets passed by value. Problems will arise if va_list is (a
       pointer to) a structure which needs deep copy. (As seen on certain
       platforms.) So always use va_copy or __va_copy (Linux), if available.
       Hopefully, va_copy will be included in the next revision of the ANSI
       C standard. */

    r = vsnprintf(*str, size, fmt, workargs);
    va_end(workargs); /* Free memory used by copy, if necessary. In Linux
			 this is just a dummy call. */

    /* Note the return value of vsnprintf changed from glibc 2.0 to
       2.1, but this code works for both. */
    if (r >- 1 && r < size)
      break;
    else if (r > -1)
      size = r + 1;
    else
      size <<= 1;

    *str = (char *)realloc(*str, size);
  }

  return(strlen(*str));
}
#endif /* HAVE_VASPRINTF */

