/************************************************************************** * 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_GETTIMEOFDAY void gettimeofday(struct timeval *t, void *tz) { struct timeb timebuffer; ftime(&timebuffer); t->tv_sec = timebuffer.time; t->tv_usec = timebuffer.millitm * 1000; } #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 void *rpl_malloc(size_t n) { if (n == 0) n = 1; return malloc(n); } void *rpl_realloc(void *ptr, size_t n) { if (n == 0) n = 1; return realloc(ptr, n); }