/* 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);
}