/*
 * static char *rcsid_porting_c =
 *   "$Id: porting.c,v 1.13 1997/11/11 10:52:01 master Exp $";
 */

/*
    CrossFire, A Multiplayer game for X-windows

    Copyright (C) 1994 Mark Wedel
    Copyright (C) 1992 Frank Tore Johansen

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    The author can be reached via e-mail to master@rahul.net
*/

/* This file contains various functions that are not really unique for
 * crossfire, but rather provides what should be standard functions 
 * for systems that do not have them.  In this way, most of the
 * nasty system dependent stuff is contained here, with the program
 * calling these functions.
 */



#include "global.h"
#include <ctype.h>
#include <sys/stat.h>
/*#include <xdir.h>*/


#ifdef NeXT
#  undef BSD
#endif
#include <sys/param.h>
#include <stdio.h>
#if defined(MACH)
#  include <stdlib.h>
#endif

#include <unistd.h>

#ifndef S_ISDIR
#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
#endif

static unsigned int curtmp = 0;

/*
 * A replacement for the tempnam() function since it's not defined
 * at some unix variants.
 */

char *tempnam_local(char *dir, char *pfx)
{
    char *f, *name;
    pid_t pid=getpid();

    if (!(name = (char *) malloc(MAXPATHLEN)))
	return(NULL);

    if (!pfx)
	pfx = "cftmp.";

    /* This is a pretty simple method - put the pid as a hex digit and
     * just keep incrementing the last digit.  Check to see if the file
     * already exists - if so, we'll just keep looking - eventually we should
     * find one that is free.
     */
    if ((f = (char *)dir)!=NULL) {
	do {
#if !defined(MACH) || defined(NeXT)
	    (void)sprintf(name,"%s/%s%hx%d", f, pfx, pid, curtmp);
#else
	    (void)snprintf(name, MAXPATHLEN, "%s/%s%hx%d", f, pid, pfx, curtmp);
#endif
	    curtmp++;
	} while (access(name, F_OK)!=-1);
	return(name);
    }
  return(NULL);
}



/*
 * A replacement of strdup(), since it's not defined at some
 * unix variants.
 */
char *strdup_local(char *str) {
  char *c=(char *)malloc(sizeof(char)*(strlen(str)+1));
  strcpy(c,str);
  return c;
}


#define DIGIT(x)        (isdigit(x) ? (x) - '0' : \
islower (x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
#define MBASE ('z' - 'a' + 1 + 10)

/*
 * A replacement of strtol() since it's not defined at
 * many unix systems.
 */

long strtol_local(str, ptr, base)
     register char *str;
     char **ptr;
     register int base;
{
  register long val;
  register int c;
  int xx, neg = 0;

  if (ptr != (char **) 0)
    *ptr = str;         /* in case no number is formed */
  if (base < 0 || base > MBASE)
    return (0);         /* base is invalid */
  if (!isalnum (c = *str)) {
    while (isspace (c))
      c = *++str;
    switch (c) {
    case '-':
      neg++;
    case '+':
      c = *++str;
    }
  }
  if (base == 0)
    if (c != '0')
      base = 10;
    else
      if (str[1] == 'x' || str[1] == 'X')
        base = 16;
      else
        base = 8;
  /*
   ** For any base > 10, the digits incrementally following
   ** 9 are assumed to be "abc...z" or "ABC...Z"
   */
  if (!isalnum (c) || (xx = DIGIT (c)) >= base)
    return 0;           /* no number formed */
  if (base == 16 && c == '0' && isxdigit (str[2]) &&
      (str[1] == 'x' || str[1] == 'X'))
    c = *(str += 2);    /* skip over leading "0x" or "0X" */
  for (val = -DIGIT (c); isalnum (c = *++str) && (xx = DIGIT (c)) < base;)
    /* accumulate neg avoids surprises near
       MAXLONG */
    val = base * val - xx;
  if (ptr != (char **) 0)
    *ptr = str;
  return (neg ? val : -val);
}
/*
 * 'Small' tool funtions for help
 */


struct xdirect *xreaddir(dir_ptr, mask)
     XDIR *dir_ptr;
     int mask;
{
  static struct xdirect xde;
#if defined(_AIX) || defined(M_UNIX) && !defined(NeXT)
  struct dirent *de;
#else
  struct direct *de;
#endif
  int namelen;
  struct stat st;

  de = readdir(dir_ptr);
  if (!de) return 0;
#ifdef POSIX
  namelen = strlen(de->d_name);
#else
  namelen = de->d_namlen;
#endif
  xde.d_namlen = namelen;
  xde.d_name   = de->d_name;
  if (mask & (2|4) ) {
    if (stat(xde.d_name, &st) == -1) { /* who knows... */
      xde.size = -1;
      xde.time = 0;
    } else {
      if (S_ISDIR(st.st_mode))
        xde.size = -2;
      else
        xde.size = st.st_size;
      xde.time = st.st_mtime;
  }
    }
  return &xde;
}

/* This seems to be lacking on some system */
#if defined(SVR4) && !defined(__sgi__) && !defined(__sun__) && !defined(SNI)
int strncasecmp(char *s1, char *s2, int n)
{
  register int c1, c2;

  while (*s1 && *s2 && n) {
    c1 = tolower(*s1);
    c2 = tolower(*s2);
    if (c1 != c2)
      return (c1 - c2);
    s1++;
    s2++;
    n--;
  }
  if (!n)
    return(0);
  return (int) (*s1 - *s2);
}


#if !defined(Xpm_Pix)
int strcasecmp(char *s1, char*s2)
{
  register int c1, c2;

  while (*s1 && *s2) {
    c1 = tolower(*s1);
    c2 = tolower(*s2);
    if (c1 != c2)
      return (c1 - c2);
    s1++;
    s2++;
  }
  if (*s1=='\0' && *s2=='\0')
	return 0;
  return (int) (*s1 - *s2);
}
#endif
#endif

/* This takes an err number and returns a string with a description of
 * the error.
 */
char *strerror_local(int errnum)
{
#if defined(SVR4) || defined(linux)
    return(strerror(errnum));
#endif
    return("strerror_local not implemented");
}
