/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure
*
* This program is free software; you can redistribute it and/or modify
*
* ---
*
- * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- * related information and legal notices. It is expected that any future
- * projects/authors will amend these files as needed.
+ * See files README, COPYING and CREDITS in the root of the source
+ * tree for related information and legal notices. It is expected
+ * that future projects/authors will amend these files as needed.
*
* ---
*
* empdis.c: Empire dispatcher stuff
- *
+ *
* Known contributors to this file:
* Dave Pare, 1994
* Steve McClure, 2000
+ * Markus Armbruster, 2006-2008
*/
-#include "prototypes.h"
+#include <config.h>
+
#include <stdio.h>
-#include "misc.h"
-#include "player.h"
-#include "nat.h"
-#include "tel.h"
-#include "proto.h"
+#include <time.h>
#include "com.h"
-#include "file.h"
#include "empio.h"
-#include "subs.h"
-#include "common.h"
+#include "file.h"
+#include "match.h"
+#include "misc.h"
+#include "nat.h"
#include "optlist.h"
+#include "player.h"
+#include "proto.h"
+#include "prototypes.h"
+#include "tel.h"
-#include <fcntl.h>
-#include <time.h>
-#if !defined(_WIN32)
-#include <unistd.h>
-#endif
-#include <signal.h>
#define KEEP_COMMANDS 50
-s_char player_commands[KEEP_COMMANDS][1024 + 8];
-int player_commands_index = 0;
+/* ring buffer of most recent command prompts and commands, user text */
+static char player_commands[KEEP_COMMANDS][1024 + 8];
+
+/* the slot holding the most recent command in player_commands[] */
+static int player_commands_index = 0;
+
+static void disable_coms(void);
+
+/*
+ * Get a command from the current player into COMBUFP[1024], in UTF-8.
+ * This may block for input, yielding the processor. Flush buffered
+ * output when blocking, to make sure player sees the prompt.
+ * Return command's byte length on success, -1 on error.
+ */
int
-getcommand(s_char *combufp)
+getcommand(char *combufp)
{
- struct natstr *natp;
- s_char buf[1024];
+ struct natstr *natp = getnatp(player->cnum);
+ char buf[1024]; /* user text */
-/* Note this now assumes a 1024 byte buffer is being passed in */
- natp = getnatp(player->cnum);
if (++player_commands_index >= KEEP_COMMANDS)
player_commands_index = 0;
sprintf(player_commands[player_commands_index], "%3d %3d [prompt]",
player_commands_index, player->cnum);
+
do {
prprompt(natp->nat_minused, natp->nat_btu);
buf[0] = 0;
return -1;
}
} while (buf[0] == 0);
+
if (++player_commands_index >= KEEP_COMMANDS)
player_commands_index = 0;
sprintf(player_commands[player_commands_index], "%3d %3d %s",
player_commands_index, player->cnum, buf);
- strcpy(combufp, buf);
- return (strlen(combufp));
+
+ if (player->flags & PF_UTF8)
+ return copy_utf8_no_funny(combufp, buf);
+ return copy_ascii_no_funny(combufp, buf);
}
void
for (i = 0; i < KEEP_COMMANDS; ++i)
*player_commands[i] = 0;
+
+ disable_coms();
}
void
int
explain(void)
{
- register s_char *format;
- register int i;
-
- pr("\t\tCurrent EMPIRE Command List\n");
- pr("\t\t------- ------ ------- ----\n");
- pr("Initial number is cost in B.T.U. units.\n");
- pr("Next 2 chars (if present) are:\n");
- pr("$ - must be non-broke\tc -- must have capital\n");
- pr("Args in [brackets] are optional.\n");
- if (player->nstat > 4) {
- pr("All-caps args in <angle brackets>");
- pr(" have the following meanings:\n");
- pr(" <NUM> :: a number in unspecified units\n");
- pr(" <COMM> :: a commodity such as `food', `guns', etc\n");
- pr(" <VAR> :: a commodity such as `food', `guns', etc\n");
- pr(" <TYPE> :: an item type such as `ship', `plane', etc\n");
- }
+ char *format;
+ int i;
+
+ pr("\t\tCurrent EMPIRE Command List\n"
+ "\t\t------- ------ ------- ----\n"
+ "Initial number is cost in B.T.U. units.\n"
+ "Next 2 chars (if present) are:\n"
+ "$ - must be non-broke\tc -- must have capital\n"
+ "Args in [brackets] are optional.\n"
+ "All-caps args in <angle brackets>"
+ " have the following meanings:\n"
+ /* FIXME incomplete */
+ " <NUM> :: a number in unspecified units\n"
+ " <COMM> :: a commodity such as `food', `guns', etc\n"
+ " <TYPE> :: an item type such as `ship', `plane', etc\n");
for (i = 0; (format = player_coms[i].c_form) != 0; i++) {
- if ((player_coms[i].c_permit & player->ncomstat) ==
- player_coms[i].c_permit) {
+ if ((player_coms[i].c_permit & player->nstat)
+ == player_coms[i].c_permit) {
pr("%2d ", player_coms[i].c_cost);
if ((player_coms[i].c_permit & MONEY) == MONEY)
pr("$");
return RET_OK;
}
+static void
+disable_coms(void)
+{
+ char *tmp = strdup(disabled_commands);
+ char *name;
+ int cmd;
+
+ for (name = strtok(tmp, " \t"); name; name = strtok(NULL, " \t")) {
+ cmd = comtch(name, player_coms, -1);
+ if (cmd < 0) {
+ logerror("Warning: not disabling %s command %s\n",
+ cmd == M_NOTUNIQUE ? "ambiguous" : "unknown", name);
+ continue;
+ }
+ player_coms[cmd].c_permit |= GOD;
+ }
+
+ free(tmp);
+}
+
/*
* returns true if down
*/
int
gamedown(void)
{
- int downf;
+ FILE *down_fp;
struct telstr tgm;
- s_char buf[1024];
+ char buf[MAXTELSIZE + 1]; /* UTF-8 */
if (player->god)
return 0;
-#if !defined(_WIN32)
- if ((downf = open(downfil, O_RDONLY, 0)) < 0)
-#else
- if ((downf = open(downfil, O_RDONLY | O_BINARY, 0)) < 0)
-#endif
+ if ((down_fp = fopen(downfil, "rb")) == NULL)
return 0;
- if (read(downf, (s_char *)&tgm, sizeof(tgm)) != sizeof(tgm)) {
+ if (fread(&tgm, sizeof(tgm), 1, down_fp) != 1) {
logerror("bad header on login message (downfil)");
- close(downf);
+ fclose(down_fp);
+ return 1;
+ }
+ if (tgm.tel_length >= (long)sizeof(buf)) {
+ logerror("text length (%ld) is too long for login message (downfil)", tgm.tel_length);
+ fclose(down_fp);
return 1;
}
- if (read(downf, buf, tgm.tel_length) != tgm.tel_length) {
+ if (fread(buf, tgm.tel_length, 1, down_fp) != 1) {
logerror("bad length %ld on login message", tgm.tel_length);
- close(downf);
+ fclose(down_fp);
return 1;
}
- if (tgm.tel_length >= (long)sizeof(buf))
- tgm.tel_length = sizeof(buf) - 1;
buf[tgm.tel_length] = 0;
- pr(buf);
+ uprnf(buf);
pr("\nThe game is down\n");
- (void)close(downf);
+ fclose(down_fp);
return 1;
}