phantasia4/
phantasia4/conf/
phantasia4/phantasia/bin/
phantasia4/phantasia/src/utilities/
phantasia4/public_html/cgi-bin/
/*
 * file.c       File manipulation routines
 */

#include "include.h"

/***************************************************************************
/ FUNCTION NAME: Do_purge_characters(void)
/
/ FUNCTION: Handles error messages
/
/ AUTHOR:  Brian Kelly, 4/22/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/

void Do_purge_characters(void)
{
    FILE *character_file;
    char error_msg[SZ_ERROR_MESSAGE];

	/* open the character file */
    errno = 0;
    if ((character_file=fopen(CHARACTER_FILE, "w")) == NULL) {

        sprintf(error_msg,
		"[0.0.0.0:?] fopen of %s failed in Do_purge_characters: %s\n",
		CHARACTER_FILE, strerror(errno));

	Do_log_error(error_msg);
	exit(CHARACTER_FILE_ERROR);
    }

    fclose(character_file);

    return;
}


/***************************************************************************
/ FUNCTION NAME: Do_purge_scoreboard(void)
/
/ FUNCTION: Handles error messages
/
/ AUTHOR:  Brian Kelly, 4/22/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/

void Do_purge_scoreboard(void)
{
    FILE *scoreboard_file;
    char error_msg[SZ_ERROR_MESSAGE];

	/* open the scoreboard file */
    errno = 0;
    if ((scoreboard_file=fopen(SCOREBOARD_FILE, "w")) == NULL) {

        sprintf(error_msg,
		"[0.0.0.0:?] fopen of %s failed in Do_purge_scoreboard: %s\n",
		SCOREBOARD_FILE, strerror(errno));

	Do_log_error(error_msg);
	exit(SCOREBOARD_FILE_ERROR);
    }

    fclose(scoreboard_file);

    return;
}


/***************************************************************************
/ FUNCTION NAME: Do_scoreboard_add(struct client_t *c, struct scoreboard_t *entry)
/
/ FUNCTION: Handles error messages
/
/ AUTHOR:  Brian Kelly, 4/22/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/

void Do_scoreboard_add(struct client_t *c, struct scoreboard_t *entry, bool showScore)
{
    FILE    *scoreboard_file, *temp_file;       /* for updating various files */
    struct scoreboard_t sb;
    struct event_t *event_ptr;
    char error_msg[SZ_ERROR_MESSAGE];
    int location;
    bool save_flag;

    Do_lock_mutex(&c->realm->scoreboard_lock);

	/* open the scoreboard file */
    errno = 0;
    if ((scoreboard_file=fopen(SCOREBOARD_FILE, "r")) == NULL) {

	Do_unlock_mutex(&c->realm->scoreboard_lock);

        sprintf(error_msg, "[%s] fopen of %s failed in Do_scoreboard_add: %s\n",
		c->connection_id, SCOREBOARD_FILE, strerror(errno));

        Do_log_error(error_msg);
	return;
    }

	/* open a tempoary file */
    if ((temp_file=fopen(TEMP_SCOREBOARD_FILE, "w")) == NULL) {

	fclose(scoreboard_file);
	Do_unlock_mutex(&c->realm->scoreboard_lock);

        sprintf(error_msg,
		"[%s] fopen of %s failed in Do_scoreboard_add(2): %s\n",
		c->connection_id, TEMP_SCOREBOARD_FILE, strerror(errno));

        Do_log_error(error_msg);
	return;
    }

    save_flag = TRUE;
    location = 0;

	/* copy records over to the temp file */
    while (fread((void *)&sb, SZ_SCOREBOARD, 1, scoreboard_file) == 1) {

	    /* if our player is higher level than our copy, put him in */
	if (save_flag && sb.level <= entry->level) {

            if (fwrite((void *)entry, SZ_SCOREBOARD, 1, temp_file) != 1) {

	        fclose(scoreboard_file);
	        fclose(temp_file);
		remove(TEMP_CHARACTER_FILE);
	        Do_unlock_mutex(&c->realm->scoreboard_lock);

                sprintf(error_msg,
			"[%s] fwrite of %s failed in Do_scoreboard_add: %s\n",
                        c->connection_id, TEMP_SCOREBOARD_FILE,
			strerror(errno));

                Do_log_error(error_msg);
		return;
            }
	    save_flag = FALSE;
	}

            /* check that the record to save isn't too old */
        if (sb.level > SB_KEEP_ABOVE || sb.time > time(NULL) - 
                SB_KEEP_FOR) {

	        /* transfer over the record */
            if (fwrite((void *)&sb, SZ_SCOREBOARD, 1, temp_file) != 1) {

	        fclose(scoreboard_file);
	        fclose(temp_file);
	        remove(TEMP_CHARACTER_FILE);
	        Do_unlock_mutex(&c->realm->scoreboard_lock);

                sprintf(error_msg,
		      "[%s] fwrite of %s failed in Do_scoreboard_add(2): %s\n",
                      c->connection_id, TEMP_SCOREBOARD_FILE, strerror(errno));

                Do_log_error(error_msg);
		return;
            }
        }

	    /* count this record if we haven't saved our character yet */
	if (save_flag) {
	    ++location;
	}
    }

	/* if no more scoreboard records, and we haven't written ours yet */
    if (save_flag) {

	    /* write it now */
        if (fwrite((void *)entry, SZ_SCOREBOARD, 1, temp_file) != 1) {

	    fclose(scoreboard_file);
	    fclose(temp_file);
	    remove(TEMP_CHARACTER_FILE);
	    Do_unlock_mutex(&c->realm->scoreboard_lock);

            sprintf(error_msg,
		    "[%s] fwrite of %s failed in Do_scoreboard_add(3): %s\n",
                    c->connection_id, TEMP_SCOREBOARD_FILE, strerror(errno));

            Do_log_error(error_msg);
	    return;
        }
    }

	/* remove the scoreboard */
    remove(SCOREBOARD_FILE);

	/* replace the old scoreboard file with the new one */
    rename(TEMP_SCOREBOARD_FILE, SCOREBOARD_FILE);

	/* close the file handles */
    fclose(scoreboard_file);
    fclose(temp_file);

    Do_unlock_mutex(&c->realm->scoreboard_lock);

        /* display the scoreboard */
    if (showScore) {
        Do_scoreboard(c, location, TRUE);
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_log(char *filename, char *message)
/
/ FUNCTION: reads the next packet type off the socket
/
/ AUTHOR: Brian Kelly, 8/25/99
/
/ ARGUMENTS:
/       int the_socket - the socket to read the packet type
/
/ RETURN VALUE:
/       int - the type of packet next on the socket
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/       wclrtoeol()
/
/ DESCRIPTION:
/       Read a string from the keyboard.
/
/************************************************************************/

Do_log(char *filename, char *message)
{
    FILE *log_file;
    time_t time_now;
    char error_msg[SZ_ERROR_MESSAGE];
    char string_buffer[SZ_LINE];

    time_now = time(NULL);
    ctime_r(&time_now, string_buffer);
    Do_truncstring(string_buffer);

        /* open the error log file */
    errno = 0;
    if ((log_file=fopen(filename, "a")) == NULL) {

            /* if the log file won't open, send and error */
        if (strcmp(filename, ERROR_LOG)) {

            sprintf(error_msg,
		    "[?:?] Can not open log file %s in Do_log: %s.\n",
		    filename, strerror(errno));

            Do_log_error(error_msg);
        }

            /* unless it is the error log, then go to stdout */
        else {

            printf("%s [?:?] Can not open error file %s in Do_log: %s.\n",
		    string_buffer, ERROR_LOG, strerror(errno));

	    printf("%s %s", string_buffer, message);
        }

        return;
    }

        /* print the error to the logfile */
    fprintf(log_file, "%s %s", string_buffer, message);

        /* close the logfile */
    fclose(log_file);

        /* return, regardless of error */
    return;
}


/***************************************************************************
/ FUNCTION NAME: Do_log_error(char *message)
/
/ FUNCTION: Handles error messages
/
/ AUTHOR:  Brian Kelly, 4/12/99
/
/ ARGUMENTS:
/       int error - the error code to be returned
/       char *message - the error message to be printed
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/

Do_log_error(char *message)
{
    Do_log(ERROR_LOG, message);
}


/************************************************************************
/
/ FUNCTION NAME: int Do_check_protected(struct client_t *c, char *theNetwork)
/
/ FUNCTION: return a char specifying player type
/
/ AUTHOR: Brian Kelly, 1/3/01
/
/ ARGUMENTS:
/       struct client_t c - pointer to the main client strcture
/
/ RETURN VALUE:
/       char - character the describes the character
/
/ MODULES CALLED: strcpy()
/
/ DESCRIPTION:
/       Return a string describing the player type.
/       King, council, valar, supercedes other types.
/       The first character of the string is '*' if the player
/       has a crown.
/       If 'shortflag' is TRUE, return a 3 character string.
/
*************************************************************************/

int Do_check_protected(struct client_t *c, char *theNetwork)
{
    char error_msg[SZ_ERROR_MESSAGE];
    char string_buffer[SZ_LINE];
    FILE *theFile;

        /* open the protected file */
    if ((theFile=fopen(PROTECTED_FILE, "r")) == NULL) {

        sprintf(error_msg,
		"[0.0.0.0:?] fopen of %s failed in Do_check_protected: %s\n",
                PROTECTED_FILE, strerror(errno));

        Do_log_error(error_msg);
	return FALSE;
    }

        /* loop through the the addresses */
    while (fgets(string_buffer, SZ_FROM, theFile) != NULL) {

        Do_truncstring(string_buffer);

        if (!strcmp(string_buffer, theNetwork)) {
	    fclose(theFile);
            return TRUE;
	}
    }

    fclose(theFile);
    return FALSE;
}


/************************************************************************
/
/ FUNCTION NAME: Do_restore_character(struct client_t *c)
/
/ FUNCTION: find location in player file of given name
/
/ AUTHOR: Brian Kelly, 01/17/01
/
/ ARGUMENTS:
/       char *name - name of character to look for
/       struct player *playerp - pointer of structure to fill
/
/ RETURN VALUE: location of player if found, -1 otherwise
/
/ MODULES CALLED: fread(), fseek(), strcmp()
/
/ GLOBAL INPUTS: Wizard, *Playersfp
/
/ GLOBAL OUTPUTS: none
/
/ DESCRIPTION:
/       Search the player file for the player of the given name.
/       If player is found, fill structure with player data.
/
*************************************************************************/

Do_restore_character(struct client_t *c)
{

    struct player_t readPlayer;
    struct history_t theHistory;
    FILE *character_file;
    char characterName[SZ_NAME], lcCharacterName[SZ_NAME];
    char error_msg[SZ_ERROR_MESSAGE];
    bool char_flag;


    if (Do_string_dialog(c, characterName, SZ_NAME - 1,
            "What is the name of the character to restore\n")) {

	Do_send_clear(c);
        return;
    }

    Do_send_clear(c);
    Do_lowercase(&lcCharacterName, &characterName);
    if (Do_look_character(c, &lcCharacterName, &readPlayer)) {

	sprintf(error_msg,
		"A character named %s is already in the character file.\n",
		characterName);

	Do_send_line(c, error_msg);
	Do_more(c);
	Do_send_clear(c);
	return;
    }

    errno = 0;
    if ((character_file=fopen(SECONDARY_CHAR_FILE, "r")) == NULL) {

	sprintf(error_msg, "fopen of %s failed: %s\n",
		SECONDARY_CHAR_FILE, strerror(errno));

	Do_send_line(c, error_msg);
	Do_more(c);
	Do_send_clear(c);
	return;
    }

    char_flag = FALSE;

	/* read each line of the character file */
    while (fread((void *)&readPlayer, SZ_PLAYER, 1, character_file) == 1) {

	    /* if we find our character, copy it over */
        if (strcmp(readPlayer.lcname, lcCharacterName) == 0) {
	    char_flag = TRUE;
	    break;
        }
    }

    fclose(character_file);

    if (!char_flag) {

	sprintf(error_msg, "A character named %s was not found in %s.\n",
		characterName, SECONDARY_CHAR_FILE);

	Do_send_line(c, error_msg);
	Do_more(c);
	Do_send_clear(c);
	return;
    }

	/* save the character */
    Do_save_character(c, &readPlayer);

	/* log this restore */
    sprintf(theHistory.description, "%s restored the character named %s\n",
	    c->modifiedName, readPlayer.name);

    theHistory.date = time(NULL);
    theHistory.type = T_ACCOUNT;
    strcpy(theHistory.name, readPlayer.parent_account);
    Do_save_history(c, &theHistory);

    theHistory.type = T_ADDRESS;
    strcpy(theHistory.name, readPlayer.parent_network);
    Do_save_history(c, &theHistory);

    sprintf(error_msg, "[%s] %s restored\n", c->connection_id,
            readPlayer.lcname);

    Do_log(GAME_LOG, error_msg);

    Do_send_line(c, "The character has been successfully restored.\n");
    Do_more(c);
    Do_send_clear(c);
    return;
}