1stMud/CVS/
1stMud/area/CVS/
1stMud/backup/CVS/
1stMud/bin/
1stMud/bin/CVS/
1stMud/bin/extras/
1stMud/bin/extras/CVS/
1stMud/data/CVS/
1stMud/data/i3/CVS/
1stMud/doc/1stMud/
1stMud/doc/1stMud/CVS/
1stMud/doc/CVS/
1stMud/doc/Diku/
1stMud/doc/Diku/CVS/
1stMud/doc/MPDocs/CVS/
1stMud/doc/Merc/CVS/
1stMud/doc/Rom/
1stMud/doc/Rom/CVS/
1stMud/log/CVS/
1stMud/notes/
1stMud/notes/CVS/
1stMud/player/CVS/
1stMud/player/backup/CVS/
1stMud/player/deleted/CVS/
1stMud/src/CVS/
1stMud/src/config/CVS/
1stMud/src/h/CVS/
1stMud/src/o/CVS/
1stMud/win/CVS/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation,    *
* Inc.  Parts of this file are from the GNU C Library.                    *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Library General Public License as published  *
* by the Free Software Foundation; either version 2 of the License, or    *
* (at your option) any later version.                                     *
* This library is distributed in the hope that it will be useful, but     *
* WITHOUT ANY WARRANTY; without even the implied warranty of              * 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
* Library General Public License for more details.                        *
* You should have received a copy of the GNU Library General Public       *
* License along with this library; see the file COPYING.LIB.  If not,     *
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite    *
* 330, Boston, MA 02111-1307, USA.                                        *
***************************************************************************
*          1stMud ROM Derivative (c) 2001-2004 by Markanth                *
*            http://www.firstmud.com/  <markanth@firstmud.com>            *
*         By using this code you have agreed to follow the term of        *
*             the 1stMud license in ../doc/1stMud/LICENSE                 *
***************************************************************************/

#include "merc.h"

#ifndef HAVE_FNMATCH

#define FNM_PATHNAME    (1 << 0)
#define FNM_NOESCAPE    (1 << 1)
#define FNM_PERIOD      (1 << 2)

#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
# define FNM_FILE_NAME   FNM_PATHNAME
# define FNM_LEADING_DIR (1 << 3)
# define FNM_CASEFOLD    (1 << 4)
#endif


#define FNM_NOMATCH     1

# if defined STDC_HEADERS || !defined isascii
#  define ISASCII(c) 1
# else
#  define ISASCII(c) isascii(c)
# endif

#ifdef isblank
# define ISBLANK(c) (ISASCII (c) && isblank (c))
#else
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
#endif
#ifdef isgraph
# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
#else
# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
#endif

#define ISPRINT(c) (ISASCII (c) && isprint (c))
#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
#define ISALNUM(c) (ISASCII (c) && isalnum (c))
#define ISALPHA(c) (ISASCII (c) && isalpha (c))
#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
#define ISLOWER(c) (ISASCII (c) && islower (c))
#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
#define ISSPACE(c) (ISASCII (c) && isspace (c))
#define ISUPPER(c) (ISASCII (c) && isupper (c))
#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))

# if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H

#  if defined CHARCLASS_NAME_MAX
#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
#  else

#   define CHAR_CLASS_MAX_LENGTH 256
#  endif

# define IS_CHAR_CLASS(string) wctype (string)
# else
#  define CHAR_CLASS_MAX_LENGTH  6

#  define IS_CHAR_CLASS(string)    	    	    	    	    	    	      \
(!str_cmp (string, "alpha") || !str_cmp (string, "upper")    	    	    	      \
|| !str_cmp (string, "lower") || !str_cmp (string, "digit")    	    	      \
|| !str_cmp (string, "alnum") || !str_cmp (string, "xdigit")    	    	      \
|| !str_cmp (string, "space") || !str_cmp (string, "print")    	    	      \
|| !str_cmp (string, "punct") || !str_cmp (string, "graph")    	    	      \
|| !str_cmp (string, "cntrl") || !str_cmp (string, "blank"))
# endif

static int
internal_fnmatch (const char *pattern, const char *string,
		  int no_leading_period, int flags)
{
  register const char *p = pattern, *n = string;
  register unsigned char c;


#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))

  while ((c = *p++) != '\0')
    {
      c = FOLD (c);

      switch (c)
	{
	case '?':
	  if (*n == '\0')
	    return FNM_NOMATCH;
	  else if (*n == '/' && (flags & FNM_FILE_NAME))
	    return FNM_NOMATCH;
	  else if (*n == '.' && no_leading_period
		   && (n == string
		       || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
	    return FNM_NOMATCH;
	  break;

	case '\\':
	  if (!(flags & FNM_NOESCAPE))
	    {
	      c = *p++;
	      if (c == '\0')

		return FNM_NOMATCH;
	      c = FOLD (c);
	    }
	  if (FOLD ((unsigned char) *n) != c)
	    return FNM_NOMATCH;
	  break;

	case '*':
	  if (*n == '.' && no_leading_period
	      && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
	    return FNM_NOMATCH;

	  for (c = *p++; c == '?' || c == '*'; c = *p++)
	    {
	      if (*n == '/' && (flags & FNM_FILE_NAME))

		return FNM_NOMATCH;
	      else if (c == '?')
		{

		  if (*n == '\0')

		    return FNM_NOMATCH;
		  else

		    ++n;
		}
	    }

	  if (c == '\0')

	    return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
		    ? FNM_NOMATCH : 0);
	  else
	    {
	      const char *endp;


	      if (!(flags & FNM_FILE_NAME)
		  || ((endp = strchr (n, '/')) == NULL))
		endp = n + strlen (n);

	      if (c == '[')
		{
		  int flags2 = ((flags & FNM_FILE_NAME)
				? flags : (flags & ~FNM_PERIOD));

		  for (--p; n < endp; ++n)
		    if (internal_fnmatch (p, n,
					  (no_leading_period
					   && (n == string
					       || (n[-1] == '/'
						   && (flags
						       &
						       FNM_FILE_NAME)))),
					  flags2) == 0)
		      return 0;
		}
	      else if (c == '/' && (flags & FNM_FILE_NAME))
		{
		  while (*n != '\0' && *n != '/')
		    ++n;
		  if (*n == '/'
		      && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
					    flags) == 0))
		    return 0;
		}
	      else
		{
		  int flags2 = ((flags & FNM_FILE_NAME)
				? flags : (flags & ~FNM_PERIOD));

		  if (c == '\\' && !(flags & FNM_NOESCAPE))
		    c = *p;
		  c = FOLD (c);
		  for (--p; n < endp; ++n)
		    if (FOLD ((unsigned char) *n) == c
			&& (internal_fnmatch (p, n,
					      (no_leading_period
					       && (n == string
						   || (n[-1] == '/'
						       && (flags
							   &
							   FNM_FILE_NAME)))),
					      flags2) == 0))
		      return 0;
		}
	    }


	  return FNM_NOMATCH;

	case '[':
	  {

	    static int posixly_correct;
	    register int except;
	    char cold;

	    if (posixly_correct == 0)
	      posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;

	    if (*n == '\0')
	      return FNM_NOMATCH;

	    if (*n == '.' && no_leading_period && (n == string
						   || (n[-1] == '/'
						       && (flags
							   & FNM_FILE_NAME))))
	      return FNM_NOMATCH;

	    if (*n == '/' && (flags & FNM_FILE_NAME))

	      return FNM_NOMATCH;

	    except = (*p == '!' || (posixly_correct < 0 && *p == '^'));
	    if (except)
	      ++p;

	    c = *p++;
	    for (;;)
	      {
		unsigned char fn = FOLD ((unsigned char) *n);

		if (!(flags & FNM_NOESCAPE) && c == '\\')
		  {
		    if (*p == '\0')
		      return FNM_NOMATCH;
		    c = FOLD ((unsigned char) *p);
		    ++p;

		    if (c == fn)
		      goto matched;
		  }
		else if (c == '[' && *p == ':')
		  {

		    char str[CHAR_CLASS_MAX_LENGTH + 1];
		    size_t c1 = 0;

# if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H

		    wctype_t wt;
# endif

		    const char *startp = p;

		    for (;;)
		      {
			if (c1 == CHAR_CLASS_MAX_LENGTH)

			  return FNM_NOMATCH;

			c = *++p;
			if (c == ':' && p[1] == ']')
			  {
			    p += 2;
			    break;
			  }
			if (c < 'a' || c >= 'z')
			  {

			    p = startp;
			    c = '[';
			    goto normal_bracket;
			  }
			str[c1++] = c;
		      }
		    str[c1] = '\0';

# if defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H

		    wt = IS_CHAR_CLASS (str);
		    if (wt == 0)

		      return FNM_NOMATCH;

		    if (iswctype (btowc ((unsigned char) *n), wt))
		      goto matched;
# else

		    if ((!str_cmp (str, "alnum")
			 && ISALNUM ((unsigned char) *n))
			|| (!str_cmp (str, "alpha")
			    && ISALPHA ((unsigned char) *n))
			|| (!str_cmp (str, "blank")
			    && ISBLANK ((unsigned char) *n))
			|| (!str_cmp (str, "cntrl")
			    && ISCNTRL ((unsigned char) *n))
			|| (!str_cmp (str, "digit")
			    && ISDIGIT ((unsigned char) *n))
			|| (!str_cmp (str, "graph")
			    && ISGRAPH ((unsigned char) *n))
			|| (!str_cmp (str, "lower")
			    && ISLOWER ((unsigned char) *n))
			|| (!str_cmp (str, "print")
			    && ISPRINT ((unsigned char) *n))
			|| (!str_cmp (str, "punct")
			    && ISPUNCT ((unsigned char) *n))
			|| (!str_cmp (str, "space")
			    && ISSPACE ((unsigned char) *n))
			|| (!str_cmp (str, "upper")
			    && ISUPPER ((unsigned char) *n))
			|| (!str_cmp (str, "xdigit")
			    && ISXDIGIT ((unsigned char) *n)))
		      goto matched;
# endif

		  }
		else if (c == '\0')

		  return FNM_NOMATCH;
		else
		  {
		  normal_bracket:
		    if (FOLD (c) == fn)
		      goto matched;

		    cold = c;
		    c = *p++;

		    if (c == '-' && *p != ']')
		      {

			unsigned char cend = *p++;

			if (!(flags & FNM_NOESCAPE) && cend == '\\')
			  cend = *p++;
			if (cend == '\0')
			  return FNM_NOMATCH;

			if (cold <= fn && fn <= FOLD (cend))
			  goto matched;

			c = *p++;
		      }
		  }

		if (c == ']')
		  break;
	      }

	    if (!except)
	      return FNM_NOMATCH;
	    break;

	  matched:

	    while (c != ']')
	      {
		if (c == '\0')

		  return FNM_NOMATCH;

		c = *p++;
		if (!(flags & FNM_NOESCAPE) && c == '\\')
		  {
		    if (*p == '\0')
		      return FNM_NOMATCH;

		    ++p;
		  }
		else if (c == '[' && *p == ':')
		  {
		    do
		      if (*++p == '\0')
			return FNM_NOMATCH;
		    while (*p != ':' || p[1] == ']')
		    ;
		    p += 2;
		    c = *p;
		  }
	      }
	    if (except)
	      return FNM_NOMATCH;
	  }
	  break;

	default:
	  if (c != FOLD ((unsigned char) *n))
	    return FNM_NOMATCH;
	}

      ++n;
    }

  if (*n == '\0')
    return 0;

  if ((flags & FNM_LEADING_DIR) && *n == '/')

    return 0;

  return FNM_NOMATCH;

# undef FOLD
}

int
fnmatch (const char *pattern, const char *string, int flags)
{
  return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
}

#else
void
fnmatch_dummy (void)
{
}
#endif

#ifndef HAVE_SCANDIR

int
scandir (const char *dirname, struct dirent ***namelist,
	 int (*select) (const struct dirent *),
	 int (*dcomp) (const struct dirent **, const struct dirent **))
{
#ifdef WIN32
  int len;
  char *findIn, *d;
  WIN32_FIND_DATA find;
  HANDLE h;
  int nDir = 0, NDir = 0;
  struct dirent **dir = 0, *selectDir;
  unsigned long ret;

  len = strlen (dirname);

  alloc_mem (findIn, char, len + 5);

  strcpy (findIn, dirname);

  for (d = findIn; *d; d++)
    if (*d == '/')
      *d = '\\';

  if ((len == 0))
    strcpy (findIn, ".\\*");

  if ((len == 1) && (d[-1] == '.'))
    strcpy (findIn, ".\\*");

  if ((len > 0) && (d[-1] == '\\'))
    {
      *d++ = '*';
      *d = 0;
    }

  if ((len > 1) && (d[-1] == '.') && (d[-2] == '\\'))
    d[-1] = '*';

  if ((h = FindFirstFile (findIn, &find)) == INVALID_HANDLE_VALUE)
    {
      LPVOID lpMsgBuf;

      ret = GetLastError ();

      if (ret != ERROR_NO_MORE_FILES)
	{
	  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
			 FORMAT_MESSAGE_FROM_SYSTEM, NULL, ret, 0,
			 (LPTSTR) & lpMsgBuf, 0, NULL);

	  MessageBox (NULL, (LPTSTR) lpMsgBuf, "GetLastError",
		      MB_OK | MB_ICONINFORMATION);


	  LocalFree (lpMsgBuf);
	}

      *namelist = dir;
      return nDir;
    }

  do
    {
      alloc_mem (selectDir, struct dirent, strlen (find.cFileName));

      strcpy (selectDir->d_name, find.cFileName);

      if (!select || (*select) (selectDir))
	{
	  if (nDir == NDir)
	    {
	      struct dirent **tempDir;

	      alloc_mem (tempDir, struct dirent *, NDir + 33);

	      if (NDir)
		memcpy (tempDir, dir, sizeof (struct dirent *) * NDir);

	      if (dir)
		free_mem (dir);

	      dir = tempDir;
	      NDir += 32;
	    }

	  dir[nDir++] = selectDir;
	  dir[nDir] = 0;
	}
      else
	free_mem (selectDir);
    }
  while (FindNextFile (h, &find));

  ret = GetLastError ();

  if (ret != ERROR_NO_MORE_FILES)
    {
      LPVOID lpMsgBuf;

      ret = GetLastError ();

      if (ret != ERROR_NO_MORE_FILES)
	{
	  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
			 FORMAT_MESSAGE_FROM_SYSTEM, NULL, ret, 0,
			 (LPTSTR) & lpMsgBuf, 0, NULL);

	  MessageBox (NULL, (LPTSTR) lpMsgBuf, "GetLastError",
		      MB_OK | MB_ICONINFORMATION);


	  LocalFree (lpMsgBuf);
	}
    }

  FindClose (h);
  free_mem (findIn);

  if (dcomp)
    qsort (dir, nDir, sizeof (*dir),
	   (int (*)(const void *, const void *)) dcomp);

  *namelist = dir;
  return nDir;
#else

  register struct dirent *d, *p, **names;
  register int nitems;
  struct stat stb;
  long arraysz;
  DIR *dirp;

  if ((dirp = opendir (dirname)) == NULL)
    return (-1);
  if (fstat (dirp->d_fd, &stb) < 0)
    return (-1);


  arraysz = (stb.st_size / 24);
  names = (struct dirent **) malloc (arraysz * sizeof (struct dirent *));

  if (names == NULL)
    return (-1);

  nitems = 0;
  while ((d = readdir (dirp)) != NULL)
    {
      if (select != NULL && !(*select) (d))
	continue;

      p = (struct dirent *) malloc (d->d_reclen);
      if (p == NULL)
	return (-1);
      p->d_ino = d->d_ino;
      p->d_reclen = d->d_reclen;
      p->d_off = d->d_off;
      strcpy (p->d_name, d->d_name);

      if (++nitems >= arraysz)
	{
	  if (fstat (dirp->d_fd, &stb) < 0)
	    return (-1);
	  arraysz = stb.st_size / 12;
	  names = (struct dirent **) realloc ((char *) names,
					      arraysz *
					      sizeof (struct dirent *));
	  if (names == NULL)
	    return (-1);
	}
      names[nitems - 1] = p;
    }
  closedir (dirp);
  if (nitems && dcomp != NULL)
    qsort (names, nitems, sizeof (struct dirent *),
	   (int (*)(const void *, const void *)) dcomp);

  *namelist = names;
  return (nitems);
#endif
}


int
alphasort (const struct dirent **d1, const struct dirent **d2)
{
  return (strcmp ((*d1)->d_name, (*d2)->d_name));
}

#endif


#ifndef HAVE_INET_ATON
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif

int
inet_aton (const char *cp, struct in_addr *addr)
{
  addr->s_addr = inet_addr (cp);
  return (addr->s_addr == INADDR_NONE) ? 0 : 1;
}
#endif

#ifndef HAVE_STRREV

char *
strrev (char *str)
{
  char *p1, *p2;

  if (!str || !*str)
    return str;
  for (p1 = str, p2 = str + strlen (str) - 1; p2 > p1; ++p1, --p2)
    {
      *p1 ^= *p2;
      *p2 ^= *p1;
      *p1 ^= *p2;
    }
  return str;
}

#endif