/*
* main.c -- the function "main", some initializations, welcome-messages etc
*
* 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 <signal.h>
#include <setjmp.h>
#include <sys/param.h>
#include "safe_malloc.h"
#include "str_galore.h"
#include "config.h"
#include "pmf.h"
#include "globals.h"
extern char *getenv();
extern char *getmud();
extern char *get_input_line();
extern int communicate_with_mud();
#ifdef GNU_READLINE
extern char *rl_readline_name;
extern (*rl_event_hook)();
extern int rl_clear_message();
extern char *rl_line_buffer;
extern int rl_point, rl_end;
extern int stop_printing();
extern int continue_printing();
extern int _rl_last_c_pos;
#endif
/* Longjmp buffer, jump there after error() or CTRL-C */
jmp_buf home_sweet_home; /* Initialized in main() */
static char *initfile_string;
char version[] = VERSION;
int no_news = 0;
extern FILE *popen_x_out();
/*---------------------------------------------------------------------------*/
#ifdef GNU_READLINE
int pmf_rl_redisplay_line(count, key)
int count, key;
{
ldisplay("\n");
ldisplay("%s", rl_line_buffer);
rl_redisplay(count, key);
_rl_last_c_pos = rl_end;
}
#endif
void init_variables()
{
char buf[10];
/* Set history list */
sprintf(buf, "%d", DEFAULT_MAX_HISTORY);
set_variable("history", buf);
/* set_variable("substitute_history", "true"); */
set_variable("show_receive", "true");
set_variable("slash_commands", "true");
sprintf(buf, "%d", DEFAULT_LINES_TO_SAVE);
set_variable("lines_to_save", buf);
set_variable("verbose", "true");
sprintf(buf, "%d", DEFAULT_SCREEN_LENGTH);
set_variable("screen_length", buf);
} /* init_variables */
#ifdef GNU_READLINE
init_readline()
{
rl_event_hook = communicate_with_mud;
rl_bind_key('\022', pmf_rl_redisplay_line); /* CTRL-R */
rl_bind_key('\023', stop_printing); /* CTRL-S */
rl_bind_key('\021', continue_printing); /* CTRL-Q */
rl_readline_name = "pmf"; /* For conditional parsing of the ~/.inputrc file. */
} /* init_readline */
#endif
initialize()
{
setup_signals();
/* We don't want any stdio-buffering of stdin and stdout. */
/* setbuf(stdin, NULL); */
/* setbuf(stdout, NULL); */
/* S{tt cbreak-mode, with no line buffering of stdin. */
/* set_cbreak(); */
init_variables();
init_queue_to_mud();
init_queue_of_lines();
init_set_of_aliases();
init_set_of_robot_actions();
init_set_of_gags();
#ifdef SOUND
init_set_of_sound_actions();
#endif
#ifdef GNU_READLINE
init_readline();
pmf_save_terminal();
#endif
} /* initialize */
say_hello()
{
printf("\n");
printf("Welcome to PMF -- Padrone's MudFrontend version %s.\n", version);
if (verbose) {
printf("\n");
printf("The PMF program connects to the MUD server in the same way as telnet, but\n");
printf("some of the lines you type are interpreted as commands to the PMF program.\n");
printf("Type \"/help\" or \"help pmf\" for more information.\n");
printf("\n");
printf("No warranty, except that I guarantee that there ARE bugs in this program.\n");
#ifdef LOCAL_PMF_GURU
printf("\n");
printf("If you have any problems with PMF, talk to %s!\n", LOCAL_PMF_GURU);
#endif
}
printf("\n");
} /* say_hello */
int print_news()
{
char *news_file;
FILE *fp;
int c;
news_file = make_path(SYSTEM_DIR, SYSTEM_NEWS_FILE);
fp = fopen(news_file, "r");
safe_free(news_file);
if (fp == NULL) {
return -1;
}
else {
printf("Local news about PMF:\n");
while ((c = getc(fp)) != EOF)
putc(c, stdout);
printf("\n");
return 0;
}
} /* print_news */
say_goodbye_and_exit(exitval)
int exitval;
{
printf("\n");
printf("PMF -- Padrone's MudFrontend version %s.\n", version);
printf("Goodbye. Have a nice day. Enjoy Coke. Be back soon!\n");
printf("\n");
disconnect();
#ifdef GNU_READLINE
pmf_restore_terminal();
#endif
if (x_outfile)
fclose(x_outfile);
if (named_pipe_name[0])
unlink(named_pipe_name);
#ifdef DEBUG_MALLOC
dump_malloc();
#endif
if (debug && exitval) {
#if defined(__FreeBSD__) && (__FreeBSD_version >= 500035)
signal(SIGABRT, SIG_DFL);
#else
signal(SIGIOT, SIG_DFL);
#endif
abort();
}
else
exit(exitval);
} /* say_goodbye_and_exit */
/*---------------------------------------------------------------------------*/
handle_args(argc, argv)
int argc;
char *argv[];
{
int argnr;
char *cp;
char next_is_initfile;
next_is_initfile = 0;
initfile_string = NULL;
arg_host_string = NULL;
arg_port_string = NULL;
for (argnr = 1; argnr < argc; ++argnr)
if (argv[argnr][0] == '-') {
cp = &argv[argnr][1];
while (*cp) {
switch (*cp) {
case 'X' : x_windows = 1; break;
case '2' : two_windows = 1; break;
case 'f' : next_is_initfile = 1; break;
case 'd' : debug = 1; set_variable("debug", "true"); break;
#ifdef DEBUG
case 'i' : internal_debug = 1; set_variable("internal_debug", "true"); break;
case 'c' : ipc_debug = 1; set_variable("ipc_debug", "true"); break;
#endif
case 'n' : no_news = 1; break;
case 's' : verbose = 0; unset_variable("verbose"); break;
default : usage(); break;
}
++cp;
}
}
else {
if (next_is_initfile) {
initfile_string = argv[argnr];
next_is_initfile = 0;
}
else if (!arg_host_string)
arg_host_string = argv[argnr];
else if (!arg_port_string)
arg_port_string = argv[argnr];
else
usage();
}
} /* handle_args */
usage()
{
fprintf(stderr, "Usage: pmf [ -dnsX2 ] [ -f startfile ] [ HOST [ PORT ] ]\n");
exit(1);
} /* usage */
goto_home_sweet_home(arg)
int arg;
{
longjmp(home_sweet_home, arg);
} /* goto_home_sweet_home */
/*---------------------------------------------------------------------------*/
main(argc, argv)
int argc;
char *argv[];
{
initialize();
handle_args(argc, argv);
if (x_windows) {
x_outfile = popen_x_out();
if (x_outfile == NULL) {
message("Couldn't fix the X output. X mode off.");
x_windows = 0;
}
}
if (x_windows && two_windows) {
message("You cannot use both -2 and -X. Turning off -2.");
two_windows = 0;
}
say_hello();
if (!no_news)
print_news();
if (setjmp(home_sweet_home)) {
/* This will not close all files if we have nested source or send/receive
* commands. But maybe we can live with that.
*/
if (the_open_file) {
fclose(the_open_file);
the_open_file = NULL;
ldisplay("Closed: \"%s\"\n", the_open_file_name);
}
if (the_source_file) {
fclose(the_source_file);
the_source_file = NULL;
ldisplay("Closed: \"%s\"\n", the_source_file_name);
}
sending = 0;
receiving = 0;
sourcing = 0;
getfiling = 0;
flush_queue_to_mud();
pmf_restore_terminal();
if (pmf_prompt)
ldisplay(pmf_prompt, query_latest_event_nr() + 1);
}
else {
/* These we must do here, since the longjmp destination must be set
* if there is an error or the user types CTRL-C.
*/
do_init_file();
if (!connected)
cmd_connect(NULL, NULL);
}
was_feof = 0;
while (1) {
while (!feof(stdin) && !was_feof) {
handle_the_player();
communicate_with_mud();
} /* while */
ldisplay("\n");
ldisplay("PMF has received an End-Of-File character.\n");
if (ignoreeof) {
ldisplay("Since the variable \"ignoreeof\" is set, the End-Of-File character is ignored.\n");
ldisplay("Logout from LPmud with \"quit\", or use \"/quit\" just to exit from PMF.\n");
ldisplay("\n");
clearerr(stdin);
was_feof = 0;
}
else {
if (connected)
ldisplay("Disconnecting from the game -- but maybe you should \"quit\", too?\n");
say_goodbye_and_exit(0);
}
}
} /* main */
int do_init_file()
{
struct stat dummy_statbuf;
char filename_buf[256], *the_filename, *this_line, *the_home;
FILE *fp;
fp = NULL;
the_home = getenv("HOME");
if (initfile_string) {
the_filename = initfile_string;
if ((fp = fopen(the_filename, "r")) == NULL)
message("Couldn't read the init file %s.", the_filename);
}
if (!fp && the_home) {
sprintf(filename_buf, "%s/%s", the_home, INIT_FILE_NAME);
the_filename = filename_buf;
if (stat(the_filename, &dummy_statbuf) == 0) {
if ((fp = fopen(the_filename, "r")) == NULL)
message("Couldn't read your init file %s.", the_filename);
}
}
if (!fp) {
the_filename = make_path(SYSTEM_DIR, SYSTEM_DEFAULT_INIT_FILE);
if (stat(the_filename, &dummy_statbuf) == 0) {
if ((fp = fopen(the_filename, "r")) == NULL)
message("Couldn't read the default init file %s.", the_filename);
}
}
if (!fp)
return -1;
/* Remember the file and its name so we can close it if an error occurs: */
the_open_file = fp;
the_open_file_name = the_filename;
if (verbose)
ldisplay("Reading init file %s (%s).\n",
the_filename, get_statstring(the_filename));
sourcing = 1;
this_line = get_input_line(fp);
while (! feof(fp)) {
if (!is_comment_line(this_line))
handle_command(this_line, 0);
/* safe_free(this_line); -- Ooops! No no no! */
if (verbose)
ldisplay(".");
this_line = get_input_line(fp);
} /* while */
if (verbose)
ldisplay("\nInit file %s done.\n", the_filename);
fclose(fp);
the_open_file = NULL;
sourcing = 0;
return 0;
} /* do_init_file */
syntax highlighted by Code2HTML, v. 0.9.1