/*
 *  putget.c -- the PMF commands /putfile and /getfile, for LPmud
 *
 *	NOTE: The code in this file is heavily dependent on the exact
 *	      format of input and output to the built-in LPmud editor "ed"!
 *	      If they are changed, this file will probably
 *	      have to be changed too!
 *
 *  PMF -- Padrone's MudFrontend, a frontend for (maybe mostly LP-)mud
 *  Thomas Padron-McCarthy (Email: padrone@lysator.liu.se), 1990, 1991
 *  Share and enjoy, but be nice: don't steal my program! Hugo is watching!
 *  This file latest updated: Sept 21, 1991
 *
 */

#include <strings.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include "safe_malloc.h"
#include "config.h"
#include "pmf.h"
#include "globals.h"

extern char *get_input_line(), *expand_alias(),
    *find_alias_string(),
    *expand_history(), *get_statstring(), *getmud(),
    *expand_variables(),
    *find_robot_action_string(),
    *return_last();

/*  This is a temporary buffer of text received from the MUD game.
 *  If the flag "getfiling" is true, the routines that receive the MUD
 *  output will put it here too, using the function getfile_got_text().
 *  We use this to remember the lines received when doing a getfile,
 *  since we cannot simply write all the output to the file
 *  -- it contains the editor prompt ":", and maybe some "Harry says:" etc.
 */
static char *received_text = NULL;
static int received_text_length = 0;

/*---------------------------------------------------------------------------*/

/* Send a file to LPmud using the built-in editor */
cmd_putfile(filename, optional_filename)
char *filename, *optional_filename;
{
    char *local_filename, *remote_filename, cmd_buffer[MAX_LINE_LENGTH + 1];
    struct stat dummy_statbuf;

    local_filename = filename;
    if (optional_filename)
	remote_filename = optional_filename;
    else
	remote_filename = filename;

    if (stat(local_filename, &dummy_statbuf) != 0) {
	uerror("No such local file: \"%s\".", local_filename);
	return;
    }

    ldisplay("Putting local \"%s\" (%s) to remote \"%s\".\n",
	     local_filename, get_statstring(local_filename), remote_filename);

    sprintf(cmd_buffer, "ed %s", remote_filename);
    queue_mudline(cmd_buffer, ":");

/* -- We do NOT write a backup file on the MUD server!
    sprintf(cmd_buffer, "w %s.bak", remote_filename);
    queue_mudline(cmd_buffer, ":");
*/
    queue_mudline("1,$d", ":");
    queue_mudline("i", "*");
    while (!ok_to_send())
	communicate_with_mud();
    cmd_send(local_filename, "*", 1);
    while (!ok_to_send())
	communicate_with_mud();
    sprintf(cmd_buffer, "w %s", remote_filename);
    queue_mudline(".", ":");
    queue_mudline(cmd_buffer, ":");
    queue_mudline("Q", ">");
    while (!ok_to_send())
	communicate_with_mud();
    ldisplay("\n");
    ldisplay("Finished putting local \"%s\".\n", local_filename);

} /* cmd_putfile */

/*---------------------------------------------------------------------------*/

static void reset_received_text()
{

    if (received_text != NULL)
	safe_free(received_text);
    received_text = NULL;
    received_text_length = 0;
} /* reset_received_text */

/*---------------------------------------------------------------------------*/

/* Get a file from LPmud using the built-in editor */
cmd_getfile(filename, optional_filename)
char *filename, *optional_filename;
{
    char *local_filename, *remote_filename, cmd_buffer[MAX_LINE_LENGTH + 1];
    int nr_lines, linenr, chunkstart, chunkend, got_lines, lines_to_get;

    if (sending || receiving || getfiling) {
	message("Cannot do more than one send or receive command at the same time.");
	return;
    }

    /* Must be done before communicate_with_mud() is called: */
    reset_received_text();

    remote_filename = filename;
    if (optional_filename)
	local_filename = optional_filename;
    else
	local_filename = filename;

    if (backup_file(local_filename) == -1)
	uerror("Couldn't backup.");
    else if ((the_open_file = fopen(local_filename, "w")) == NULL) {
	uerror("Couldn't open local file \"%s\".", local_filename);
    }

    /* Remember the file and its name so we can close it if an error occurs: */
    /* We already set "the_open_file". */
    the_open_file_name = strcpy(safe_malloc(strlen(local_filename) + 1),
				local_filename);
    getfiling = 1;

    ldisplay("Getting remote \"%s\" into local \"%s\".\n", remote_filename, local_filename);

    /* First: Enter the editor. */
    sprintf(cmd_buffer, "ed %s", remote_filename);
    queue_mudline(cmd_buffer, ":");
    while (!ok_to_send())
	communicate_with_mud();

    /* Get the number of lines in the remote file. */
    do {
	reset_received_text();
	queue_mudline("$=", ":");
	while (!ok_to_send())
	    communicate_with_mud();
    } while (nr_lines_in_text(received_text) != 1 || received_text[received_text_length - 1] != ':');

    nr_lines = atoi(received_text);
    ldisplay("\nThe remote file \"%s\" seems to contain %d lines.\n", remote_filename, nr_lines);

    /* Get the lines. */
    for (linenr = 1; linenr < nr_lines + 1; linenr += GETFILE_CHUNKSIZE) {
	while (!ok_to_send())
	    communicate_with_mud();
	chunkstart = linenr;
	chunkend = chunkstart + GETFILE_CHUNKSIZE - 1;
	if (chunkend > nr_lines)
	    chunkend = nr_lines;
	lines_to_get = chunkend - chunkstart + 1;
	sprintf(cmd_buffer, "%d,%dp", chunkstart, chunkend);
	do {
	    USER_DEBUG(("Trying to get lines %d..%d from remote file \"%s\"", chunkstart, chunkend, remote_filename));
	    reset_received_text();
	    queue_mudline(cmd_buffer, ":");
	    while (!ok_to_send())
		communicate_with_mud();
	    got_lines = nr_lines_in_text(received_text);
	    if (got_lines != lines_to_get || received_text[received_text_length - 1] != ':') {
		ldisplay("\n");
		message("Failed to receive lines %d..%d. Trying again.", chunkstart, chunkend);
	    }
	} while (got_lines != lines_to_get || received_text[received_text_length - 1] != ':');
	USER_DEBUG(("Got lines %d..%d from remote file \"%s\"", chunkstart, chunkend, remote_filename));
	received_text[received_text_length - 1] = '\0';	/* Remove the ed prompt ":" */
	fprintf(the_open_file, "%s", received_text);	/* No '\n' here. */
	fflush(the_open_file);
    }

    ldisplay("\n");

    /* Close the file, free the file name buffer, and restore all states. */
    fclose(the_open_file);
    safe_free(the_open_file_name);
    the_open_file = NULL;
    the_open_file_name = NULL;
    getfiling = 0;

    /* And exit the LPmud editor. */
    while (!ok_to_send())
	communicate_with_mud();
    queue_mudline("Q", ">");
    while (!ok_to_send())
	communicate_with_mud();

    ldisplay("Finished getting remote \"%s\" into local \"%s\" (%s).\n",
	     remote_filename, local_filename, get_statstring(local_filename));
} /* cmd_getfile */

/*---------------------------------------------------------------------------*/

/*  This function should be called from the routines that receive text
 *  from MUD, if and only if "getfiling" is true.
 */
char *getfile_got_text(text_from_mud)
char *text_from_mud;
{

    ASSERT(getfiling);
    ASSERT(text_from_mud != NULL);

    if (received_text == NULL) {
	received_text_length = strlen(text_from_mud);
	    /* Without the null byte! */
	received_text = safe_malloc(received_text_length + 1);
	    /* The null byte too! */
	strcpy(received_text, text_from_mud);
    }
    else {
	received_text =
	    safe_realloc(received_text,
			 (received_text_length += strlen(text_from_mud)) + 1);
	             /* The null byte here too, idiot! */
	strcat(received_text, text_from_mud);
    }
    return received_text;
} /* getfile_got_text */


syntax highlighted by Code2HTML, v. 0.9.1