]> git.pond.sub.org Git - empserver/blobdiff - src/client/main.c
client: Rewrite readline configuration
[empserver] / src / client / main.c
index 62c667ae5389c56714b6d7cd79254fbb56a270c4..cdffc8ac42a8deddde85cb16aa93970e943c3b2f 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                Ken Stevens, Steve McClure, Markus Armbruster
  *
- *  This program is free software; you can redistribute it and/or modify
+ *  Empire is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  ---
  *
  *  ---
  *
  *  main.c: client main function
- * 
+ *
  *  Known contributors to this file:
  *     Dave Pare, 1986
  *     Steve McClure, 1998
- *     Ron Koenderink, 2004-2005
- *     Markus Armbruster, 2005-2007
+ *     Ron Koenderink, 2004-2007
+ *     Markus Armbruster, 2005-2015
+ *     Tom Dickson-Hunt, 2010
+ *     Martin Haukeli, 2015
  */
 
 #include <config.h>
 
-#ifndef _WIN32
-#include <pwd.h>
 #include <stdlib.h>
-#include <unistd.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <shlobj.h>
+#include "sys/socket.h"
+#else
+#include <pwd.h>
 #endif
+#include <unistd.h>
 #include "misc.h"
 #include "version.h"
 
 #ifdef _WIN32
 #define getuid() 0
-#define getpwuid(uid) ((uid), w32_getpw())
-#else
+#define getpwuid(uid) ((void)(uid), w32_getpw())
+#define sysdep_init() w32_sysdep_init()
+
+struct passwd {
+    char *pw_name;
+    char *pw_dir;
+};
+
+static struct passwd *w32_getpw(void);
+static void w32_sysdep_init(void);
+#else  /* !_WIN32 */
 #define sysdep_init() ((void)0)
-#endif
+#endif /* !_WIN32 */
 
 static void
 print_usage(char *program_name)
@@ -57,7 +72,12 @@ print_usage(char *program_name)
     printf("Usage: %s [OPTION]...[COUNTRY [PASSWORD]]\n"
           "  -2 FILE         Append log of session to FILE\n"
           "  -k              Kill connection\n"
+          "  -r              Restricted mode, no redirections\n"
+          "  -s [HOST:]PORT  Specify server HOST and PORT\n"
           "  -u              Use UTF-8\n"
+#ifdef HAVE_LIBREADLINE
+          "  -H              Save readline command history to file\n"
+#endif /* HAVE_LIBREADLINE */
           "  -h              display this help and exit\n"
           "  -v              display version information and exit\n",
           program_name);
@@ -68,24 +88,45 @@ main(int argc, char **argv)
 {
     int opt;
     char *auxfname = NULL;
+    int use_history_file = 0;
     int send_kill = 0;
+    char *host = NULL;
+    char *port = NULL;
     int utf8 = 0;
     char **ap;
     char *country;
     char *passwd;
     char *uname;
-    char *host;
-    char *port;
+    char *udir;
+    char *colon;
     int sock;
+    char *history_file;
 
-    while ((opt = getopt(argc, argv, "2:kuhv")) != EOF) {
+    while ((opt = getopt(argc, argv, "2:Hkrs:uhv")) != EOF) {
        switch (opt) {
        case '2':
            auxfname = optarg;
            break;
+#ifdef HAVE_LIBREADLINE
+       case 'H':
+           use_history_file = 1;
+           break;
+#endif /* HAVE_LIBREADLINE */
        case 'k':
            send_kill = 1;
            break;
+       case 'r':
+           restricted = 1;
+           break;
+       case 's':
+           port = strdup(optarg);
+           colon = strrchr(port, ':');
+           if (colon) {
+               *colon = 0;
+               host = port;
+               port = colon + 1;
+           }
+           break;
        case 'u':
            utf8 = eight_bit_clean = 1;
            break;
@@ -96,7 +137,7 @@ main(int argc, char **argv)
            printf("%s\n\n%s", version, legal);
            exit(0);
        default:
-           print_usage(argv[0]);
+           fprintf(stderr, "Try -h for help.\n");
            exit(1);
        }
     }
@@ -110,14 +151,17 @@ main(int argc, char **argv)
        passwd = *ap++;
     else
        passwd = getenv("PLAYER");
-    port = getenv("EMPIREPORT");
+    if (!port)
+       port = getenv("EMPIREPORT");
     if (!port)
        port = empireport;
-    host = getenv("EMPIREHOST");
+    if (!host)
+       host = getenv("EMPIREHOST");
     if (!host)
        host = empirehost;
     uname = getenv("LOGNAME");
-    if (uname == NULL) {
+    udir = getenv("HOME");
+    if (!uname || !udir) {
        struct passwd *pwd;
 
        pwd = getpwuid(getuid());
@@ -125,7 +169,15 @@ main(int argc, char **argv)
            fprintf(stderr, "You don't exist.  Go away\n");
            exit(1);
        }
-       uname = pwd->pw_name;
+       if (!uname)
+           uname = pwd->pw_name;
+       if (!udir)
+           udir = pwd->pw_dir;
+    }
+    if (*ap) {
+       fprintf(stderr, "%s: extra operand %s\n", argv[0], *ap);
+       fprintf(stderr, "Try -h for help.\n");
+       exit(1);
     }
 
     getsose();
@@ -138,11 +190,66 @@ main(int argc, char **argv)
 
     sock = tcp_connect(host, port);
 
+    if (use_history_file) {
+       /* FIXME don't truncate udir */
+       history_file = malloc(1024);
+       strncpy(history_file, udir, 1000);
+       strcat(history_file, "/.empire.history");
+    }
+
     if (!login(sock, uname, country, passwd, send_kill, utf8))
        exit(1);
 
-    if (play(sock) < 0)
+    if (play(sock, history_file) < 0)
        exit(1);
 
     return 0;
 }
+
+#ifdef _WIN32
+/*
+ * Get Windows user name and directory
+ */
+static struct passwd *
+w32_getpw(void)
+{
+    static char unamebuf[128];
+    static char udirbuf[MAX_PATH];
+    static struct passwd pwd;
+    DWORD unamesize;
+
+    unamesize = sizeof(unamebuf);
+    if (GetUserName(unamebuf, &unamesize)) {
+       pwd.pw_name = unamebuf;
+       if (unamesize == 0 || strlen(unamebuf) == 0)
+           pwd.pw_name = "nobody";
+    } else
+       pwd.pw_name = "nobody";
+    if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, udirbuf))
+       && strlen(udirbuf) == 0)
+       pwd.pw_dir = udirbuf;
+    return &pwd;
+}
+
+static void
+w32_sysdep_init(void)
+{
+    int err;
+
+    /*
+     * stdout is unbuffered under Windows if connected to a character
+     * device, and putchar() screws up when printing multibyte strings
+     * bytewise to an unbuffered stream.  Switch stdout to line-
+     * buffered mode.  Unfortunately, ISO C allows implementations to
+     * screw that up, and of course Windows does.  Manual flushing
+     * after each prompt is required.
+     */
+    setvbuf(stdout, NULL, _IOLBF, 4096);
+
+    err = w32_socket_init();
+    if (err != 0) {
+       fprintf(stderr, "WSAStartup Failed, error code %d\n", err);
+       exit(1);
+    }
+}
+#endif