/
teeny/db/
teeny/dbm/
teeny/docs/
teeny/includes/
teeny/misc/
teeny/news/
teeny/text/
/* utils.c */

#include "copyright.h"
#include "config.h"

#include <stdio.h>
#ifdef STRING_H
#include <string.h>
#else
#include <strings.h>
#endif                                /* STRING_H */
#include <ctype.h>
#include <sys/time.h>
#ifdef STDDEF_H
#include <stddef.h>
#else				/* STDDEF_H */
#define size_t unsigned
#endif				/* STDDEF_H */

#include "teeny.h"

/*
 * Some generic utility functions for TeenyMUD 
 */

/*
 * Write a timestamp on an object. In minutes since Jan 1 1970 
 */

#ifdef TIMESTAMPS
void 
stamp(obj)
{
  struct timeval  foo;

  (void) gettimeofday(&foo, (struct timezone *) 0);

  if (set_int_elt(obj, TIMESTAMP, (int) (foo.tv_sec / 60)) == -1)
  {
    warning("timestamp", "failed write to object");
  }
}

#endif

/*
 * Manufactures a new player and returns the object number, one doesn't exist
 * already. 
 *
 */

int 
create_player(p, code)

  char           *p;
  int             code;
{
  char           *name, *pwd;
  int             player;
  int             list;
  char           *work;

  if (parse_name_pwd(p, &name, &pwd) == -1)
    return (-1);

  if (!ok_player_name(name))
    return (-1);

  work = (char *) ty_malloc(strlen(name) + strlen(pwd) + 2,
			    "create_player");

  strcpy(work, name);
  work[strlen(name)] = ' ';
  strcpy(work + strlen(name) + 1, pwd);

  /* Create a player in object number 0 */

  player = create_obj(TYP_PLAYER);
  if (set_str_elt(player, NAME, work) == -1)
    goto createboom;
  if (code == -1)
  {
    if (get_int_elt(STARTING_LOC, CONTENTS, &list) == -1)
      goto createboom;
    if (set_int_elt(player, LOC, STARTING_LOC) == -1)
      goto createboom;
    if (set_int_elt(STARTING_LOC, CONTENTS, player) == -1)
      goto createboom;
  } else
  {
    if (get_int_elt(code, CONTENTS, &list) == -1)
      goto createboom;
    if (set_int_elt(player, LOC, code) == -1)
      goto createboom;
    if (set_int_elt(code, CONTENTS, player) == -1)
      goto createboom;
  }
  if (set_int_elt(player, NEXT, list) == -1)
    goto createboom;
  if (set_int_elt(player, HOME, STARTING_LOC) == -1)
    goto createboom;
  if (set_int_elt(player, OWNER, player) == -1)
    goto createboom;
  if (code == -1)
  {
    int             loc;

    if (get_int_elt(player, LOC, &loc) == -1)
      goto createboom;

    animate(player);
    if (!isdark(player) && !isdark(loc))
      do_pose(player, "has connected.");
  }
#ifdef TIMESTAMPS
  stamp(player);
#endif

  ty_free(work);

  return (player);

createboom:
  ty_free(work);
  destroy_obj(player);
  return (-1);
}

/*
 * Connects a player, if it exists and the password matches. Returns -1 if no
 * dice. 
 *
 */

int 
connect_player(p)

  char           *p;

{
  char           *name, *pwd;
  char           *realname;
  int             player;

  if (parse_name_pwd(p, &name, &pwd) == -1)
    return (-1);

  player = match_player(name);
  if (player == -1)
  {
    return (-1);
  }
  /* Check the password */

  if (get_str_elt(player, NAME, &realname) == -1)
  {
    warning("connect_player", "could not reference name");
    return (-1);
  }
  /* Assume no leading whitespace */
  while (!isspace(*realname) && *realname)
    realname++;
  while (isspace(*realname) && *realname)
    realname++;
  if (*realname == '\0')
    return (-1);

  if (strcmp(realname, pwd) == 0)
  {
    int             loc;

#ifdef TIMESTAMPS
    stamp(player);
#endif
    if (get_int_elt(player, LOC, &loc) == -1)
    {
      warning("connect_player",
	      "could not ref player location");
      return (-1);
    }
    if (!isdark(player) && !isdark(loc))
      do_pose(player, "has connected.");
    animate(player);
    return (player);
  }
  return (-1);

}

void 
disconnect_player(player)
  int             player;
{
  int             loc;

  if (get_int_elt(player, LOC, &loc) == -1)
  {
    warning("disconnect_player", "could not ref player loc");
    return;
  }
  if (!isdark(player) && !isdark(loc))
    do_pose(player, "has disconnected.");
}

/*
 * Hack name/pwd pair up. 
 *
 */

int 
parse_name_pwd(p, name, pwd)
  char           *p;
  char          **name, **pwd;

{
  while (isspace(*p) && *p)
    p++;
  if (*p == '\0')
    return (-1);

  *name = p;
  while (!isspace(*p) && *p)
    p++;
  if (*p == '\0')
    return (-1);
  *p++ = '\0';

  while (isspace(*p) && *p)
    p++;
  if (*p == '\0')
    return (-1);

  *pwd = p;			/* Assume no trailing whitespace. */
  return (0);
}

/*
 * Reliable memory allocation. 
 */

char           *
ty_malloc(n, util)
  int             n;
  char           *util;		/* Identifies the calling routine */

{
  char           *p;
  extern char    *malloc();

  if ((p = (char *) malloc((size_t) n)) == NULL)
  {
    fatal(util, "memory allocation failed");
  }
  return (p);
}

/*
 * Reliable free(), which does NULL OK. 
 */

void 
ty_free(p)
  char           *p;
{
  if (p == NULL)
  {
    return;			/* Ok */
  }
  free(p);
}

/*
 * Converts ints to strings. 
 *
 */

char           *
ty_itoa(p, i)

  char           *p;
  int             i;

{
  char           *ty_itoa_prim();

  if (i < 0)
  {
    i = -i;
    *p++ = '-';
  } else
  if (i == 0)
  {
    *p++ = '0';
    return (p);
  }
  return (ty_itoa_prim(p, i));
}

/* recursively does it to it. Hee! Russ would love me. */

char           *
ty_itoa_prim(p, i)
  char           *p;
  int             i;
{
  if (i == 0)
  {
    return (p);
  } else
  {
    p = ty_itoa_prim(p, i / 10);
    *p++ = (char) (i % 10) + '0';
    return (p);
  }
}

void 
parse_type(str, ret)
  char           *str;
  int            *ret;
{
  if (stringprefix(str, "player"))
  {
    *ret = TYP_PLAYER;
  } else
  if (stringprefix(str, "room"))
  {
    *ret = TYP_ROOM;
  } else
  if (stringprefix(str, "thing") || stringprefix(str, "object"))
  {
    *ret = TYP_THING;
  } else
  if (stringprefix(str, "exit"))
  {
    *ret = TYP_EXIT;
  }				/* else leave ret alone */
}

/* an idea from TinyMUD that has been a long time in coming.. */

int 
ok_name(name)
  char           *name;
{
  return (name && *name
	  && *name != '*'
	  && *name != '#'
	  && *name != '!'
	  && !index(name, '=')
	  && !index(name, '&')
	  && !index(name, '|') 
#ifdef ILLEGAL_NAMES
	  && strcasecmp(name, "A")
	  && strcasecmp(name, "An")
	  && strcasecmp(name, "The")
	  && strcasecmp(name, "You")
	  && strcasecmp(name, "Your")
	  && strcasecmp(name, "Going")
	  && strcasecmp(name, "Huh?")
	  && strcasecmp(name, "[")
#endif				/* ILLEGAL_NAMES */
	  && strcasecmp(name, "me")
	  && strcasecmp(name, "home")
	  && strcasecmp(name, "here"));
}

int 
ok_player_name(name)
  char           *name;
{
  if (!ok_name(name) || (strlen(name) > 16) || (match_player(name) != -1)
      /*|| index(name, '=') || index(name, '&') || index(name, '|')*/)
    return (0);
  else
    return (1);
}

int
ok_exit_name(name)
  char                 *name;
{
  char *p, *q, *buf;

  if(!ok_name(name))
    return (0);

  buf = (char *)ty_malloc(strlen(name) + 1, "ok_exit_name");
  (void)strcpy(buf, name);

  /* we have to check each sub string... */
  q = buf;
  while(q && *q){
    for(p = q; *p && *p != ';'; p++);
    if(*p)
      *p++ = 0;
    if(!ok_name(q)){
      ty_free((char *)buf);
      return (0);
    }
    q = p;
  }

  ty_free((char *)buf);
  return(1);
}