/* 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 */
#ifdef MALLOC_H
#include <malloc.h>
#endif /* MALLOC_H */
#if defined(ALLOCA_H) && !defined(NO_ALLOCA)
#include <alloca.h>
#endif
#include "teeny.h"
#include "rwho.h"
void announce_connect();
void announce_disconnect();
int malloc_calls = 0, malloc_total = 0, malloc_free = 0;
/*
* Some generic utility functions for TeenyMUD
*/
/*
* Write a timestamp on an object. In minutes since Jan 1 1970
*/
void stamp(obj)
{
struct timeval foo;
(void) gettimeofday(&foo, (struct timezone *) 0);
if (set_int_elt(obj, TIMESTAMP, (int) foo.tv_sec) == -1) {
warning("timestamp", "failed write to object");
}
}
/*
* 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, flags;
if (parse_name_pwd(p, &name, &pwd) == -1)
return (-1);
if (!ok_player_name(name))
return (-1);
if (!pwd || !*pwd)
return (-1);
/* Create a player in object number 0 */
player = create_obj(TYP_PLAYER);
if (set_str_elt(player, NAME, name) == -1)
goto createboom;
if (set_str_elt(player, PASSWORD, crypt(pwd, CRYPT_KEY)) == -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;
#ifdef AUTO_GUEST
if (get_int_elt(player, FLAGS, &flags) == -1)
goto createboom;
if (set_int_elt(player, FLAGS, flags | GUEST) == -1)
goto createboom;
#endif
} 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;
#ifdef AUTO_BUILDER
if (get_int_elt(player, FLAGS, &flags) == -1)
goto createboom;
if (set_int_elt(player, FLAGS, flags | BUILDER) == -1)
goto createboom;
#endif
if (set_int_elt(player, QUOTA, STARTING_QUOTA) == -1)
goto createboom;
if (code == -1) {
int loc;
if (get_int_elt(player, LOC, &loc) == -1)
goto createboom;
if (!isdark(player) && !isdark(loc))
do_pose(player, "has connected.");
announce_connect(player);
}
return (player);
createboom:
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 *realpwd;
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, PASSWORD, &realpwd) == -1) {
warning("connect_player", "could not reference pword");
return (-1);
}
if (((!realpwd || !*realpwd) && !pwd) ||
(pwd && *pwd && (strcmp(realpwd, crypt(pwd, CRYPT_KEY)) == 0))) {
return (player);
}
return (-1);
}
void connect_player2(player)
int player;
{
int loc;
if (get_int_elt(player, LOC, &loc) != -1) {
if (!isdark(player) && !isdark(loc))
do_pose(player, "has connected.");
}
announce_connect(player);
}
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.");
announce_disconnect(player);
if (isguest(player)) {
/* send "GUEST" players to their home */
send_home(player, loc);
if (isroom(loc))
flush_room(loc);
}
#ifdef SUPPORT_RWHO
if (rwho_enabled)
rwho_logout(player);
#endif
}
/*
* Hack name/pwd pair up. Hopefully modified to support multi-word names.
*/
int parse_name_pwd(p, name, pwd)
char *p;
char **name, **pwd;
{
register char *q;
char ch;
while (isspace(*p) && *p)
p++;
if (*p == '\0')
return (-1);
if (*p != '\"') { /* the name isn't quoted, fuck */
/* assume the first word is name, all other is pword */
*name = p;
while (!isspace(*p) && *p)
p++;
if (*p == '\0')
return (-1);
*p++ = '\0';
while (isspace(*p) && *p)
p++;
if (*p == '\0')
*pwd = (char *) 0;
else
*pwd = p; /* Assume no trailing whitespace. */
return (0);
} else { /* quoted name! YAY! */
while (*p && *p == '\"')
p++;
while (*p && isspace(*p))
p++;
if (*p == 0)
return (-1);
for (*name = p; *p && *p != '\"'; p++);
if (*p == 0)
return (-1);
/* found the other quote! */
*p++ = 0; /* terminate the name */
while (*p && isspace(*p))
p++;
if (*p == 0)
*pwd = (char *) 0;
else
*pwd = p;
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");
}
malloc_calls++;
malloc_total += n;
return (p);
}
/*
* Reliable free(), which does NULL OK.
*/
void ty_free(p)
char *p;
{
if (p == NULL) {
return; /* Ok */
}
malloc_free++;
free(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, '|') */
|| isspace(name[0]) || isspace(name[strlen(name) - 1]))
return (0);
else
return (1);
}
int ok_exit_name(name)
char *name;
{
char *p, *q, *buf;
if (!ok_name(name))
return (0);
#ifdef NO_ALLOCA
buf = (char *) ty_malloc(strlen(name) + 1, "ok_exit_name");
#else
buf = (char *) alloca(strlen(name) + 1);
#endif
(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)) {
#ifdef NO_ALLOCA
ty_free((char *) buf);
#endif
return (0);
}
q = p;
}
#ifdef NO_ALLOCA
ty_free((char *) buf);
#endif
return (1);
}
void fix_newline(buff)
char *buff;
{
register int i;
i = strlen(buff);
if (buff[i - 1] == '\n') {
buff[i - 1] = '\r';
buff[i] = '\n';
buff[i + 1] = '\0';
}
}
int domaincmp(x, y, i)
char *x;
char *y;
int i;
{
register char *p;
while (i) {
for (p = x; *p && *p != '.'; p++);
p++;
i--;
}
return (strcasecmp(p, y));
}
void announce_connect(player)
int player;
{
char *name;
char buf[80];
if (get_str_elt(player, NAME, &name) != -1) {
(void) sprintf(buf, "* %s has connected. *\r\n", name);
notify_wizz(buf);
}
}
void announce_disconnect(player)
int player;
{
char *name;
char buf[80];
if (get_str_elt(player, NAME, &name) != -1) {
(void) sprintf(buf, "* %s has disconnected. *\r\n", name);
notify_wizz(buf);
}
}
void check_last(player)
int player;
{
char *host, *time;
int last;
extern char *ctime();
extern char cmdwork[];
if (get_int_elt(player, TIMESTAMP, &last) == -1 ||
get_str_elt(player, SITE, &host) == -1)
return;
if (last == 0)
return;
time = ctime(&((long) last));
time[strlen(time) - 1] = 0;
(void) sprintf(cmdwork, "Last connection: %s from %s\r\n", time,
(host == NULL) ? "???" : host);
notify_player(player, cmdwork);
}
char *getname(obj)
int obj;
{
char *nm;
if (!exists_object(obj))
return (char *) NULL;
if (get_str_elt(obj, NAME, &nm) == -1)
return (char *) NULL;
return nm;
}