#include "copyright.h"
#include "config.h"
#include "db.h"
#include "params.h"
#include "interface.h"
#include "externs.h"
static char buf[BUFFER_LEN];
static hash_tab player_table[PLAYER_HASH_SIZE];
typedef struct player_match
{
char *name;
struct player_match *next;
dbref d;
} player_match;
static player_match *player_list = NULL, *pm, *pm_next;
dbref lookup_player(char *name)
{
dbref player = NOTHING;
hash_data *hd;
char *current, *next;
for(current = name; current; current = next)
{
next = (char *)strchr(current, EXIT_DELIMITER);
if (next)
{
strncpy(buf, current, next - current);
buf[next++ - current] = '\0';
}
else strcpy(buf, current);
if ((hd = find_hash(buf, player_table, PLAYER_HASH_SIZE)))
player = (player == NOTHING) ? hd->dbval : AMBIGUOUS;
}
return player;
}
dbref connect_player(char *name, char *password)
{
dbref player;
if((player = lookup_player(name)) == NOTHING) return NOTHING;
if(DBFETCH(player)->sp.player.password
&& *DBFETCH(player)->sp.player.password
&& check_password(password, player)) return NOTHING;
return player;
}
dbref create_player(char *name, char *password, dbref doer)
{
dbref player;
if(!ok_player_name(name, NOTHING) || !ok_password(password)) return NOTHING;
if(o_taboonames) {
if(doer == NOTHING)
if(!ok_taboo_name(NOTHING, name, 0)) return NOTHING;
else
if(!ok_taboo_name(NOTHING, name, 0) && !Wizard(doer)) return NOTHING;
}
/* else he doesn't already exist, create him */
player = new_object();
/* initialize everything */
NAME(player) = dup_string(name);
DBSTORE(player, location, PLAYER_START);
DBSTORE(player, link, PLAYER_START);
add_backlinks(player);
DBSTORE(player, nextowned, NOTHING);
#ifdef DEFAULT_PFLAGS
DBSTORE(player, flags, TYPE_PLAYER | DEFAULT_PFLAGS);
#else /* !DEFAULT_PFLAGS */
DBSTORE(player, flags, TYPE_PLAYER);
#endif /* DEFAULT_PFLAGS */
DBSTORE(player, owner, player);
DBSTORE(player, exits, NOTHING);
DBSTORE(player, pennies, DEFAULT_PENNIES);
DBSTORE(player, sp.player.password, dup_string(password));
DBSTORE(player, sp.player.password,
make_password(DBFETCH(player)->sp.player.password));
DBSTORE(player, curr_prog, NOTHING);
DBSTORE(player, sp.player.insert_mode, 0);
DBSTORE(player, sp.player.pid, 0);
/* link him to PLAYER_START */
PUSH(player, DBFETCH(PLAYER_START)->contents);
add_player(player);
DBDIRTY(PLAYER_START);
return player;
}
void do_password(__DO_PROTO)
{
/* nuke .last property */
add_property(player, ".last", "@password", PERMS_COREAD | PERMS_COWRITE,
ACCESS_CO);
if(!DBFETCH(player)->sp.player.password || check_password(arg1, player))
notify(player, player, "Sorry");
else if(!ok_password(arg2)) notify(player, player, "Bad new password.");
else
{
free(DBFETCH(player)->sp.player.password);
DBSTORE(player, sp.player.password, dup_string(arg2));
DBFETCH(player)->sp.player.password =
make_password(DBFETCH(player)->sp.player.password);
notify(player, player, "Password changed.");
}
}
/* nukes all player hashtable stuff */
void clear_players()
{
kill_hash(player_table, PLAYER_HASH_SIZE, 0);
for(pm = player_list; pm; pm = pm_next)
{
pm_next = pm->next;
free(pm->name);
free(pm);
}
}
void delete_player(dbref who)
{
player_match *pm, *pm_next;
char *current, *next;
for(current = NAME(who); current; current = next)
{
next = (char *)strchr(current, EXIT_DELIMITER);
if (next)
{
strncpy(buf, current, next - current);
buf[next++ - current] = '\0';
}
else strcpy(buf, current);
free_hash(buf, player_table, PLAYER_HASH_SIZE);
}
while(player_list && (player_list->d == who))
{
pm_next = player_list->next;
free(player_list->name);
free(player_list);
player_list = pm_next;
}
pm = player_list;
while (pm && pm->next)
{
while (pm && pm->next && (pm->next->d == who))
{
pm_next = pm->next;
pm->next = pm_next->next;
free(pm_next->name);
free(pm_next);
}
if(pm) pm = pm->next;
}
}
void add_player(dbref who)
{
hash_data hd;
char *current, *next;
for(current = NAME(who); current; current = next)
{
next = (char *)strchr(current, EXIT_DELIMITER);
if (next)
{
strncpy(buf, current, next - current);
buf[next++ - current] = '\0';
}
else strcpy(buf, current);
/* Will this work????? */
if(buf[0] == '\0') return;
pm = (player_match *)malloc(sizeof(player_match));
pm->d = who;
pm->name = dup_string(buf);
pm->next = player_list;
player_list = pm;
hd.dbval = who;
if(!add_hash(pm->name, hd, player_table, PLAYER_HASH_SIZE))
panic("Out of memory");
}
}
int awake_count(dbref player)
{
descriptor_data *d;
int retval = 0;
if (FLAGS(player) & DARK) return 0;
for(d = descriptor_list; d; d = d->next)
{
if (d->connected && d->player == player)
retval++;
}
return retval;
}
void do_player_setuid(__DO_PROTO)
{
descriptor_data *d;
dbref new_player;
/* nuke .last property */
add_property(player, ".last", "@user", PERMS_COREAD | PERMS_COWRITE,
ACCESS_CO);
new_player = lookup_player(arg1);
if (new_player == NOTHING)
{
notify(player, player, "Invalid player name. UID remains unchanged.");
return;
}
if (awake_count(player) != 1)
{
notify(player, player,
"Cannot set UID if you are connected more than once.");
log_status("UID CHANGE: From %s to %s FAILED, multiple connects.\n",
NAME(player), NAME(new_player));
return;
}
if (awake_count(new_player) != 0)
{
notify(player, player, "Cannot set UID to that of a connected player.");
log_status("UID CHANGE: From %s to %s FAILED, already connected.\n",
NAME(player), NAME(new_player));
return;
}
if((!DBFETCH(new_player)->sp.player.password
|| check_password(arg2, new_player))
&& !controls(player, new_player))
{
notify(player, player, "Permission denied.");
log_status("UID CHANGE: From %s to %s FAILED, BAD PASSWORD!!!\n",
NAME(player), NAME(new_player));
}
else
{
for(d = descriptor_list; d; d = d->next)
if (d->connected && d->player == player) d->player = new_player;
log_status("UID CHANGE: From %s to %s, successful.\n",
NAME(player),NAME(new_player));
notify(new_player, new_player, "UID changed.");
if(o_notify_wiz) {
/* tell wizards online that someone has setuid */
sprintf(buf, "%s has setuid to ", unparse_name(player));
strcat(buf, unparse_name(new_player));
strcat(buf, ".");
notify_wizards(buf);
}
}
return;
}