#
# Empire - A multi-player, client/server Internet based war game.
-# Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+# Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
# Ken Stevens, Steve McClure, Markus Armbruster
#
# Empire is free software: you can redistribute it and/or modify
# Make.mk: The real Makefile, included by GNUmakefile
#
# Known contributors to this file:
-# Markus Armbruster, 2005-2015
+# Markus Armbruster, 2005-2016
#
# This makefile was inspired by `Recursive Make Considered Harmful',
# Source files
ifeq ($(revctrl),git)
src := $(shell cd $(srcdir) && git ls-files | uniq)
+version := $(shell cd $(srcdir) && build-aux/git-version-gen /dev/null)
else
include $(srcdir)/sources.mk
+version := $(shell cat $(srcdir)/.tarball-version || echo "UNKNOWN")
+endif
+ifeq ($(version),UNKNOWN)
+$(error cannot figure out version)
endif
dirs := $(sort $(dir $(src)))
csrc := $(filter %.c, $(src))
# Generated files
# See `Cleanliness' below
-mk :=
-ifeq ($(revctrl),git)
-mk += $(srcdir)/sources.mk
-endif
+# Generated makefiles, distributed by dist-source from $(srcdir):
+mk := sources.mk
# Generated by Autoconf, not distributed:
ac := config.h config.log config.status info.html info.nr lib stamp-h
ac += $(basename $(filter %.in, $(src)))
server := src/server/emp_server$(EXEEXT)
# Info subjects:
tsubj := $(addprefix info/, $(addsuffix .t, $(subjects)))
-ttop := info/TOP.t
# Formatted info:
info.nr := $(addprefix info.nr/, $(info))
info.html := $(addprefix info.html/, $(addsuffix .html, $(info)))
# Each generated file should be in one of the following sets.
# Removed by clean:
clean := $(obj) $(deps) $(libs) $(util) $(client) $(server) $(tsubj) \
-$(ttop) $(info.all) $(empth_obj) $(empth_lib) sandbox
+info/toc info/TOP.t $(info.all) $(empth_obj) $(empth_lib) sandbox
# Removed by distclean:
-distclean := $(ac) $(mk)
+distclean := $(ac)
+ifeq ($(revctrl),git)
+distclean += $(addprefix $(srcdir)/, $(mk))
+endif
# Distributed by dist-source from $(srcdir):
-src_distgen := $(acdist)
+src_distgen := $(acdist) $(mk)
# Distributed by dist-client from $(srcdir)/src/client; removed by distclean:
cli_distgen := $(acdistcli)
$(srcdir)/tests/torpedo-test $(srcdir)
$(srcdir)/tests/bridgefall-test $(srcdir)
$(srcdir)/tests/retreat-test $(srcdir)
+ $(srcdir)/tests/update-test $(srcdir)
+ $(srcdir)/tests/version-test $(srcdir)
else
@echo "$(srcdir)/tests/smoke-test SKIPPED"
@echo "$(srcdir)/tests/actofgod-test SKIPPED"
@echo "$(srcdir)/tests/torpedo-test SKIPPED"
@echo "$(srcdir)/tests/bridgefall-test SKIPPED"
@echo "$(srcdir)/tests/retreat-test SKIPPED"
+ @echo "$(srcdir)/tests/update-test SKIPPED"
+ @echo "$(srcdir)/tests/version-test SKIPPED"
endif
$(srcdir)/tests/empdump-test $(srcdir)
$(server): $(filter src/server/% src/lib/commands/% src/lib/player/% src/lib/subs/% src/lib/update/%, $(obj)) $(empth_obj) $(empth_lib) $(libs)
$(call quiet-command,$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@,LINK $@)
- $(client): $(filter src/client/%, $(obj)) src/lib/global/version.o
+ $(client): $(filter src/client/%, $(obj)) src/lib/global/version.o src/lib/gen/fnameat.o
$(call quiet-command,$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@,LINK $@)
$(util): $(libs)
$(call quiet-command,$(AR) rc $@ $?,AR $@)
$(RANLIB) $@
+src/lib/global/version.o: CPPFLAGS += -DVERSION='"$(version)"'
+src/lib/global/version.o: $(src)
+
+ifneq ($(revctrl),git)
+$(srcdir)/.tarball-version: $(src)
+ v=`sed -e 's/-dirty$$//' <$@`; echo "$$v-dirty" >$@
+# Force Make to start over after updating .tarball-version, so that
+# $(version) gets the new value
+$(srcdir)/.dirty-stamp: .tarball-version
+ >$@
+include $(srcdir)/.dirty-stamp
+endif
+
# Info formatting
# mksubj.pl reads $(tsrc) and writes $(tsubj). A naive rule
$(call quiet-command,perl $(srcdir)/info/mksubj.pl $(subjects) $(filter %.t, $^),GEN '$(tsubj) info/toc')
>$@
-$(ttop): info/mktop.pl info/subjects.mk
+info/TOP.t: info/mktop.pl info/subjects.mk
$(call quiet-command,perl $(srcdir)/info/mktop.pl $@ $(subjects),GEN $@)
info.nr/all: $(filter-out info.nr/all, $(info.nr))
$(info.html): info/emp2html.pl
-info.ps: info/TROFF.MAC info/INFO.MAC $(ttop) $(tsubj) $(tsrc)
+info.ps: info/TROFF.MAC info/INFO.MAC info/TOP.t $(tsubj) $(tsrc)
groff $^ >$@
# Distributing
.PHONY: dist-source
dist-source: $(src_distgen)
+ $(tarball) $(TARNAME) $(version) -C $(srcdir) $(src_distgen) $(src)
+
ifeq ($(revctrl),git)
- echo "src := $(src)" >$(srcdir)/sources.mk
+.PHONY: $(srcdir)/sources.mk
+$(srcdir)/sources.mk:
+ $(call quiet-command,echo "src := $(src)" >$@,GEN $@)
endif
- $(tarball) $(TARNAME)-$(VERSION) -C $(srcdir) $(src_distgen) $(src) sources.mk
.PHONY: dist-client
dist-client: $(cli_distgen)
- $(tarball) $(TARNAME)-client-$(VERSION) \
+ $(tarball) $(TARNAME)-client $(version) \
-C $(srcdir)/src/client \
$(notdir $(filter src/client/%, $(src)) $(cli_distgen)) \
- -C $(srcdir)/include proto.h version.h \
+ -C $(srcdir)/include fnameat.h proto.h version.h \
-C $(srcdir)/src/lib/global version.c \
+ -C $(srcdir)/src/lib/gen fnameat.c \
-C $(srcdir)/src/lib $(addprefix w32/, $(client/w32)) \
-C $(srcdir)/man empire.6 \
-C $(srcdir)/build-aux install-sh \
.PHONY: dist-info
dist-info: info html
- $(tarball) $(TARNAME)-info-text-$(VERSION) -C info.nr $(info)
- $(tarball) $(TARNAME)-info-html-$(VERSION) -C info.html $(addsuffix .html, $(info))
+ $(tarball) $(TARNAME)-info-text $(version) -C info.nr $(info)
+ $(tarball) $(TARNAME)-info-html $(version) -C info.html $(addsuffix .html, $(info))
# Dependencies
cd $(dir $@) && autoheader
touch $@
- $(srcdir)/src/client/aclocal.m4: m4/ax_lib_socket_nsl.m4 m4/my_terminfo.m4 m4/my_windows_api.m4
+ $(srcdir)/src/client/aclocal.m4: m4/ax_lib_socket_nsl.m4 m4/my_lib_readline.m4 m4/my_terminfo.m4 m4/my_windows_api.m4
cat $^ >$@
#
# Empire - A multi-player, client/server Internet based war game.
-# Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+# Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
# Ken Stevens, Steve McClure, Markus Armbruster
#
# Empire is free software: you can redistribute it and/or modify
# configure.ac: Autoconf input file
#
# Known contributors to this file:
-# Markus Armbruster, 2005-2015
+# Markus Armbruster, 2005-2016
#
# Process this file with autoconf to produce a configure script.
# POSIX, and when something breaks on some oddball machine, see
# whether it's worth fixing.
-AC_PREREQ(2.64)
-AC_INIT([Wolfpack Empire], [4.3.34], [wolfpack@wolfpackempire.com], [empire],
+AC_PREREQ(2.69)
+AC_INIT([Wolfpack Empire],
+ m4_esyscmd([build-aux/git-version-gen .tarball-version]),
+ [wolfpack@wolfpackempire.com], [empire],
[http://www.wolfpackempire.com/])
AC_CONFIG_SRCDIR([include/combat.h])
AC_CONFIG_AUX_DIR([build-aux])
AC_CHECK_PROG(NROFF, groff, [GROFF_NO_SGR= groff -Tascii -U], nroff)
# not really a check for a program, but close enough
-if test -d $srcdir/.git; then revctrl=git
+if test -d $srcdir/.git
+then revctrl=git
else revctrl=
fi
+if test "$revctrl" && test -r .tarball-version
+then AC_MSG_ERROR([.tarball-version must not exist])
+fi
AC_SUBST(revctrl,$revctrl)
# Not a program, but need to check this early
LIBS="$LIBS_SOCKETS $LIBS"
AX_LIB_SOCKET_NSL
LIBS_server="$LIBS"
+ MY_WITH_READLINE
### Checks for header files
AC_MSG_NOTICE([])
AC_MSG_NOTICE([-= Configuration summary =-])
AC_MSG_NOTICE([Thread package: $empthread])
+ AC_MSG_NOTICE([ readline: $with_readline])
AC_MSG_NOTICE([ terminfo: $with_terminfo])
AC_MSG_NOTICE([ EMPIREHOST: $EMPIREHOST])
AC_MSG_NOTICE([ EMPIREPORT: $EMPIREPORT])
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
extern int load_comm_ok(struct sctstr *, natid, i_type, int);
extern void gift(natid, natid, void *, char *);
extern int display_mark(i_type, int);
-extern int count_pop(int);
extern int line_of_sight(char **rad, int ax, int ay, int bx, int by);
extern void plane_sona(struct emp_qelem *, int, int, struct shiplist **);
extern char *prsub(struct shpstr *);
int torp(void);
int trad(void);
int tran(void);
-int trea(void);
int turn(void);
int upda(void);
int upgr(void);
int wipe(void);
int work(void);
int xdump(void);
-int xedit(void);
int zdon(void);
/*
/* res_pop.c */
extern int max_population(float, int, int);
extern int max_pop(float, struct sctstr *);
+extern int max_workers(float, struct sctstr *);
/* stmtch.c */
/* in match.h */
/* type.c */
/* disassoc.c */
extern int disassoc(void);
/* fnameat.c */
- extern char *fnameat(const char *, const char *);
- extern FILE *fopenat(const char *, const char *, const char *);
+ /* in fnameat.h */
/* fsize.c */
extern int fsize(int);
extern int blksize(int);
/* coastal.c */
extern void set_coastal(struct sctstr *, int, int);
/* control.c */
+extern double security_strength(struct sctstr *, int *);
extern int military_control(struct sctstr *);
extern int abandon_askyn(struct sctstr *, i_type, int, struct ulist *);
extern int would_abandon(struct sctstr *, i_type, int, struct ulist *);
extern int detonate(struct nukstr *, coord, coord, int);
/* disloan.c */
extern int disloan(int, struct lonstr *);
-/* distrea.c */
-extern int distrea(int, struct trtstr *);
/* fileinit.c */
extern void ef_init_srv(int);
extern void ef_fin_srv(void);
/* list.c */
extern int shipsatxy(coord, coord, int, int, int);
extern int carriersatxy(coord, coord, natid);
-extern int unitsatxy(coord, coord, int, int, int);
+extern int unitsatxy(coord, coord, int, int);
extern int planesatxy(coord, coord, int, int);
extern int asw_shipsatxy(coord, coord, int, int, struct plnstr *,
struct shiplist **);
extern void print_shiplist(struct shiplist *);
extern int has_units(coord, coord, natid);
extern int adj_units(coord, coord, natid);
-extern int islist(char *);
/* maps.c */
/* in map.h */
/* mission.c */
extern void radmap(int, int, int, double, int, double);
extern void rad_map_set(natid, int, int, int, double, int);
/* rej.c */
-extern void setrel(natid, natid, int);
-extern void setcont(natid, natid, int);
-extern void setrej(natid, natid, int, int);
+/* in nat.h */
/* retreat.c */
/* in retreat.h */
/* sarg.c */
extern void takeover_plane(struct plnstr *, natid);
/* trdsub.c */
/* in trade.h */
-/* trechk.c */
-extern int trechk(natid, natid, int);
/* whatitem.c */
/* in item.h */
/* wu.c */
/*
* src/lib/update/ *.c
*/
-/* age.c */
-extern int age_people(int, int);
-extern void age_levels(int);
-/* anno.c */
-extern void delete_old_announcements(void);
-/* bp.c */
-/* in budg.h */
-/* deliver.c */
-extern void dodeliver(struct sctstr *);
-/* distribute.c */
-extern int dodistribute(struct sctstr *, int, double);
-/* finish.c */
-extern void finish_sects(int);
-/* human.c */
-extern int new_work(struct sctstr *, int);
-extern int do_feed(struct sctstr *, struct natstr *, short *, int *, int);
-extern int feed_people(short *, int);
-extern double food_needed(short *, int);
-extern int famine_victims(short *, int);
-/* land.c */
-extern int prod_land(int, int, struct bp *, int);
-/* main.c */
-/* in server.h */
-/* material.c */
-/* in budg.h */
-/* mobility.c */
-extern void mob_sect(void);
-extern void mob_ship(void);
-extern void mob_land(void);
-extern void mob_plane(void);
-extern void sct_do_upd_mob(struct sctstr *sp);
-extern void shp_do_upd_mob(struct shpstr *sp);
-extern void lnd_do_upd_mob(struct lndstr *lp);
-extern void pln_do_upd_mob(struct plnstr *pp);
-/* move_sat.c */
-extern void move_sat(struct plnstr *);
-/* nat.c */
-extern void prod_nat(int);
-/* nxtitemp.c */
-/* in nsc.h */
-/* plague.c */
-extern void do_plague(struct sctstr *, struct natstr *, int);
-extern int plague_people(struct natstr *, short *, int *, int *, int);
-/* plane.c */
-extern int prod_plane(int, int, struct bp *, int);
-/* populace.c */
-extern void populace(struct natstr *, struct sctstr *, int);
-extern int total_work(int, int, int, int, int, int);
-/* prepare.c */
-extern void tax(struct sctstr *, struct natstr *, int, int *, int *,
- int *, int *);
-extern int upd_slmilcosts(natid, int);
-extern void prepare_sects(int, struct bp *);
-extern int bank_income(struct sctstr *, int);
-/* produce.c */
-extern int produce(struct natstr *, struct sctstr *, short *, int, int,
- int, int *, int *);
-extern int prod_materials_cost(struct pchrstr *, short[], int *);
-extern int prod_resource_limit(struct pchrstr *, unsigned char *);
-extern double prod_eff(int, float);
-/* removewants.c */
-extern int update_removewants(void);
-/* revolt.c */
-extern void revolt(struct sctstr *);
-extern void guerrilla(struct sctstr *);
-/* sect.c */
-extern void do_fallout(struct sctstr *, int);
-extern void spread_fallout(struct sctstr *, int);
-extern void decay_fallout(struct sctstr *, int);
-extern void produce_sect(int, int, struct bp *, int[][2]);
-/* ship.c */
-extern int prod_ship(int, int, struct bp *, int);
+/* in update.h */
/*
* src/server
#
# Empire - A multi-player, client/server Internet based war game.
-# Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+# Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
# Ken Stevens, Steve McClure, Markus Armbruster
#
# Empire is free software: you can redistribute it and/or modify
# Makefile.in: Makefile template for configure
#
# Known contributors to this file:
- # Markus Armbruster, 2005-2013
+ # Markus Armbruster, 2005-2015
#
CC = @CC@
VPATH = @srcdir@
prog = empire$E
- obj = expect.$O host.$O ipglob.$O linebuf.$O login.$O main.$O play.$O \
- ringbuf.$O secure.$O servcmd.$O termlib.$O version.$O $(LIBOBJS)
+ obj = expect.$O fnameat.$O host.$O ipglob.$O linebuf.$O login.$O \
+ main.$O play.$O ringbuf.$O secure.$O servcmd.$O termlib.$O version.$O \
+ $(LIBOBJS)
all: $(prog)
host.$O: misc.h
linebuf.$O: linebuf.h
login.$O: misc.h proto.h
- main.$O: misc.h version.h
+ main.$O: fnameat.h misc.h version.h
play.$O: linebuf.h misc.h proto.h ringbuf.h secure.h
ringbuf.$O: ringbuf.h
secure.$O: ringbuf.h secure.h
#
# Empire - A multi-player, client/server Internet based war game.
-# Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+# Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
# Ken Stevens, Steve McClure, Markus Armbruster
#
# Empire is free software: you can redistribute it and/or modify
# configure.ac: Autoconf input file
#
# Known contributors to this file:
-# Markus Armbruster, 2005-2015
+# Markus Armbruster, 2005-2016
#
# Process this file with autoconf to produce a configure script.
# POSIX, and when something breaks on some oddball machine, see
# whether it's worth fixing.
-AC_PREREQ(2.64)
-AC_INIT([Empire Client], [4.3.34], [wolfpack@wolfpackempire.com],,
+AC_PREREQ(2.69)
+AC_INIT([Wolfpack Empire Client],
+ m4_esyscmd([cat .tarball-version]),
+ [wolfpack@wolfpackempire.com],,
[http://www.wolfpackempire.com/])
AC_CONFIG_SRCDIR([empire.6])
AC_CONFIG_HEADERS([config.h])
AC_LIBOBJ([w32/w32io])
AC_LIBOBJ([w32/w32sockets])
fi
+ MY_WITH_READLINE
### Checks for header files.
### Output
+AC_DEFINE_UNQUOTED(VERSION, "`cat .tarball-version`", [Tarball version])
+
AC_CONFIG_FILES([Makefile ipglob.c])
AC_OUTPUT
AC_MSG_NOTICE([])
AC_MSG_NOTICE([-= Configuration summary =-])
+ AC_MSG_NOTICE([ readline: $with_readline])
AC_MSG_NOTICE([ terminfo: $with_terminfo])
AC_MSG_NOTICE([ EMPIREHOST: $EMPIREHOST])
AC_MSG_NOTICE([ EMPIREPORT: $EMPIREPORT])
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* Dave Pare, 1986
* Steve McClure, 1998
* Ron Koenderink, 2004-2007
- * Markus Armbruster, 2005-2010
+ * Markus Armbruster, 2005-2015
* Tom Dickson-Hunt, 2010
+ * Martin Haukeli, 2015
*/
#include <config.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 "fnameat.h"
#include "misc.h"
#include "version.h"
struct passwd {
char *pw_name;
+ char *pw_dir;
};
static struct passwd *w32_getpw(void);
" -r Restricted mode, no redirections\n"
" -s [HOST:]PORT Specify server HOST and PORT\n"
" -u Use UTF-8\n"
+ #ifdef HAVE_LIBREADLINE
+ " -H FILE Load and save command history from FILE\n"
+ " (default ~/.empire_history with -r, none without -r)\n"
+ #endif /* HAVE_LIBREADLINE */
" -h display this help and exit\n"
" -v display version information and exit\n",
program_name);
{
int opt;
char *auxfname = NULL;
+ char *history_file = NULL;
int send_kill = 0;
char *host = NULL;
char *port = NULL;
char *country;
char *passwd;
char *uname;
+ char *udir;
char *colon;
int sock;
- while ((opt = getopt(argc, argv, "2:krs:uhv")) != EOF) {
+ while ((opt = getopt(argc, argv, "2:H:krs:uhv")) != EOF) {
switch (opt) {
case '2':
auxfname = optarg;
break;
+ #ifdef HAVE_LIBREADLINE
+ case 'H':
+ history_file = optarg;
+ break;
+ #endif /* HAVE_LIBREADLINE */
case 'k':
send_kill = 1;
break;
if (!host)
host = empirehost;
uname = getenv("LOGNAME");
- if (uname == NULL) {
+ udir = getenv("HOME");
+ if (!uname || !udir) {
struct passwd *pwd;
pwd = getpwuid(getuid());
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);
sock = tcp_connect(host, port);
+ if (!restricted && !history_file)
+ history_file = ".empire_history";
+ if (history_file)
+ history_file = fnameat(history_file, udir);
+
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
+ * 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;
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;
}
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
*
* Known contributors to this file:
* Steve McClure, 1998
+ * Markus Armbruster, 2004-2017
*/
#ifndef MISC_H
extern char empirehost[];
extern char empireport[];
extern int eight_bit_clean;
- extern int input_fd;
- extern int send_eof;
extern FILE *auxfp;
extern int restricted;
int expect(int s, int match, char *buf);
int tcp_connect(char *, char *);
int login(int s, char *uname, char *cname, char *cpass, int kill_proc, int);
- int play(int);
+ int play(int, char *);
+ void prompt(int, char *, char *);
void sendcmd(int s, char *cmd, char *arg);
- void servercmd(int, char *, int);
+ int servercmd(int, char *, int);
void outch(char);
#ifdef _MSC_VER
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* play.c: Playing the game
*
* Known contributors to this file:
- * Markus Armbruster, 2007-2010
+ * Markus Armbruster, 2007-2017
* Ron Koenderink, 2007-2009
+ * Martin Haukeli, 2015
*/
#include <config.h>
#include "ringbuf.h"
#include "secure.h"
+ #ifdef HAVE_LIBREADLINE
+ #include <readline/readline.h>
+ #include <readline/history.h>
+ #endif
+
+ #define EOF_COOKIE "ctld\n"
+ #define INTR_COOKIE "aborted\n"
+
+ /*
+ * Player input file descriptor
+ * 0 while reading interactive input
+ * >0 while reading a batch file
+ * <0 during error handling
+ */
+ static int input_fd;
+
+ static volatile sig_atomic_t send_intr; /* need to send INTR_COOKIE */
+
#ifdef _WIN32
static CRITICAL_SECTION signal_critical_section;
static LPCRITICAL_SECTION signal_critical_section_ptr = NULL;
#define sysdep_stdin_init() ((void)0)
#endif
- #define EOF_COOKIE "ctld\n"
- #define INTR_COOKIE "aborted\n"
-
- int input_fd;
- int send_eof; /* need to send EOF_COOKIE */
- static volatile sig_atomic_t send_intr; /* need to send INTR_COOKIE */
-
/*
* Receive and process server output from @sock.
* Return number of characters received on success, -1 on error.
static struct lbuf lbuf;
char buf[4096];
ssize_t n;
- int i, ch, len;
+ int i, ch, len, fd;
char *line;
n = read(sock, buf, sizeof(buf));
len = lbuf_putc(&lbuf, ch);
if (len) {
line = lbuf_line(&lbuf);
- servercmd(id, line, len);
+ fd = servercmd(id, line, len);
+ if (fd < 0) {
+ /* failed execute */
+ if (input_fd)
+ close(input_fd);
+ input_fd = 0;
+ send_intr = 1;
+ } else if (fd > 0) {
+ /* successful execute, switch to batch file */
+ assert(!input_fd);
+ input_fd = fd;
+ }
lbuf_init(&lbuf);
state = SCANNING_ID;
}
return n;
}
+ #ifdef HAVE_LIBREADLINE
+ static int use_readline;
+ static char *input_from_rl;
+ static int has_rl_input;
+
+ static void
+ input_handler(char *line)
+ {
+ input_from_rl = line;
+ has_rl_input = 1;
+ if (line && *line)
+ add_history(line);
+ }
+
+ static int
+ ring_from_rl(struct ring *inbuf)
+ {
+ size_t len;
+ int n;
+
+ assert(has_rl_input && input_from_rl);
+
+ len = strlen(input_from_rl);
+ n = ring_space(inbuf);
+ assert(n);
+
+ if (len >= (size_t)n) {
+ ring_putm(inbuf, input_from_rl, n);
+ memmove(input_from_rl, input_from_rl + n, len - n + 1);
+ } else {
+ ring_putm(inbuf, input_from_rl, len);
+ ring_putc(inbuf, '\n');
+ free(input_from_rl);
+ has_rl_input = 0;
+ n = len + 1;
+ }
+
+ return n;
+ }
+ #endif /* HAVE_LIBREADLINE */
+
/*
- * Receive command input from @fd into @inbuf.
+ * Receive player input from @fd into @inbuf.
* Return 1 on receipt of input, zero on EOF, -1 on error.
*/
static int
recv_input(int fd, struct ring *inbuf)
{
- static struct lbuf cmdbuf;
- int n, i, ch;
- char *line;
+ int n;
int res = 1;
- n = ring_from_file(inbuf, fd);
+ #ifdef HAVE_LIBREADLINE
+ if (fd == 0 && use_readline) {
+ if (!has_rl_input)
+ rl_callback_read_char();
+ if (!has_rl_input)
+ return 1;
+ if (input_from_rl) {
+ n = ring_from_rl(inbuf);
+ } else
+ n = 0;
+ } else
+ #endif
+ n = ring_from_file(inbuf, fd);
if (n < 0)
return -1;
if (n == 0) {
- /* EOF on input */
- if (lbuf_len(&cmdbuf)) {
- /* incomplete line */
- ring_putc(inbuf, '\n');
- n++;
- }
/*
* Can't put EOF cookie into INBUF here, it may not fit.
* Leave it to caller.
res = 0;
}
- /* copy input to AUXFP etc. */
- for (i = -n; i < 0; i++) {
- ch = ring_peek(inbuf, i);
+ return res;
+ }
+
+ static int
+ send_input(int fd, struct ring *inbuf)
+ {
+ struct iovec iov[2];
+ int cnt, i, ch;
+ ssize_t res;
+
+ cnt = ring_to_iovec(inbuf, iov);
+ res = writev(fd, iov, cnt);
+ if (res < 0)
+ return res;
+
+ /* Copy input to @auxfp etc. */
+ for (i = 0; i < res; i++) {
+ ch = ring_getc(inbuf);
assert(ch != EOF);
- if (ch != '\r' && lbuf_putc(&cmdbuf, ch) > 0) {
- line = lbuf_line(&cmdbuf);
- save_input(line);
- lbuf_init(&cmdbuf);
- }
+ if (ch != '\r')
+ save_input(ch);
if (auxfp)
putc(ch, auxfp);
}
+ #ifdef HAVE_LIBREADLINE
+ if (fd == 0 && use_readline && has_rl_input && input_from_rl)
+ ring_from_rl(inbuf);
+ #endif
+
return res;
}
/*
* Play on @sock.
+ * @history_file is the name of the history file, or null.
* The session must be in the playing phase.
* Return 0 when the session ended, -1 on error.
*/
int
- play(int sock)
+ play(int sock, char *history_file)
{
/*
* Player input flows from INPUT_FD through recv_input() into ring
struct ring inbuf; /* input buffer, draining to SOCK */
int eof_fd0; /* read fd 0 hit EOF? */
int partial_line_sent; /* partial input line sent? */
+ int send_eof; /* need to send EOF_COOKIE */
fd_set rdfd, wrfd;
int n;
+ int ret = -1;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
+ #ifdef HAVE_LIBREADLINE
+ if (isatty(0)) {
+ use_readline = 1;
+ rl_already_prompted = 1;
+ rl_readline_name = "Empire";
+ if (history_file)
+ read_history(history_file);
+ rl_bind_key('\t', rl_insert); /* Disable tab completion */
+ rl_callback_handler_install("", input_handler);
+ }
+ #endif /* HAVE_LIBREADLINE */
ring_init(&inbuf);
eof_fd0 = partial_line_sent = send_eof = send_intr = 0;
/*
* Want to read player input only when we don't need to send
- * cookies, and INPUT_FD is still open, and INBUF can accept
+ * cookies, haven't reached EOF on fd 0, and @inbuf can accept
* some.
*/
- if (!send_intr && !send_eof && input_fd >= 0 && ring_space(&inbuf))
+ if (!send_intr && !send_eof && (input_fd || !eof_fd0)
+ && ring_space(&inbuf))
FD_SET(input_fd, &rdfd);
/* Want to send player input only when we have something */
if (send_intr || send_eof || ring_len(&inbuf))
if (n < 0) {
if (errno != EINTR) {
perror("select");
- return -1;
+ break;
}
}
partial_line_sent = 0;
if (send_eof && !partial_line_sent
&& ring_putm(&inbuf, EOF_COOKIE, sizeof(EOF_COOKIE) - 1) >= 0)
- send_eof--;
+ send_eof = 0;
if (send_intr && !partial_line_sent
&& ring_putm(&inbuf, INTR_COOKIE, sizeof(INTR_COOKIE) - 1) >= 0) {
send_intr = 0;
if (input_fd) {
/* execute aborted, switch back to fd 0 */
close(input_fd);
- input_fd = eof_fd0 ? -1 : 0;
+ input_fd = 0;
}
}
-
if (n < 0)
continue;
/* read player input */
- if (input_fd >= 0 && FD_ISSET(input_fd, &rdfd)) {
+ if (FD_ISSET(input_fd, &rdfd) && ring_space(&inbuf)) {
n = recv_input(input_fd, &inbuf);
- if (n < 0) {
- perror("read stdin"); /* FIXME stdin misleading, could be execing */
- n = 0;
- }
- if (n == 0) {
- /* EOF on input */
- send_eof++;
+ if (n <= 0) {
if (input_fd) {
/* execute done, switch back to fd 0 */
+ if (n < 0) {
+ perror("read batch file");
+ send_intr = 1;
+ } else
+ send_eof = 1;
close(input_fd);
- input_fd = eof_fd0 ? -1 : 0;
+ input_fd = 0;
} else {
/* stop reading input, drain socket ring buffers */
+ if (n < 0)
+ perror("read stdin");
+ send_eof = 1;
eof_fd0 = 1;
- input_fd = -1;
sa.sa_handler = SIG_DFL;
sigaction(SIGINT, &sa, NULL);
+ send_intr = 0;
}
- } else
+ } else if (ring_len(&inbuf) > 0)
partial_line_sent = ring_peek(&inbuf, -1) != '\n';
}
/* send it to the server */
if (FD_ISSET(sock, &wrfd)) {
- n = ring_to_file(&inbuf, sock);
+ n = send_input(sock, &inbuf);
if (n < 0) {
perror("write socket");
- return -1;
+ break;
}
}
n = recv_output(sock);
if (n < 0) {
perror("read socket");
- return -1;
+ break;
+ }
+ if (n == 0) {
+ ret = 0;
+ break;
}
- if (n == 0)
- return 0;
}
}
+
+ #ifdef HAVE_LIBREADLINE
+ if (use_readline) {
+ rl_callback_handler_remove();
+ if (history_file)
+ write_history(history_file);
+ }
+ #endif
+ return ret;
+ }
+
+ void
+ prompt(int code, char *prompt, char *teles)
+ {
+ char pr[1024];
+
+ snprintf(pr, sizeof(pr), "%s%s", teles, prompt);
+ #ifdef HAVE_LIBREADLINE
+ if (use_readline) {
+ rl_set_prompt(pr);
+ rl_forced_update_display();
+ } else
+ #endif /* HAVE_LIBREADLINE */
+ {
+ printf("%s", pr);
+ fflush(stdout);
+ }
+ if (auxfp) {
+ fprintf(auxfp, "%s%s", teles, prompt);
+ fflush(auxfp);
+ }
}
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* ringbuf.c: Simple ring buffer
*
* Known contributors to this file:
- * Markus Armbruster, 2007-2009
+ * Markus Armbruster, 2007-2017
*/
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
- #include <sys/uio.h>
#include "ringbuf.h"
/*
assert(-RING_SIZE - 1 <= n && n <= RING_SIZE);
- idx = n >= 0 ? r->cons + n : r->prod - -n;
- if (idx < r->cons && idx >= r->prod)
- return EOF;
+ if (n >= 0) {
+ idx = r->cons + n;
+ if (idx >= r->prod)
+ return EOF;
+ } else {
+ /* Beware, r->prod - -n can wrap around, avoid that */
+ if (r->prod < r->cons + -n)
+ return EOF;
+ idx = r->prod - -n;
+ }
+
return r->buf[idx % RING_SIZE];
}
/*
* Search the ring buffer for zero-terminated string S.
- * If found, return a non-negative value referring to the beginning of
- * S in the buffer when passed to ring_peek(). Else return -1.
+ * Start at the @(n+1)-th byte to be gotten.
+ * If found, return the number of bytes in the buffer before S.
+ * Else return -1.
*/
int
- ring_search(struct ring *r, char *s)
+ ring_search(struct ring *r, char *s, int n)
{
size_t len = strlen(s);
size_t i, j;
- for (i = r->cons; i + len <= r->prod; i++) {
+ for (i = r->cons + n; i + len <= r->prod; i++) {
for (j = 0; s[j] && s[j] == (char)r->buf[(i + j) % RING_SIZE]; j++)
;
if (!s[j])
}
/*
- * Drain ring buffer to file referred by file descriptor @fd.
- * If ring buffer is already empty, do nothing and return 0.
- * Else attempt to write complete contents with writev(), and return
- * its value.
+ * Set up @iov[] to describe complete contents of ring buffer.
+ * @iov[] must have at least two elements.
+ * Return number of elements used (zero for an empty ring buffer).
*/
int
- ring_to_file(struct ring *r, int fd)
+ ring_to_iovec(struct ring *r, struct iovec iov[])
{
unsigned cons = r->cons % RING_SIZE;
unsigned prod = r->prod % RING_SIZE;
- struct iovec iov[2];
- int cnt;
- ssize_t res;
if (r->cons == r->prod)
return 0;
iov[0].iov_base = r->buf + cons;
- if (prod <= cons) {
- /* r->buf[cons..] */
- iov[0].iov_len = RING_SIZE - cons;
- /* r->buf[..prod-1] */
- iov[1].iov_base = r->buf;
- iov[1].iov_len = prod;
- cnt = 2;
- } else {
+ if (prod > cons) {
/* r->buf[cons..prod-1] */
iov[0].iov_len = prod - cons;
- cnt = 1;
+ return 1;
}
- res = writev(fd, iov, cnt);
- if (res < 0)
- return res;
- r->cons += res;
- return res;
+ /* r->buf[cons..] */
+ iov[0].iov_len = RING_SIZE - cons;
+ /* r->buf[..prod-1] */
+ iov[1].iov_base = r->buf;
+ iov[1].iov_len = prod;
+ return 2;
}
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* ringbuf.h: Simple ring buffer
*
* Known contributors to this file:
- * Markus Armbruster, 2007
+ * Markus Armbruster, 2007-2017
*/
#ifndef RINGBUF_H
#define RINGBUF_H
#include <stddef.h>
+ #include <sys/uio.h>
#define RING_SIZE 4096
extern int ring_putc(struct ring *, unsigned char);
extern int ring_putm(struct ring *, void *, size_t);
extern void ring_discard(struct ring *, int);
- extern int ring_search(struct ring *, char *);
+ extern int ring_search(struct ring *, char *, int);
extern int ring_from_file(struct ring *, int fd);
- extern int ring_to_file(struct ring *, int fd);
+ extern int ring_to_iovec(struct ring *, struct iovec[]);
#endif
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* secure.c: Check redir etc. to protect against tampering deity
*
* Known contributors to this file:
- * Markus Armbruster, 2007
+ * Markus Armbruster, 2007-2017
*/
#include <config.h>
#include <assert.h>
+ #include <ctype.h>
+ #include <stdio.h>
#include <string.h>
#include "ringbuf.h"
#include "secure.h"
static struct ring recent_input;
- static size_t saved_bytes;
/*
- * Remember line of input @inp for a while.
- * It must end with a newline.
- * Return value is suitable for forget_input(): it makes it forget all
- * input up to and including this line.
+ * Remember input @inp for a while.
*/
- size_t
- save_input(char *inp)
+ void
+ save_input(char inp)
{
- size_t len = strlen(inp);
int eol;
- assert(len && inp[len - 1] == '\n');
-
- while (ring_putm(&recent_input, inp, len) < 0) {
- eol = ring_search(&recent_input, "\n");
+ while (ring_putc(&recent_input, inp) < 0) {
+ eol = ring_search(&recent_input, "\n", 0);
assert(eol >= 0);
ring_discard(&recent_input, eol + 1);
}
- saved_bytes += len;
- return saved_bytes;
}
/*
* Can you still remember a line of input that ends with @tail?
* It must end with a newline.
- * Return non-zero iff @tail can be remembered.
- * Passing that value to forget_input() will forget all input up to
- * and including this line.
*/
- size_t
+ int
seen_input(char *tail)
{
size_t len = strlen(tail);
- size_t remembered = ring_len(&recent_input);
- int dist;
assert(len && tail[len - 1] == '\n');
-
- dist = ring_search(&recent_input, tail);
- if (dist < 0)
- return 0;
-
- assert(dist + len <= remembered && remembered <= saved_bytes);
- return saved_bytes - remembered + dist + len;
+ return ring_search(&recent_input, tail, 0) >= 0;
}
/*
- * Forget remembered input up to @seen.
- * @seen should be obtained from save_input() or seen_input().
+ * Can you still remember input that looks like an execute @arg?
+ * @arg must end with a newline.
*/
- void
- forget_input(size_t seen)
+ int
+ seen_exec_input(char *arg)
{
- size_t forgotten = saved_bytes - ring_len(&recent_input);
+ size_t len = strlen(arg);
+ int n, i, j, ch;
+ unsigned char buf[RING_SIZE + 1];
+
+ assert(len && arg[len - 1] == '\n');
+
+ n = 1;
+ for (;;) {
+ /* find next line ending with arg */
+ n = ring_search(&recent_input, arg, n + 1);
+ if (n <= 0)
+ return 0;
- assert(seen);
+ /* extract command (same or previous line) */
+ i = n - 1;
+ if (ring_peek(&recent_input, i) == '\n')
+ i--;
+ j = sizeof(buf);
+ buf[--j] = 0;
+ for (; i >= 0 && (ch = ring_peek(&recent_input, i)) != '\n'; i--)
+ buf[--j] = ch;
- if (seen > forgotten) {
- assert(ring_peek(&recent_input, seen - forgotten - 1) == '\n');
- ring_discard(&recent_input, seen - forgotten);
+ /* compare command */
+ for (; isspace(buf[j]); j++) ;
+ for (i = j; buf[i] && !isspace(buf[i]); i++) ;
+ if (i - j >= 2 && !strncmp("execute", (char *)buf + j, i - j))
+ return 1;
}
}
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* secure.h: Check redir etc. to protect against tampering deity
*
* Known contributors to this file:
- * Markus Armbruster, 2007-2009
+ * Markus Armbruster, 2007-2017
*/
#ifndef SECURE_H
#include <stddef.h>
- extern size_t save_input(char *);
- extern size_t seen_input(char *);
- extern void forget_input(size_t);
+ extern void save_input(char);
+ extern int seen_input(char *);
+ extern int seen_exec_input(char *);
#endif
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* Dave Pare, 1989
* Steve McClure, 1998
* Ron Koenderink, 2005
- * Markus Armbruster, 2005-2010
+ * Markus Armbruster, 2005-2017
*/
#include <config.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
+ #include <unistd.h>
#include "misc.h"
#include "proto.h"
#include "secure.h"
static FILE *redir_fp;
static int redir_is_pipe;
static int executing;
- static size_t input_to_forget;
- static void prompt(int, char *, char *);
static void doredir(char *p);
static void dopipe(char *p);
static int doexecute(char *p);
- void
+ int
servercmd(int code, char *arg, int len)
{
static int nmin, nbtu, fd;
switch (code) {
case C_PROMPT:
if (sscanf(arg, "%d %d", &nmin, &nbtu) != 2) {
- fprintf(stderr, "prompt: bad server prompt %s\n", arg);
+ fprintf(stderr, "Warning: server sent malformed prompt %s",
+ arg);
}
snprintf(the_prompt, sizeof(the_prompt), "[%d:%d] Command : ",
nmin, nbtu);
(void)fclose(redir_fp);
redir_fp = NULL;
}
- if (input_to_forget) {
- forget_input(input_to_forget);
- input_to_forget = 0;
- }
+ outch('\n');
prompt(code, the_prompt, teles);
executing = 0;
break;
break;
case C_EXECUTE:
fd = doexecute(arg);
- if (fd < 0)
- send_eof++;
- else {
- input_fd = fd;
+ if (fd >= 0)
executing = 1;
- }
- break;
+ return fd;
case C_EXIT:
printf("Exit: %s", arg);
if (auxfp)
if (arg[0] != '\n') {
snprintf(teles, sizeof(teles), "(%.*s) ", len - 1, arg);
if (!redir_fp) {
+ outch('\n');
putchar('\07');
prompt(code, the_prompt, teles);
}
assert(0);
break;
}
- }
- static void
- prompt(int code, char *prompt, char *teles)
- {
- char *nl;
-
- nl = code == C_PROMPT || code == C_INFORM ? "\n" : "";
- printf("%s%s%s", nl, teles, prompt);
- fflush(stdout);
- if (auxfp) {
- fprintf(auxfp, "%s%s%s", nl, teles, prompt);
- fflush(auxfp);
- }
+ return 0;
}
static char *
}
static int
- redir_authorized(char *arg, char *attempt, int expected)
+ common_authorized(char *arg, char *attempt)
{
- size_t seen = seen_input(arg);
-
if (restricted) {
fprintf(stderr, "Can't %s in restricted mode\n", attempt);
return 0;
fprintf(stderr, "Can't %s in a batch file\n", attempt);
return 0;
}
+ return 1;
+ }
- if (!expected) {
- fprintf(stderr, "WARNING! Server attempted to %s unexpectedly\n",
- attempt);
+ static int
+ redir_authorized(char *arg, char *attempt)
+ {
+ if (redir_fp) {
+ fprintf(stderr, "Warning: dropped conflicting %s %s",
+ attempt, arg);
return 0;
}
- if (!seen || (input_to_forget && input_to_forget != seen)) {
- fprintf(stderr, "WARNING! Server attempted to %s %s\n",
+ if (!seen_input(arg)) {
+ fprintf(stderr, "Warning: server attempted to %s %s",
attempt, arg);
return 0;
}
- input_to_forget = seen;
- return 1;
+
+ return common_authorized(arg, attempt);
+ }
+
+ static int
+ exec_authorized(char *arg)
+ {
+ if (!seen_exec_input(arg)) {
+ fprintf(stderr,
+ "Warning: server attempted to execute batch file %s", arg);
+ return 0;
+ }
+
+ return common_authorized(arg, "execute batch file");
}
static void
int mode;
int fd;
- if (!redir_authorized(p, "redirect to file", !redir_fp))
+ if (!redir_authorized(p, "redirect to file"))
return;
if (*p++ != '>') {
- fprintf(stderr, "WARNING! Weird redirection %s", p);
+ fprintf(stderr, "Warning: dropped weird redirection %s", p);
return;
}
static void
dopipe(char *p)
{
- if (!redir_authorized(p, "pipe to shell command", !redir_fp))
+ if (!redir_authorized(p, "pipe to shell command"))
return;
if (*p++ != '|') {
- fprintf(stderr, "WARNING! Weird pipe %s", p);
+ fprintf(stderr, "Warning: dropped weird pipe %s", p);
return;
}
return;
}
+ /* strip newline */
+ p[strlen(p) - 1] = 0;
+
redir_is_pipe = 1;
+ errno = 0;
if ((redir_fp = popen(p, "w")) == NULL) {
- fprintf(stderr, "Can't redirect to pipe %s: %s\n",
- p, strerror(errno));
+ fprintf(stderr, "Can't redirect to pipe %s%s%s\n",
+ p, errno ? ": " : "", errno ? strerror(errno) : "");
}
}
{
int fd;
- if (!redir_authorized(p, "execute batch file", 1))
+ if (!exec_authorized(p))
return -1;
p = fname(p);
}
if ((fd = open(p, O_RDONLY)) < 0) {
- fprintf(stderr, "Can't open execute file %s: %s\n",
+ fprintf(stderr, "Can't open batch file %s: %s\n",
p, strerror(errno));
return -1;
}
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
#include <errno.h>
#include <stdio.h>
#include "file.h"
+ #include "fnameat.h"
#include "optlist.h"
#include "prototypes.h"
#include "xdump.h"
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
#include <string.h>
#include <unistd.h>
+ #include "fnameat.h"
#include "misc.h"
#include "optlist.h"
#include "prototypes.h"
/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2016, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
#include <config.h>
#include <errno.h>
- #include "prototypes.h"
+ #include <stdlib.h>
+ #include <string.h>
+ #include "fnameat.h"
static int fname_is_abs(const char *);