From: Markus Armbruster Date: Sat, 8 Jul 2017 18:43:29 +0000 (+0200) Subject: Merge branch 'readline' X-Git-Tag: v4.4.0~65 X-Git-Url: http://git.pond.sub.org/?p=empserver;a=commitdiff_plain;h=d3a64a4f6e8aa1dc1ee027086aa9b280864e80e4;hp=-c Merge branch 'readline' --- d3a64a4f6e8aa1dc1ee027086aa9b280864e80e4 diff --combined Make.mk index 5746cc380,6ea44d09c..8c921d309 --- a/Make.mk +++ b/Make.mk @@@ -1,6 -1,6 +1,6 @@@ # # 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 @@@ -27,7 -27,7 +27,7 @@@ # 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', @@@ -47,13 -47,8 +47,13 @@@ all # 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)) @@@ -106,8 -101,10 +106,8 @@@ subst.in = sed # 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))) @@@ -128,6 -125,7 +128,6 @@@ client := src/client/empire$(EXEEXT 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))) @@@ -158,14 -156,11 +158,14 @@@ endi # 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) @@@ -265,8 -260,6 +265,8 @@@ ifeq ($(empthread),LWP $(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" @@@ -276,8 -269,6 +276,8 @@@ @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) @@@ -323,7 -314,7 +323,7 @@@ info.html/%.html: info/%. $(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) @@@ -338,19 -329,6 +338,19 @@@ $(libs) $(empth_lib) $(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 @@@ -364,7 -342,7 +364,7 @@@ info/stamp-subj: info/mksubj.pl $(tsrc $(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)) @@@ -378,28 -356,26 +378,29 @@@ $(info.nr): info/CRT.MAC info/INFO.MAC $(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 \ @@@ -407,8 -383,8 +408,8 @@@ .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 @@@ -457,5 -433,5 +458,5 @@@ $(srcdir)/src/client/config.h.in: src/c 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 $^ >$@ diff --combined configure.ac index 8c1c6cd28,7e56c02af..a30010816 --- a/configure.ac +++ b/configure.ac @@@ -1,6 -1,6 +1,6 @@@ # # 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 @@@ -27,7 -27,7 +27,7 @@@ # 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. @@@ -36,10 -36,8 +36,10 @@@ # 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]) @@@ -60,13 -58,9 +60,13 @@@ AC_ARG_VAR(NROFF, [nroff command] 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 @@@ -79,6 -73,7 +79,7 @@@ LIBS_util="$LIBS LIBS="$LIBS_SOCKETS $LIBS" AX_LIB_SOCKET_NSL LIBS_server="$LIBS" + MY_WITH_READLINE ### Checks for header files @@@ -240,6 -235,7 +241,7 @@@ AC_OUTPU 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]) diff --combined include/prototypes.h index 0471335bc,6fca449d3..ec89b40df --- a/include/prototypes.h +++ b/include/prototypes.h @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -59,6 -59,7 +59,6 @@@ extern int edit_sect_i(struct sctstr * 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 *); @@@ -225,6 -226,7 +225,6 @@@ int togg(void) int torp(void); int trad(void); int tran(void); -int trea(void); int turn(void); int upda(void); int upgr(void); @@@ -234,6 -236,7 +234,6 @@@ int wing(void) int wipe(void); int work(void); int xdump(void); -int xedit(void); int zdon(void); /* @@@ -267,7 -270,6 +267,7 @@@ extern int read_schedule(char *, time_t /* 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 */ @@@ -285,8 -287,7 +285,7 @@@ extern int demandupdatecheck(void) /* 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); @@@ -399,7 -400,6 +398,7 @@@ extern int check_trade_ok(struct trdst /* 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 *); @@@ -418,6 -418,8 +417,6 @@@ extern int commdamage(int, int, i_type) 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); @@@ -443,13 -445,14 +442,13 @@@ extern int roundrange(double) /* 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 */ @@@ -563,7 -566,9 +562,7 @@@ extern int delty(struct range *, coord) 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 */ @@@ -630,6 -635,8 +629,6 @@@ extern void takeover_ship(struct shpst 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 */ @@@ -640,7 -647,78 +639,7 @@@ extern int wu(natid, natid, char *, ... /* * 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 diff --combined src/client/Makefile.in index 998e737a8,f794c2fd7..e7154c311 --- a/src/client/Makefile.in +++ b/src/client/Makefile.in @@@ -1,6 -1,6 +1,6 @@@ # # 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 @@@ -28,7 -28,7 +28,7 @@@ # Makefile.in: Makefile template for configure # # Known contributors to this file: - # Markus Armbruster, 2005-2013 + # Markus Armbruster, 2005-2015 # CC = @CC@ @@@ -53,8 -53,9 +53,9 @@@ srcdir = @srcdir 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) @@@ -83,7 -84,7 +84,7 @@@ expect.$O: misc.h proto. 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 diff --combined src/client/configure.ac index 9352989f0,2baebcad0..f529d721d --- a/src/client/configure.ac +++ b/src/client/configure.ac @@@ -1,6 -1,6 +1,6 @@@ # # 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 @@@ -27,7 -27,7 +27,7 @@@ # 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. @@@ -36,10 -36,8 +36,10 @@@ # 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]) @@@ -60,6 -58,7 +60,7 @@@ if test "$Windows_API" = yes; the AC_LIBOBJ([w32/w32io]) AC_LIBOBJ([w32/w32sockets]) fi + MY_WITH_READLINE ### Checks for header files. @@@ -90,13 -89,12 +91,14 @@@ MY_WITH_TERMINF ### 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]) diff --combined src/client/main.c index f7c1c5344,190380b79..9cfba7112 --- a/src/client/main.c +++ b/src/client/main.c @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -30,8 -30,9 +30,9 @@@ * 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 @@@ -40,11 -41,13 +41,13 @@@ #include #ifdef _WIN32 #include + #include #include "sys/socket.h" #else #include #endif #include + #include "fnameat.h" #include "misc.h" #include "version.h" @@@ -55,6 -58,7 +58,7 @@@ struct passwd { char *pw_name; + char *pw_dir; }; static struct passwd *w32_getpw(void); @@@ -72,6 -76,10 +76,10 @@@ print_usage(char *program_name " -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); @@@ -82,6 -90,7 +90,7 @@@ main(int argc, char **argv { int opt; char *auxfname = NULL; + char *history_file = NULL; int send_kill = 0; char *host = NULL; char *port = NULL; @@@ -90,14 -99,20 +99,20 @@@ 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; @@@ -146,7 -161,8 +161,8 @@@ if (!host) host = empirehost; uname = getenv("LOGNAME"); - if (uname == NULL) { + udir = getenv("HOME"); + if (!uname || !udir) { struct passwd *pwd; pwd = getpwuid(getuid()); @@@ -154,7 -170,10 +170,10 @@@ 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); @@@ -172,10 -191,15 +191,15 @@@ 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; @@@ -183,12 -207,13 +207,13 @@@ #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; @@@ -199,6 -224,9 +224,9 @@@ 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; } diff --combined src/client/misc.h index c7a476d08,dacaf12b4..e92454a13 --- a/src/client/misc.h +++ b/src/client/misc.h @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -28,6 -28,7 +28,7 @@@ * * Known contributors to this file: * Steve McClure, 1998 + * Markus Armbruster, 2004-2017 */ #ifndef MISC_H @@@ -41,8 -42,6 +42,6 @@@ 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; @@@ -61,9 -60,10 +60,10 @@@ int parseid(char *) 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 diff --combined src/client/play.c index 3f6400177,5349f323e..87a698662 --- a/src/client/play.c +++ b/src/client/play.c @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -27,8 -27,9 +27,9 @@@ * 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 @@@ -51,6 -52,24 +52,24 @@@ #include "ringbuf.h" #include "secure.h" + #ifdef HAVE_LIBREADLINE + #include + #include + #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; @@@ -301,13 -320,6 +320,6 @@@ w32_ring_from_file_or_bounce_buf(struc #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. @@@ -335,7 -347,7 +347,7 @@@ recv_output(int sock 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)); @@@ -381,7 -393,18 +393,18 @@@ 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; } @@@ -397,28 -420,73 +420,73 @@@ 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. @@@ -426,19 -494,36 +494,36 @@@ 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; } @@@ -450,11 -535,12 +535,12 @@@ intr(int sig /* * 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 @@@ -466,8 -552,10 +552,10 @@@ 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); @@@ -475,6 -563,17 +563,17 @@@ 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; @@@ -487,10 -586,11 +586,11 @@@ /* * 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)) @@@ -502,7 -602,7 +602,7 @@@ if (n < 0) { if (errno != EINTR) { perror("select"); - return -1; + break; } } @@@ -511,51 -611,52 +611,52 @@@ 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; } } @@@ -564,10 -665,43 +665,43 @@@ 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); + } } diff --combined src/client/ringbuf.c index 9e04bc81a,2e4c88575..9782d9143 --- a/src/client/ringbuf.c +++ b/src/client/ringbuf.c @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -27,7 -27,7 +27,7 @@@ * ringbuf.c: Simple ring buffer * * Known contributors to this file: - * Markus Armbruster, 2007-2009 + * Markus Armbruster, 2007-2017 */ #include @@@ -35,7 -35,6 +35,6 @@@ #include #include #include - #include #include "ringbuf.h" /* @@@ -82,9 -81,17 +81,17 @@@ ring_peek(struct ring *r, int n 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]; } @@@ -149,16 -156,17 +156,17 @@@ ring_discard(struct ring *r, int n /* * 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]) @@@ -206,39 -214,29 +214,29 @@@ ring_from_file(struct ring *r, int fd } /* - * 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; } diff --combined src/client/ringbuf.h index a3794e8bd,545a2fd36..9d1a58bf8 --- a/src/client/ringbuf.h +++ b/src/client/ringbuf.h @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -27,13 -27,14 +27,14 @@@ * ringbuf.h: Simple ring buffer * * Known contributors to this file: - * Markus Armbruster, 2007 + * Markus Armbruster, 2007-2017 */ #ifndef RINGBUF_H #define RINGBUF_H #include + #include #define RING_SIZE 4096 @@@ -59,8 -60,8 +60,8 @@@ extern int ring_getc(struct ring *) 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 diff --combined src/client/secure.c index 808301882,c2e3cd24b..14bb6d1fe --- a/src/client/secure.c +++ b/src/client/secure.c @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -27,79 -27,81 +27,81 @@@ * secure.c: Check redir etc. to protect against tampering deity * * Known contributors to this file: - * Markus Armbruster, 2007 + * Markus Armbruster, 2007-2017 */ #include #include + #include + #include #include #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; } } diff --combined src/client/secure.h index 425cd7976,c5462f681..60986ac50 --- a/src/client/secure.h +++ b/src/client/secure.h @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -27,7 -27,7 +27,7 @@@ * 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 @@@ -35,8 -35,8 +35,8 @@@ #include - 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 diff --combined src/client/servcmd.c index f2d0e3fc6,ba6d974e6..fd83f9036 --- a/src/client/servcmd.c +++ b/src/client/servcmd.c @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -30,7 -30,7 +30,7 @@@ * Dave Pare, 1989 * Steve McClure, 1998 * Ron Koenderink, 2005 - * Markus Armbruster, 2005-2010 + * Markus Armbruster, 2005-2017 */ #include @@@ -41,6 -41,7 +41,7 @@@ #include #include #include + #include #include "misc.h" #include "proto.h" #include "secure.h" @@@ -52,14 -53,12 +53,12 @@@ int restricted 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; @@@ -69,7 -68,8 +68,8 @@@ 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); @@@ -80,10 -80,7 +80,7 @@@ (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; @@@ -93,13 -90,9 +90,9 @@@ 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) @@@ -114,6 -107,7 +107,7 @@@ if (arg[0] != '\n') { snprintf(teles, sizeof(teles), "(%.*s) ", len - 1, arg); if (!redir_fp) { + outch('\n'); putchar('\07'); prompt(code, the_prompt, teles); } @@@ -130,20 -124,8 +124,8 @@@ 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 * @@@ -158,10 -140,8 +140,8 @@@ fname(char *s } 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; @@@ -171,20 -151,37 +151,37 @@@ 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 @@@ -193,10 -190,10 +190,10 @@@ doredir(char *p 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; } @@@ -228,10 -225,10 +225,10 @@@ 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; } @@@ -241,10 -238,14 +238,14 @@@ 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) : ""); } } @@@ -253,7 -254,7 +254,7 @@@ doexecute(char *p { int fd; - if (!redir_authorized(p, "execute batch file", 1)) + if (!exec_authorized(p)) return -1; p = fname(p); @@@ -263,7 -264,7 +264,7 @@@ } 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; } diff --combined src/lib/common/conftab.c index 72f1d62d2,2c5d48e34..ae79d13cb --- a/src/lib/common/conftab.c +++ b/src/lib/common/conftab.c @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -35,6 -35,7 +35,7 @@@ #include #include #include "file.h" + #include "fnameat.h" #include "optlist.h" #include "prototypes.h" #include "xdump.h" diff --combined src/lib/common/emp_config.c index fa9fb4f59,d084e3a1f..90299ddb2 --- a/src/lib/common/emp_config.c +++ b/src/lib/common/emp_config.c @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -50,6 -50,7 +50,7 @@@ #include #include + #include "fnameat.h" #include "misc.h" #include "optlist.h" #include "prototypes.h" diff --combined src/lib/gen/fnameat.c index 098b03224,d970372c9..5a44bb25f --- a/src/lib/gen/fnameat.c +++ b/src/lib/gen/fnameat.c @@@ -1,6 -1,6 +1,6 @@@ /* * 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 @@@ -33,7 -33,9 +33,9 @@@ #include #include - #include "prototypes.h" + #include + #include + #include "fnameat.h" static int fname_is_abs(const char *);