Mud20/accounts/
Mud20/accounts/c/
Mud20/accounts/f/
Mud20/accounts/k/
Mud20/accounts/s/
Mud20/accounts/t/
Mud20/area_current/
Mud20/area_current/newareas/
Mud20/bin/
Mud20/clans/
Mud20/gods/
Mud20/old-sources/
Mud20/player/
Mud20/player/a/del/
Mud20/player/b/
Mud20/player/b/bak/
Mud20/player/b/del/
Mud20/player/f/
Mud20/player/f/bak/
Mud20/player/f/del/
Mud20/player/k/
Mud20/player/k/bak/
Mud20/player/k/del/
Mud20/player/k/dmp/
Mud20/player/m/
Mud20/player/m/bak/
Mud20/player/o/
Mud20/player/o/bak/
Mud20/player/p/
Mud20/player/s/
Mud20/player/s/bak/
Mud20/player/s/del/
Mud20/player/t/
Mud20/player/t/del/
Mud20/player/v/
Mud20/public_html/
Mud20/races/
Mud20/skilltables/
__MACOSX/Mud20/accounts/
__MACOSX/Mud20/accounts/c/
__MACOSX/Mud20/accounts/f/
__MACOSX/Mud20/accounts/k/
__MACOSX/Mud20/accounts/s/
__MACOSX/Mud20/area_current/
__MACOSX/Mud20/area_current/core_areas/
__MACOSX/Mud20/area_current/helps/
__MACOSX/Mud20/area_current/newareas/
__MACOSX/Mud20/backups/
__MACOSX/Mud20/bin/
__MACOSX/Mud20/clans/
__MACOSX/Mud20/gods/
__MACOSX/Mud20/log/
__MACOSX/Mud20/old-sources/
__MACOSX/Mud20/player/
__MACOSX/Mud20/player/a/del/
__MACOSX/Mud20/player/b/
__MACOSX/Mud20/player/b/bak/
__MACOSX/Mud20/player/f/
__MACOSX/Mud20/player/f/bak/
__MACOSX/Mud20/player/f/del/
__MACOSX/Mud20/player/k/
__MACOSX/Mud20/player/k/bak/
__MACOSX/Mud20/player/k/del/
__MACOSX/Mud20/player/k/dmp/
__MACOSX/Mud20/player/m/
__MACOSX/Mud20/player/m/bak/
__MACOSX/Mud20/player/o/
__MACOSX/Mud20/player/o/bak/
__MACOSX/Mud20/player/p/
__MACOSX/Mud20/player/s/
__MACOSX/Mud20/player/s/bak/
__MACOSX/Mud20/player/t/del/
__MACOSX/Mud20/player/v/
__MACOSX/Mud20/public_html/
__MACOSX/Mud20/races/
__MACOSX/Mud20/skilltables/
/***************************************************************************
 * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming   *
 * License by Wizards of the Coast. All comments referring to D20, OGL,    *
 * and SRD refer to the System Reference Document for the Open Gaming      *
 * system. Any inclusion of these derivatives must include credit to the   *
 * Mud20 system, the full and complete Open Gaming LIcense, and credit to  *
 * the respective authors. See ../doc/srd.txt for more information.        *
 *                                                                         *
 * Emud  2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem.   *
 *                                                                         *
 * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey                *
 *                                                                         *
 * Merc  2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael      *
 * Chastain, Michael Quan, and Mitchell Tse.                               *
 *                                                                         *
 * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe.     *
 ***************************************************************************/

/***************************************************************************
 * new_auth.c: Control authorization of new player names, and descs			   *
 ***************************************************************************/
/*
 *  New name authorization system
 *  Author: Rantic (supfly@geocities.com)
 *  of FrozenMUD (empire.digiunix.net 4000)
 *
 *  Permission to use and distribute this code is granted provided
 *  this header is retained and unaltered, and the distribution
 *  package contains all the original files unmodified.
 *  If you modify this code and use/distribute modified versions
 *  you must give credit to the original author(s).
 */

#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>
#include "mud.h"

AUTH_LIST *first_auth_name;
AUTH_LIST *last_auth_name;

void free_auth_entry (AUTH_LIST * auth)
{
	UNLINK (auth, first_auth_name, last_auth_name, next, prev);
	STRFREE (auth->adjective);
	STRFREE (auth->descr);
	STRFREE (auth->authed_by);
	STRFREE (auth->change_by);
	STRFREE (auth->name);
	FREEMEM (auth);
}

void free_all_auths (void)
{
	AUTH_LIST *auth, *auth_next;

	for (auth = first_auth_name; auth; auth = auth_next)
	{
		auth_next = auth->next;
		free_auth_entry (auth);
	}
	return;
}

void clean_auth_list (void)
{
	AUTH_LIST *auth, *nauth;

	for (auth = first_auth_name; auth; auth = nauth)
	{
		nauth = auth->next;

		if (!char_exists (auth->name))
			free_auth_entry (auth);
		else
		{
			time_t tdiff = 0;
			time_t curr_time = time (0);
			struct stat fst;
			char file[256], name[MAX_STRING_LENGTH];

			strncpy (name, auth->name, MAX_STRING_LENGTH);
			snprintf (file, 256, "%s/%c/%s", PLAYER_DIR, tolower(auth->name[0]), capitalize_name(auth->name));

			if (stat (file, &fst) != -1)
				tdiff = (curr_time - fst.st_mtime) / 86400;
			else
				bug ("File %s does not exist!", file);

			if (tdiff > MAX_AUTH_WAIT)
			{
				if (unlink (file) == -1)
					perror ("Unlink: do_auth: \"clean\"");
				else
				{
					log_printf ("%s deleted for inactivity: %ld days", file, (long int)tdiff);
				}
			}
		}
	}
}

void write_auth_file (FILE * fpout, AUTH_LIST * list)
{
	fprintf (fpout, "Name     %s~\n", list->name);
	fprintf (fpout, "State    %d\n", list->state);
	fprintf (fpout, "Sex      %d\n", list->sex);
	fprintf (fpout, "Race     %d\n", list->race);
	fprintf (fpout, "Pvnum    %d\n", list->pvnum);
	if (list->adjective)
		fprintf (fpout, "Adject   %s~\n", list->adjective);
	if (list->descr)
		fprintf (fpout, "Descr   %s~\n", fixer(list->descr));
	if (list->authed_by)
		fprintf (fpout, "AuthedBy %s~\n", list->authed_by);
	if (list->change_by)
		fprintf (fpout, "Change   %s~\n", list->change_by);
	fprintf (fpout, "%s", "End\n\n");
}

AUTH_LIST *fread_auth (FILE * fp)
{
	AUTH_LIST *new_auth;
	bool fMatch;
	const char *word;

	ALLOCMEM (new_auth, AUTH_LIST, 1);

	new_auth->authed_by = NULL;
	new_auth->change_by = NULL;

	for (;;)
	{
		word = feof (fp) ? "End" : fread_word (fp);
		fMatch = FALSE;
		switch (UPPER (word[0]))
		{
			case '*':
				fMatch = TRUE;
				fread_to_eol (fp);
				break;

			case 'A':
				SKEY ("AuthedBy", new_auth->authed_by, fread_string (fp));
				SKEY ("Adject", new_auth->adjective, fread_string (fp));
				break;

			case 'C':
				SKEY ("Change", new_auth->change_by, fread_string (fp));
				break;

			case 'D':
				SKEY ("Descr", new_auth->descr, fread_string (fp));
				break;

			case 'E':
				if (!strcasecmp (word, "End"))
				{
					LINK (new_auth, first_auth_name, last_auth_name, next, prev);
					return new_auth;
				}
				break;

			case 'N':
				SKEY ("Name", new_auth->name, fread_string (fp));
				break;

			case 'P':
				NKEY ("Pvnum", new_auth->pvnum, fread_number (fp));
				break;

			case 'R':
				NKEY ("Race", new_auth->race, fread_number (fp));
				break;

			case 'S':
				NKEY ("Sex", new_auth->sex, fread_number (fp));
				if (!strcasecmp (word, "State"))
				{
					new_auth->state = fread_number (fp);
					/*
					 * Crash proofing. Can't be online when 
					 * booting up. Would suck for do_auth	
					 */
					if (new_auth->state == AUTH_ONLINE || new_auth->state == AUTH_LINK_DEAD)
						new_auth->state = AUTH_OFFLINE;
					fMatch = TRUE;
					break;
				}
				break;
		}
		if (!fMatch)
			bug ("%s: no match: %s", __FUNCTION__, word);
	}
}

void save_auth_list (void)
{
	FILE *fpout;
	AUTH_LIST *list;

	close_reserve();

	if ((fpout = my_fopen (AUTH_FILE, "w", FALSE)) == NULL)
	{
		bug ("%s", "Cannot open auth.dat for writing.");
		perror (AUTH_FILE);
		open_reserve();
		return;
	}

	for (list = first_auth_name; list; list = list->next)
	{
		fprintf (fpout, "%s", "#AUTH\n");
		write_auth_file (fpout, list);
	}

	fprintf (fpout, "%s", "#END\n");
	my_fclose (fpout);
	fpout = NULL;
	
	open_reserve();
}

void clear_auth_list (void)
{
	AUTH_LIST *auth, *nauth;

	for (auth = first_auth_name; auth; auth = nauth)
	{
		nauth = auth->next;

		if (!char_exists (auth->name))
			free_auth_entry (auth);
	}
	save_auth_list (	);
}

void load_auth_list (void)
{
	FILE *fp;
	int x;

	first_auth_name = last_auth_name = NULL;

	close_reserve();

	if ((fp = my_fopen (AUTH_FILE, "r", FALSE)) != NULL)
	{
		x = 0;
		for (;;)
		{
			char letter;
			char *word;

			letter = fread_letter (fp);
			if (letter == '*')
			{
				fread_to_eol (fp);
				continue;
			}

			if (letter != '#')
			{
				bug ("%s", "Load_auth_list: # not found.");
				break;
			}

			word = fread_word (fp);
			if (!strcasecmp (word, "AUTH"))
			{
				fread_auth (fp);
				continue;
			}
			else if (!strcasecmp (word, "END"))
				break;
			else
			{
				bug ("%s", "load_auth_list: bad section.");
				continue;
			}
		}
		my_fclose (fp);
		fp = NULL;
	}
	else
	{
		bug ("%s", "Cannot open auth.dat");
		open_reserve();
		return;
	}
	clear_auth_list (	);
	open_reserve();
}

int get_auth_state (CHAR_DATA * ch)
{
	AUTH_LIST *namestate;
	int state;

	state = AUTH_AUTHED;

	for (namestate = first_auth_name; namestate; namestate = namestate->next)
	{
		if (!strcasecmp (namestate->name, ch->name))
		{
			state = namestate->state;
			break;
		}
	}
	return state;
}

AUTH_LIST *get_auth_name (char *name)
{
	AUTH_LIST *mname;

	if (last_auth_name && last_auth_name->next != NULL)
		bug ("Last_auth_name->next != NULL: %s", last_auth_name->next->name);

	for (mname = first_auth_name; mname; mname = mname->next)
	{
		if (!strcasecmp (mname->name, name)) /* If the name is already in the list, break */
			break;
	}
	return mname;
}

void add_to_auth (CHAR_DATA * ch)
{
	AUTH_LIST *new_name;
	DESCRIPTOR_DATA *d;
	char log_buf[MAX_INPUT_LENGTH];

	new_name = get_auth_name (ch->name);

	if (new_name != NULL)
		return;
	else
	{
		ALLOCMEM (new_name, AUTH_LIST, 1);
		new_name->name = STRALLOC (ch->name);
		new_name->sex = ch->sex;
		new_name->race = ch->race;
		new_name->pvnum = ch->pcdata->pvnum;
		if (ch->pcdata->adjective && ch->pcdata->adjective[0] != '\0')
			new_name->adjective = STRALLOC (ch->pcdata->adjective);
		if (ch->description && ch->description[0] != '\0')
			new_name->descr = STRALLOC(ch->description);
		new_name->state = AUTH_ONLINE;	/* Just entered the game */
		LINK (new_name, first_auth_name, last_auth_name, next, prev);
		save_auth_list (	);

		sprintf(log_buf, "{200}AUTH: {178}%s {300}is now awaiting authorization.\n\r", ch->name);
		for (d = mud->f_desc; d; d = d->next)
			if (d->connected == CON_PLAYING && d->character && IS_IMMORTAL(d->character))
				send_to_char_color(log_buf, d->character);
	}
}

void remove_from_auth (char *name)
{
	AUTH_LIST *old_name;

	old_name = get_auth_name (name);
	if (old_name == NULL)	/* Its not old */
		return;
	else
	{
		free_auth_entry (old_name);
		save_auth_list (	);
	}
}

void check_auth_state (CHAR_DATA * ch)
{
	AUTH_LIST *old_auth;
	char colY[10], colR[10], colW[10], colw[10];

	old_auth = get_auth_name (ch->name);
	if (old_auth == NULL)
		return;
		
	strcpy(colY, ansi_translate("{138}"));
	strcpy(colR, ansi_translate("{118}"));
	strcpy(colW, ansi_translate("{178}"));
	strcpy(colw, ansi_translate("{078}"));

	if (!ch->pcdata->adjective || ch->pcdata->adjective[0] == '\0')
	{
		ch_printf_color (ch,
								"%s\r\nYou have not yet set your adjective. You cannot be\r\n"
								"authorized until you set one. See HELP ADJECTIVE.\r\n", colR);
	}
	if (!ch->description || ch->description[0] == '\0')
	{
		ch_printf_color (ch,
								"%s\r\nYou have not yet set your description. You cannot be\r\n"
								"authorized until you write one. See HELP DESC.\r\n", colR);
	}

	if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_CHNG_NAME))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have found your name\r\n"
								"to be unacceptable. You must set a new one. See HELP NAME.\r\n", colR);
	}
	else if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_AUTH_NAME))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have not yet authorized your name\r\n"
								"It will have to be authorized before you can enter the realms.\r\n", colR);
	}
	else if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_UNAUTHED))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have authorised the name %s\r\n", colY, ch->name);
	}

	if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_CHNG_ADJ))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have found your adjective\r\n"
								"to be unacceptable. You must set a new one. See HELP ADJECTIVE.\r\n", colR);
	}
	else if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_AUTH_ADJ))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have not yet authorized your adjective\r\n"
								"It will have to be authorized before you can enter the realms.\r\n", colR);
	}
	else if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_UNAUTHED))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have authorised your adjective.\r\n", colY);
	}

	if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_CHNG_DESC))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have found your description to\r\n"
								"be unacceptable. You must set a new one. See HELP DESC.\r\n", colR);
	}
	else if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_AUTH_ADJ))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have not yet authorized your description.\r\n", colR);
	}
	else if (IS_SET(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_UNAUTHED))
	{
		ch_printf_color (ch,
								"%s\r\nThe MUD Administrators have authorised your description.\r\n", colY);
	}

	if (old_auth->state == AUTH_OFFLINE /* checking as they enter the game */
		 || old_auth->state == AUTH_LINK_DEAD)
	{
		old_auth->state = AUTH_ONLINE;
		save_auth_list (	);
	}
	else if (old_auth->state == AUTH_AUTHED)
	{
		if (ch->pcdata->authed_by)
			STRFREE (ch->pcdata->authed_by);
		if (old_auth->authed_by)
		{
			ch->pcdata->authed_by = STRALLOC (old_auth->authed_by);
			STRFREE (old_auth->authed_by);
		}
		else
			ch->pcdata->authed_by = STRALLOC ("The Code");

		ch_printf_color (ch,
								"\r\n{138}The MUD Administrators have authorized you.\r\n"
								"You are now free to roam the realms.\r\n");
		REMOVE_BIT(pvnum_index[ch->pcdata->pvnum]->flags, PVNUM_UNAUTHED);
		remove_from_auth (ch->name);
		return;
	}
	return;
}

/* new auth */
void do_authorize (CHAR_DATA * ch, char *argument)
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	char buf[MAX_STRING_LENGTH];
	char buf2[MAX_STRING_LENGTH];
	char colc[10], colw[10], colW[10];
	CHAR_DATA *victim = NULL;
	AUTH_LIST *auth;
	bool offline, authed, change, pending;
	int states = 0;
	
	strcpy(colc, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));

	offline = authed = change = pending = FALSE;
	auth = NULL;

	argument = one_argument (argument, arg1);
	argument = one_argument (argument, arg2);
	argument = one_argument (argument, arg3);

	if (arg1[0] == '\0')
	{
		ch_printf_color (ch, "%sSyntax:\r\n", colc);
		ch_printf_color (ch, "%s  Approve a character fully:     auth <name> accept\r\n", colw);
		ch_printf_color (ch, "%s  Deny and delete a character:   auth <name> reject\r\n", colw);
		ch_printf_color (ch, "%s  To review a character:         auth <name> review\r\n", colw);
		ch_printf_color (ch, "%s  Authorize a character's name:  auth <name> name <accept|change>\r\n", colw);
		ch_printf_color (ch, "%s  Authorize a character's adj:   auth <name> adj  <accept|change>\r\n", colw);
		ch_printf_color (ch, "%s  Authorize a character's desc:  auth <name> desc <accept|change>\r\n", colw);
		ch_printf_color (ch, "%s  Verify the list:               auth fixlist\r\n", colw);
		ch_printf_color (ch, "%s  Purge inactive entries:        auth clean\r\n", colw);

		ch_printf_color(ch, "\r\n%sCharacters awaiting approval%s\r\n", colc, colw);

		for (auth = first_auth_name; auth; auth = auth->next)
		{
			states = pvnum_index[auth->pvnum]->flags;

			if (IS_SET(states, PVNUM_CHNG_NAME|PVNUM_CHNG_ADJ|PVNUM_CHNG_DESC))
				change = TRUE;
			else if (auth->state == AUTH_AUTHED)
				authed = TRUE;

			if (auth->name != NULL && IS_SET(states, PVNUM_AUTH_NAME|PVNUM_AUTH_ADJ|PVNUM_AUTH_DESC))
				pending = TRUE;

		}
		if (pending)
		{
			for (auth = first_auth_name; auth; auth = auth->next)
			{
				states = pvnum_index[auth->pvnum]->flags;

				if (auth->name != NULL && IS_SET(states, PVNUM_AUTH_NAME|PVNUM_AUTH_ADJ|PVNUM_AUTH_DESC))
				{
					if (!auth->adjective || auth->adjective[0] == '\0')
						sprintf(buf, "  %s%s, %sa %s %s (Adjective not yet set)", colW, auth->name, colw, sex_types[auth->sex], race_table[auth->race].race_name);
					else
						sprintf(buf, "  %s%s, %sa %s %s %s", colW, auth->name, colw, auth->adjective, sex_types[auth->sex], race_table[auth->race].race_name);
					str_resize(buf, buf2, -64);
					switch (auth->state)
					{
						default:
							ch_printf_color (ch, "%-64s %sStatus: %sUnknown?\n\r", buf, colW, colw);
							break;
						case AUTH_LINK_DEAD:
							ch_printf_color (ch, "%-64s %sStatus: %sLink Dead\n\r", buf, colW, colw);
							break;
						case AUTH_ONLINE:
							ch_printf_color (ch, "%-64s %sStatus: %sOnline\n\r", buf, colW, colw);
							break;
						case AUTH_OFFLINE:
							ch_printf_color (ch, "%-64s %sStatus: %sOffline\n\r", buf, colW, colw);
							break;
					}
				}
			}
		}
		else
			send_to_char ("  None\r\n", ch);

		if (authed)
		{
			ch_printf_color (ch, "\r\n%sAuthorized Characters:\r\n", colc);
			for (auth = first_auth_name; auth; auth = auth->next)
			{
				if (auth->state == AUTH_AUTHED)
					ch_printf_color (ch, "  Name: %-15s  Approved by: %s\r\n", auth->name, auth->authed_by);
			}
		}
		if (change)
		{
			ch_printf_color (ch, "\r\n%sChange:\r\n", colc);
			for (auth = first_auth_name; auth; auth = auth->next)
			{
				states = pvnum_index[auth->pvnum]->flags;

				if (IS_SET(states, PVNUM_CHNG_NAME|PVNUM_CHNG_ADJ|PVNUM_CHNG_DESC))
					ch_printf_color (ch, "  Name: %s, a %s %s %s - Change:%s%s%s  Requested: %s\r\n",
							auth->name, auth->adjective, sex_types[auth->sex], race_table[auth->race].race_name,
							IS_SET(states, PVNUM_CHNG_NAME) ? " N" : "", IS_SET(states, PVNUM_CHNG_DESC) ? " D" : "",
							IS_SET(states, PVNUM_CHNG_ADJ) ? " A" : "", auth->change_by);
			}
		}
		return;
	}

	if (!strcasecmp (arg1, "fixlist"))
	{
		send_to_char ("Checking authorization list...\r\n", ch);
		clear_auth_list (	);
		send_to_char ("Done.\r\n", ch);
		return;
	}

	if (!strcasecmp (arg1, "clean"))
	{
		send_to_char ("Cleaning authorization list...\r\n", ch);
		clean_auth_list (	);
		send_to_char ("Checking authorization list...\r\n", ch);
		clear_auth_list (	);
		send_to_char ("Done.\r\n", ch);
		return;
	}

	auth = get_auth_name (arg1);

	if (auth != NULL)
	{
		if (!auth->adjective || auth->adjective[0] == '\0')
		{
			ch_printf_color (ch, "You cannot authorize %s until they set an adjective.\r\n", auth->name);
			return;
		}
		if (auth->state == AUTH_OFFLINE || auth->state == AUTH_LINK_DEAD)
		{
			offline = TRUE;

			if (arg2[0] == '\0')
			{
				do_authorize(ch, "");
			}
			else if (!strcasecmp (arg2, "accept") || !strcasecmp (arg2, "yes"))
			{
				if (IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_NAME))
				{
					ch_printf_color (ch, "The name %s has already been rejected.\r\n", auth->name);
					return;
				}
				if (IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_ADJ))
				{
					ch_printf_color (ch, "%s's adjective has already been rejected.\r\n", auth->name);
					return;
				}
				if (IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_DESC))
				{
					ch_printf_color (ch, "%s's description has already been rejected.\r\n", auth->name);
					return;
				}
				auth->state = AUTH_AUTHED;
				STRFREE(auth->authed_by);
				auth->authed_by = STRALLOC (ch->name);
				save_auth_list (	);
				REMOVE_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_UNAUTHED);
				snprintf (buf, MAX_STRING_LENGTH, "%s: authorized", auth->name);
				log_printf (buf);
				ch_printf_color (ch, "You have authorized %s.\r\n", auth->name);
			}
			else if (!strcasecmp (arg2, "reject"))
			{
				snprintf (buf, MAX_STRING_LENGTH, "%s: denied authorization", auth->name);
				log_printf (buf);
				ch_printf_color (ch, "You have denied %s.\r\n", auth->name);
// 				/*
// 				 * Addition so that denied names get added to reserved list - Samson 10-18-98 
// 				 */
// 				snprintf (buf, MAX_STRING_LENGTH, "%s add", auth->name);
// 				do_reserve (ch, buf);	/* Samson 7-27-98 */
				do_destroy (ch, auth->name);
			}
			else if (!strcasecmp (arg2, "review"))
			{
				if (!auth->adjective || auth->adjective[0] == '\0')
					sprintf(buf, "%s%s, %sa %s %s (Adjective not yet set)\n\r", colW, auth->name, colw, sex_types[auth->sex], race_table[auth->race].race_name);
				else
					sprintf(buf, "%s%s, %sa %s %s %s\n\r", colW, auth->name, colw, auth->adjective, sex_types[auth->sex], race_table[auth->race].race_name);
				if (!auth->descr || auth->descr[0] == '\0')
					cat_sprintf(buf, "%s(Description not yet set)\n\r", colw);
				else
					cat_sprintf(buf, "%sDescription:\n\r%s%s%s", colc, colw, auth->descr, colw);
				send_to_char(buf, ch);
			}
			else if (!strcasecmp (arg2, "name"))
			{
				if (arg3[0] == '\0')
				{
					send_to_char("Syntax: auth <name> name <accept|change>\n\r", ch);
					return;
				}
				if (!IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_NAME)
				&& !IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_NAME))
				{
					ch_printf_color (ch, "The name %s has already been accepted.\r\n", auth->name);
					return;
				}
				if (!strcasecmp(arg3, "change"))
				{
					STRFREE(auth->change_by)
					auth->change_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_NAME);
					SET_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_NAME);
					snprintf (buf, MAX_STRING_LENGTH, "%s: name denied", auth->name);
					log_printf (buf);
					ch_printf_color (ch, "You requested %s to change names.\r\n", auth->name);
				}
				else if (!strcasecmp(arg3, "accept"))
				{
					if (IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_NAME))
					{
						ch_printf_color (ch, "The name %s has already been rejected.\r\n", auth->name);
						return;
					}
					STRFREE(auth->authed_by);
					auth->authed_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_NAME);
					snprintf (buf, MAX_STRING_LENGTH, "%s: name accepted", auth->name);
					log_printf (buf);
					ch_printf_color (ch, "You authorized the name %s.\r\n", auth->name);
				}
			}
			else if (!strcasecmp (arg2, "adj"))
			{
				if (arg3[0] == '\0')
				{
					send_to_char("Syntax: auth <name> adj <accept|change>\n\r", ch);
					return;
				}
				if (!IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_ADJ)
				&& !IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_ADJ))
				{
					ch_printf_color (ch, "The adjective has already been accepted.\r\n");
					return;
				}
				if (!strcasecmp(arg3, "change"))
				{
					STRFREE(auth->change_by)
					auth->change_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_ADJ);
					SET_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_ADJ);
					snprintf (buf, MAX_STRING_LENGTH, "%s: adjective denied", auth->name);
					log_printf (buf);
					ch_printf_color (ch, "You requested %s change their adjective.\r\n", auth->name);
				}
				else if (!strcasecmp(arg3, "accept"))
				{
					if (IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_ADJ))
					{
						ch_printf_color (ch, "%s's adjective has already been rejected.\r\n", auth->name);
						return;
					}
					STRFREE(auth->authed_by);
					auth->authed_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_ADJ);
					snprintf (buf, MAX_STRING_LENGTH, "%s: adjective accepted", auth->name);
					log_printf (buf);
					ch_printf_color (ch, "You authorized %s's adjective.\r\n", auth->name);
				}
			}
			else if (!strcasecmp (arg2, "desc"))
			{
				if (arg3[0] == '\0')
				{
					send_to_char("Syntax: auth <name> desc <accept|change>\n\r", ch);
					return;
				}
				if (!IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_DESC)
				&& !IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_DESC))
				{
					ch_printf_color (ch, "The description has already been accepted.\r\n");
					return;
				}
				if (!strcasecmp(arg3, "change"))
				{
					STRFREE(auth->change_by)
					auth->change_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_DESC);
					SET_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_DESC);
					snprintf (buf, MAX_STRING_LENGTH, "%s: description denied", auth->name);
					log_printf (buf);
					ch_printf_color (ch, "You requested %s change their description.\r\n", auth->name);
				}
				else if (!strcasecmp(arg3, "accept"))
				{
					if (IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_DESC))
					{
						ch_printf_color (ch, "%s's description has already been rejected.\r\n", auth->name);
						return;
					}
					STRFREE(auth->authed_by);
					auth->authed_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_DESC);
					snprintf (buf, MAX_STRING_LENGTH, "%s: description accepted", auth->name);
					log_printf (buf);
					ch_printf_color (ch, "You authorized %s's description.\r\n", auth->name);
				}
			}
			else
			{
				send_to_char ("Invalid argument.\r\n", ch);
			}
			if (!IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_UNAUTHED))
			{
				auth->state = AUTH_AUTHED;
				STRFREE(auth->authed_by);
				auth->authed_by = STRALLOC (ch->name);
				save_auth_list (	);
			}
		}
		else
		{
			if ((victim = get_char_pvnum(auth->pvnum)) == NULL)
			{
				send_to_char ("There is no such character waiting for authorization.\r\n", ch);
			}
			if (arg2[0] == '\0')
			{
				do_authorize(ch, "");
			}
			else if (!strcasecmp (arg2, "accept") || !strcasecmp (arg2, "yes"))
			{
				if (IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_NAME))
				{
					ch_printf_color (ch, "The name %s has already been rejected.\r\n", auth->name);
					return;
				}
				if (IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_ADJ))
				{
					ch_printf_color (ch, "%s's adjective has already been rejected.\r\n", auth->name);
					return;
				}
				if (IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_DESC))
				{
					ch_printf_color (ch, "%s's description has already been rejected.\r\n", auth->name);
					return;
				}
				if (victim->pcdata->authed_by)
					STRFREE (victim->pcdata->authed_by);
				victim->pcdata->authed_by = STRALLOC (ch->name);
				snprintf (buf, MAX_STRING_LENGTH, "%s: authorized", victim->name);
				log_printf (buf);
				REMOVE_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_UNAUTHED);
				ch_printf_color (ch, "You have authorized %s.\r\n", victim->name);

				ch_printf_color (victim,
										"\r\n{138}The MUD Administrators have authorized you.\r\n"
										"You are now free to roam the realms.{300}\r\n");
				remove_from_auth (victim->name);
			}
			else if (!strcasecmp (arg2, "reject"))
			{
				send_to_char ("{118}You have been denied access.\r\n", victim);
				snprintf (buf, MAX_STRING_LENGTH, "%s: denied authorization", auth->name);
				log_printf (buf);
				ch_printf_color (ch, "You have denied %s.\r\n", victim->name);
				remove_from_auth (victim->name);
				sprintf(buf, "player %s", victim->name);
				do_destroy (ch, buf);
			}
			else if (!strcasecmp (arg2, "review"))
			{
				if (!victim->pcdata->adjective || victim->pcdata->adjective[0] == '\0')
					sprintf(buf, "%s%s, %sa %s %s (Adjective not yet set)\n\r", colW, victim->name, colw, sex_types[victim->sex], race_table[victim->race].race_name);
				else
					sprintf(buf, "%s%s, %sa %s %s %s\n\r", colW, victim->name, colw, victim->pcdata->adjective, sex_types[victim->sex], race_table[victim->race].race_name);
				if (!victim->description || victim->description[0] == '\0')
					cat_sprintf(buf, "%s(Description not yet set)\n\r", colw);
				else
					cat_sprintf(buf, "%sDescription:\n\r%s%s%s", colc, colw, victim->description, colw);
				send_to_char(buf, ch);
			}
			else if (!strcasecmp (arg2, "name"))
			{
				if (arg3[0] == '\0')
				{
					send_to_char("Syntax: auth <name> name <accept|change>\n\r", ch);
					return;
				}
				if (!IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_NAME)
				&& !IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_CHNG_NAME))
				{
					ch_printf_color (ch, "The name %s has already been accepted.\r\n", auth->name);
					return;
				}
				if (!strcasecmp(arg3, "change"))
				{
					STRFREE(auth->change_by)
					auth->change_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_AUTH_NAME);
					SET_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_NAME);
					snprintf (buf, MAX_STRING_LENGTH, "%s: name denied", auth->name);
					log_printf (buf);
					ch_printf_color (victim,
											"{118}\r\nThe MUD Administrators have found your adjective to be\r\n"
											"unacceptable. You must set a new one. See HELP NAME.{300}\r\n");
					ch_printf_color (ch, "You requested %s change names.\r\n", victim->name);
				}
				else if (!strcasecmp(arg3, "accept"))
				{
					if (IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_NAME))
					{
						ch_printf_color (ch, "The name %s has already been rejected.\r\n", auth->name);
						return;
					}
					STRFREE(auth->authed_by);
					auth->authed_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_AUTH_NAME);
					snprintf (buf, MAX_STRING_LENGTH, "%s: name accepted", victim->name);
					log_printf (buf);
					ch_printf_color (ch, "You authorized the name %s.\r\n", victim->name);
				}
			}
			else if (!strcasecmp (arg2, "adj"))
			{
				if (arg3[0] == '\0')
				{
					send_to_char("Syntax: auth <name> adj <accept|change>\n\r", ch);
					return;
				}
				if (!IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_AUTH_ADJ)
				&& !IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_ADJ))
				{
					ch_printf_color (ch, "The adjective has already been accepted.\r\n");
					return;
				}
				if (!strcasecmp(arg3, "change"))
				{
					STRFREE(auth->change_by)
					auth->change_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_AUTH_ADJ);
					SET_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_ADJ);
					snprintf (buf, MAX_STRING_LENGTH, "%s: adjective denied", victim->name);
					log_printf (buf);
					ch_printf_color (victim,
											"{118}\r\nThe MUD Administrators have found your adjective to be\r\n"
											"unacceptable. You must set a new one. See HELP ADJECTIVE.{300}\r\n");
					ch_printf_color (ch, "You requested %s change their adjective.\r\n", victim->name);
				}
				else if (!strcasecmp(arg3, "accept"))
				{
					if (IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_ADJ))
					{
						ch_printf_color (ch, "%s's adjective has already been rejected.\r\n", victim->name);
						return;
					}
					STRFREE(auth->authed_by);
					auth->authed_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_AUTH_ADJ);
					snprintf (buf, MAX_STRING_LENGTH, "%s: adjective accepted", victim->name);
					log_printf (buf);
					ch_printf_color (ch, "You authorized %s's adjective.\r\n", victim->name);
				}
			}
			else if (!strcasecmp (arg2, "desc"))
			{
				if (arg3[0] == '\0')
				{
					send_to_char("Syntax: auth <name> desc <accept|change>\n\r", ch);
					return;
				}
				if (!IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_AUTH_DESC)
				&& !IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_DESC))
				{
					ch_printf_color (ch, "The description has already been accepted.\r\n");
					return;
				}
				if (!strcasecmp(arg3, "change"))
				{
					STRFREE(auth->change_by)
					auth->change_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_AUTH_DESC);
					SET_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_DESC);
					snprintf (buf, MAX_STRING_LENGTH, "%s: description denied", victim->name);
					log_printf (buf);
					ch_printf_color (victim,
											"{118}\r\nThe MUD Administrators have found your description to be\r\n"
											"unacceptable. You must set a new one. See HELP DESC.{300}\r\n");
					ch_printf_color (ch, "You requested %s change their description.\r\n", victim->name);
				}
				else if (!strcasecmp(arg3, "accept"))
				{
					if (IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_CHNG_DESC))
					{
						ch_printf_color (ch, "%s's description has already been rejected.\r\n", victim->name);
						return;
					}
					STRFREE(auth->authed_by);
					auth->authed_by = STRALLOC (ch->name);
					save_auth_list();
					REMOVE_BIT(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_AUTH_DESC);
					snprintf (buf, MAX_STRING_LENGTH, "%s: description accepted", victim->name);
					log_printf (buf);
					ch_printf_color (ch, "You authorized %s's description.\r\n", victim->name);
				}
			}
			else
			{
				send_to_char ("Invalid argument.\r\n", ch);
			}
			if (!IS_SET(pvnum_index[victim->pcdata->pvnum]->flags, PVNUM_UNAUTHED))
			{
				if (victim->pcdata->authed_by)
					STRFREE (victim->pcdata->authed_by);
				victim->pcdata->authed_by = STRALLOC (ch->name);
				ch_printf_color (victim,
										"\r\n{138}The MUD Administrators have authorized you.\r\n"
										"You are now free to roam the realms.{300}\r\n");
				remove_from_auth (victim->name);
			}
		}
		save_players();
	}
	else
	{
		send_to_char ("No such player pending authorization.\r\n", ch);
		return;
	}
}

/* changed for new auth */
void auth_update (void)
{
	AUTH_LIST *auth;
	char buf[MAX_INPUT_LENGTH];
	char buf2[MAX_INPUT_LENGTH];
	char log_buf[MAX_INPUT_LENGTH];
	DESCRIPTOR_DATA *d;
	CHAR_DATA *victim;
	int level = LEVEL_IMMORTAL;
	char colc[10], colw[10], colW[10];
	bool found_hit = FALSE; /* was at least one found? */
	
	strcpy(colc, "{200}");
	strcpy(colw, "{078}");
	strcpy(colW, "{178}");

	sprintf(log_buf, "\r\n%sCharacters awaiting approval%s\r\n", colc, colw);
	for (auth = first_auth_name; auth; auth = auth->next)
	{
		if (auth != NULL && IS_SET(pvnum_index[auth->pvnum]->flags, PVNUM_AUTH_NAME|PVNUM_AUTH_ADJ|PVNUM_AUTH_DESC))
		{
			found_hit = TRUE;

			if (!auth->adjective || auth->adjective[0] == '\0')
				sprintf(buf, "  %s%s, %sa %s %s (Adjective not yet set)", colW, auth->name, colw, race_table[auth->race].race_name, sex_types[auth->sex]);
			else
				sprintf(buf, "  %s%s, %sa %s %s %s", colW, auth->name, colw, auth->adjective, sex_types[auth->sex], race_table[auth->race].race_name);
			str_resize(buf, buf2, -64);

			switch (auth->state)
			{
				default:
					cat_sprintf (log_buf, "%-64s %sStatus: %sUnknown?\n\r", buf, colW, colw);
					break;
				case AUTH_LINK_DEAD:
					cat_sprintf (log_buf, "%-64s %sStatus: %sLink Dead\n\r", buf, colW, colw);
					break;
				case AUTH_ONLINE:
					cat_sprintf (log_buf, "%-64s %sStatus: %sOnline\n\r", buf, colW, colw);
					break;
				case AUTH_OFFLINE:
					cat_sprintf (log_buf, "%-64s %sStatus: %sOffline\n\r", buf, colW, colw);
					break;
			}
			if ((victim = get_char_pvnum(auth->pvnum)) != NULL)
			{
				if (!victim->pcdata->adjective || victim->pcdata->adjective[0] == '\0')
				{
					ch_printf_color (victim,
											"{118}\r\nYou have not yet set your adjective. You cannot be\r\n"
											"authorized until you set one. See HELP ADJECTIVE.{300}\r\n");
				}
			}	
		}
	}
	if (found_hit)
	{
		for (d = mud->f_desc; d; d = d->next)
			if (d->connected == CON_PLAYING && d->character && IS_IMMORTAL (d->character) && d->character->level >= level)
				send_to_char_color(log_buf, d->character);
	}
}

// void save_reserved args ( (void));
// void sort_reserved args ( (RESERVE_DATA * pRes));
// 
// /* Modified to require an "add" or "remove" argument in addition to name - Samson 10-18-98 */
// void do_reserve (CHAR_DATA * ch, char *argument)
// {
// 	char arg[MAX_INPUT_LENGTH];
// 	char arg2[MAX_INPUT_LENGTH];
// 	RESERVE_DATA *res;
// 
// 	set_char_color (AT_PLAIN, ch);
// 
// 	argument = one_argument (argument, arg);
// 	argument = one_argument (argument, arg2);
// 
// 	if (!*arg)
// 	{
// 		int wid = 0;
// 
// 		send_to_char ("To add a name: reserve <name> add\r\nTo remove a name: reserve <name> remove\r\n", ch);
// 		send_to_char ("\r\n-- Reserved Names --\r\n", ch);
// 		for (res = first_reserved; res; res = res->next)
// 		{
// 			ch_printf_color (ch, "%c%-17s ", (*res->name == '*' ? '*' : ' '), (*res->name == '*' ? res->name + 1 : res->name));
// 			if (++wid % 4 == 0)
// 				send_to_char ("\r\n", ch);
// 		}
// 		if (wid % 4 != 0)
// 			send_to_char ("\r\n", ch);
// 		return;
// 	}
// 
// 	if (!strcasecmp (arg2, "remove"))
// 	{
// 		for (res = first_reserved; res; res = res->next)
// 			if (!strcasecmp (arg, res->name))
// 			{
// 				UNLINK (res, first_reserved, last_reserved, next, prev);
// 				FREEMEM (res->name);
// 				FREEMEM (res);
// 				save_reserved (	);
// 				send_to_char ("Name no longer reserved.\r\n", ch);
// 				return;
// 			}
// 		ch_printf_color (ch, "The name %s isn't on the reserved list.\r\n", arg);
// 		return;
// 
// 	}
// 
// 	if (!strcasecmp (arg2, "add"))
// 	{
// 		for (res = first_reserved; res; res = res->next)
// 			if (!strcasecmp (arg, res->name))
// 			{
// 				ch_printf_color (ch, "The name %s has already been reserved.\r\n", arg);
// 				return;
// 			}
// 
// 		ALLOCMEM (res, RESERVE_DATA, 1);
// 		res->name = str_dup (arg);
// 		sort_reserved (res);
// 		save_reserved (	);
// 		send_to_char ("Name reserved.\r\n", ch);
// 		return;
// 	}
// 	send_to_char ("Invalid argument.\r\n", ch);
// }