Commit graph

4916 commits

Author SHA1 Message Date
Martin Haukeli
f1fc0df03d client: Add readline support to empire client
Readline provides fancy command line editing such as <Arrow Up> for
previous commands and CTRL+A to jump to the beginning of the line.

This patch does not add any completion on <tab> key, a TODO, if you
will.

A new command line flag, -H, turns on saving the history to disk.
This may have security implications on shared computers, as all
commands are saved as-is.  Thus "change re 1234" would be logged
directly to the file.

Signed-off-by: Martin Haukeli <martin.haukeli@gmail.com>

Rebase on top of preparatory work, fix a few bugs, and tidy up:

* Update the standalone client build, too.

* Fix the Windows build.

* Keep command line options sorted case-insensitively.

* Error out when $HOME is unset and getpwuid() fails, just like we do
  for $LOGNAME.

* Give @input_from_rl, @has_rl_input static linkage.

* @has_rl_input is a flag, not a counter, set and test it accordingly.

* Save all input in history, not just commands.  Martin's attempt to
  recognize commands works only as long as the server sends prompts
  faster than the user sends input.  Drop that part, and update commit
  message accordingly.

* Fix recv_input() not to truncate value of strlen() to int, and to
  use memmove() for updating @input_from_rl in place.

* Clean up whitespace in a few places.

* Tweak commit message.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
594cd20f76 client: Remove unused ring_to_file()
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
b3383c7423 client: Delay additional input processing until after send
We need to copy input to @auxfp to implement command line option -2,
and pass it to save_input() to enable protection against a rogue
server exploiting redirection and execute.  We currently do this right
when input enters the ring buffer, in recv_input().

Calling save_input() before sending input to the server is sloppy: it
can make the client accept "future" redirections and executes.

Delay save_input() until after input is sent.  For simplicity, delay
copying to @auxfp as well.

This is actually pretty close to how things worked before commit
8b7d0b9 (v4.3.11).

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
26372eb85d client: Inline ring_to_file() into new send_input()
In preparation for the next commit.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
53c8794ef8 client: Rearrange ring_to_iovec() for clarity
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
8fe2b949e6 client: Split ring_to_iovec() off ring_to_file()
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
8301e0f144 client: Lift assignment to @input_fd to recv_output()
On successful execute, servercmd() sets @input_fd to the batch file
descriptor.  Return the file descriptor instead, and let its caller
recv_output() set @input_fd.  This permits giving @input_fd static
linkage.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
37e68e5796 client: Fix obscure misdetection of input EOF
recv_input(input_fd, &inbuf) returns zero when @inbuf is full or
@input_fd is at EOF.  We avoid the former by putting @input_fd in
@rdfd only when @inbuf has space, so we can detect EOF easily.  But we
missed the case where adding a cookie fills up @inbuf.  We
misinterpret "can't read into full buffer" as "EOF on input" then.

Fix by checking for space again.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
38097c4986 client: Clear pending interrupt on stdin EOF
The client can send an interrupt cookie after the EOF cookie.
Harmless, as the server throws away input after the EOF cookie.  Clean
it up anyway.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
3135cd39c3 client: Simplify input EOF handling
We increment @send_eof only when read() returns zero, and we read()
only when it's zero.  Therefore, we never increment it beyond one.
Change it from counter to flag.

This effectively reverts commit 51846ec (v4.3.11).  Possible only
because the previous commit got rid of the @send_eof increment on
failed execute.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
b6d0f4e3db client: Signal interrupt instead of EOF on batch file error
The server doesn't currently care for the difference, but interrupt is
more accurate than EOF.  The change also enables the next commit.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
cf7d52fc10 client: Simplify rogue redirection and execute protection further
recv_input() passes full lines to save_input().  Pass characters
instead.  Simpler, and doesn't truncate long lines.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-08-06 11:22:29 +02:00
5cb14f508e client: Fix rogue execute protection
To protect against a rogue server reading your files, the client
honors C_EXECUTE only when it matches recent player input.

This has a somewhat troubled history, detailed in the previous commit.

The remaining major issue comes from commit 8b7d0b9 (v4.3.11): any
suffix of a recent line of input is accepted as C_EXECUTE text.
Before, only text that looked like an argument of an execute command
or a redirection was accepted.

Fix by again requiring the text to be preceded by something that looks
like an execute command.  But do it more carefully: don't break
execute with a prompted for argument, and prevent abuse of
redirections for execute.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-07-24 20:21:40 +02:00
d13950470a client: Simplify rogue redirection and execute protection
Redirections let the server write files and run pipelines, and execute
lets it read files.

Before 4.2.0, the client simply trusted the server.  4.2.0 added
fairly complex code to recognize redirections and execute, replace the
filenames and pipelines by tag strings, remember tag string and
replaced text, and honor redirection and execute only when their text
is a known tag string.  Tag and replaced text were freed on use.

Broken by design because the client cannot know whether a line will
actually be read as a command by the server.  Issues included:

(1) Non-command lines could be messed up.

(2) The memory used for remembering their tags was never freed.

(3) execute prompting for its argument was incorrectly rejected.

(4) A rogue server could use a tag for the wrong purpose.  For
instance, "execute fire" creates a tag for "fire", which a rogue
server could use for a pipeline to command "ire".

4.2.10 dropped the tag strings, and used the actual text as key.  This
took care of (1).

Commit 17d6997 and commit 2456a71 (both v4.3.11) tightened checking of
redirections, which took care of (4) for redirections, but not
execute.  Relatively harmless, because redirection text always starts
with '>' or '|', but filenames rarely do.

Commit 8b7d0b9 (v4.3.11) replaced the protection code wholesale.
Instead of attempting to recognize redirections and execute, we now
save everything in a ring buffer, and require redirections and execute
to match at a line end in the ring buffer.  Much simpler, takes care
of issues (2) and (3), but adds new issues:

(5) When sent-ahead input exceeds the ring buffer, good redirections
and executes get rejected.  Could be avoided by limiting send-ahead,
or remembering input until its output arrives.  However, bogus
rejections haven't been a problem in practice even with a tiny 4KiB
ring buffer.

(6) The protection against rogue execute is *much* weaker, because we
now accept any line suffix.  Before, we accepted any tag,
i.e. anything that looks like a redirection or an execute command.

(7) When we find a match in the ring buffer, we used to drop
everything up to that line right away.  This broke redirected execute
commands.  Commit 02a9af0 (v4.3.11) fixed it by delaying the drop
until the next prompt, but that's overly complicated.

This commit addresses (7): don't drop on use, simply let new input
push old input out of the ring buffer.

The next commit will address (6) and the remainder of (4).

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-07-24 20:21:16 +02:00
a2f6ea968c client: Improve the client's messages
Use a "Warning: " prefix for server output violating the protocol and
for rogue redirections and executes.  Don't shout "WARNING!"

In redir_authorized(), check for server issues (conflicting
redirections, rogue redirections and executes) before enforcing
restrictions (restricted mode, executing batch file), so server issues
aren't masked.

Surprisingly, popen() may not set errno on failure.  Avoid reporting a
bogus errno in dopipe().

doexecute() complains about an "execute file".  We call that a "batch
file" elsewhere.  Reword for consistency.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-07-08 19:17:07 +02:00
8fe0221634 client: Drop extra newlines from the client's messages
servercmd()'s argument arg ends with a newline already.  Broken in
commit 8b7d0b9, v4.3.11.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-07-08 19:17:07 +02:00
63a6288435 client: Fix integer wrap around in ring_peek()
Peeking beyond either end of the ring buffer must return EOF.  We
first compute the index, then check whether it's in range.

Unfortunately, the index computation r->prod - -n can wrap around
while r->prod is still <= RING_SIZE.  If it happens, ring_peek()
returns r->buf[(r->prod - -n) % RING_SIZE] instead of EOF.

Currently harmless, because no caller peeks out of range.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2017-07-08 19:17:07 +02:00
93dfd60c4b man/empire: Trim unwanted space in synopsis
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-13 10:46:58 +01:00
5c28d3685b doc/contributing: Fix git format-patch topic branch example
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-13 10:46:58 +01:00
4bce12ac0b travis: Enable OS X
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:19:39 +01:00
42a3c10fd9 navigate march: Fix abort not to wipe out concurrent updates
When the player aborts the command at the movement prompt, we write
back stale ships or land units, triggering a generation oops.  Any
updates made by other threads meanwhile are wiped out, triggering a
seqno mismatch oops.

Broken in commit 24000b4, v4.3.33.  Fix by restoring the lost
shp_nav_stay_behind() and lnd_mar_stay_behind() calls.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:19:39 +01:00
354b6aea3d tests/navi-march: Cover abort at movement prompt
This exposes generation oopses.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:19:39 +01:00
863fde5a2c march: Fix concurrent updates at sector abandon prompt
When the player declines to abandon a sector, we write back stale land
units, triggering a generation oops.  Any updates made by other
threads meanwhile are wiped out, triggering a seqno mismatch oops.

The culprit is lnd_abandon_askyn(): when the player declines, it
returns without calling check_sect_ok(), check_land_ok().  Broken in
commit 7c1b166, v4.3.33.  Fix it.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:19:38 +01:00
8daeffbd8f recvclient: Track potential yield on input
recvclient() calls ef_make_stale() only when it does actual I/O, via
io_output() and io_input().  Missed in commit 2fa5f652, v4.3.24.  Call
it directly when it doesn't do actual I/O.

This makes navi-march-test expose a bug in march: when the player
declines to abandon a sector, we write back stale land units,
triggering a generation oops.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:19:38 +01:00
9645caf6ff configure: Use -fstack-protector-strong when available
Testing whether the compiler supports it is a bit tricky.

The obvious AX_APPEND_COMPILE_FLAGS([-fstack-protector-strong])
doesn't suffice, since some ports of the GNU toolchain reportedly pass
this test, then fail to link.  That's because the compiler accepts the
flag, duly emits references to helper code in libc, but libc doesn't
provide, and linking fails.

Instead, use AX_APPEND_LINK_FLAGS with an input source that makes the
compiler emit the extra stack checking code.  This requires the latest
version from the autoconf-archive, so update m4/ax* to commit e3d948b.
Also update m4/my_append_compile_flags.m4 to keep it in sync with
upstream's ax_append_compile_flags.m4.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:19:38 +01:00
41263cf8c9 scripts/savecore: Report nicely when there's no core dump
When savecore can't find a core dump, it reports something like

    ls: cannot access core.*: No such file or directory

to stderr, and fails.  If privlog is set, it also mails out a "Could
not save core dump" note.

Suppress the error message, and mail out "Could not find core dump to
save" instead.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:19:38 +01:00
3f86dd2ecf configure: Use -fno-strict-aliasing -fno-strict-overflow
Contemporary compilers can squeeze out some extra performance by
assuming the program never executes code that has undefined behavior
according to the C standard.  Unfortunately, this can break programs.
Pointing out that these programs are non-conforming is as correct as
it is unhelpful, at least as long as the compiler is unable to
diagnose the non-conformingness.

Since keeping our programs working is a lot more important to us than
running them as fast as possible, forbid some assumptions that are
known to break real-world programs:

* Aliasing: perfectly clean programs don't engage in type-punning, and
  perfectly conforming programs do it only in full accordance with the
  standard's (subtle!) aliasing rules.  Neither kind of perfection is
  realistic for us, therefore -fno-strict-aliasing.

* Signed integer overflow: perfectly clean programs won't ever do
  signed integer arithmetic that overflows.  This is an imperfect
  program, therefore -fno-strict-overflow.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:19:38 +01:00
6e80cf103f tests: Enable GNU libc memory allocation error checking
MALLOC_CHECK_=3 makes glibc check for memory allocation programming
errors.  It's the factory default, but set it anyway just in case
someone disabled it for speed.

Non-zero MALLOC_PERTURB_ makes glibc wipe memory value on allocation
and deallocation.  The actual value determines the bit pattern.  Set
it to the value of environment variable EMPIRE_CHECK_MALLOC_PERTURB or
else a pseudo-random number, and record it in sandbox/malloc-perturb.

See mallopt(3) for more information.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 13:03:08 +01:00
1abd3c5b0b navigate march: Plug memory leaks
When the player aborts the command at the movement prompt, or declines
to abandon a sector, unit_move() returns without freeing the list.
Found with valgrind.  Broken in commit 24000b4 and commit 7c1b166,
both v4.3.33.

Free the list on these returns, too.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:51:07 +01:00
25c7d3798b navigate march retreat lretreat: Fix read beyond buffer
shp_nav_gauntlet() and lnd_mar_gauntlet() read beyond the list head
when the list is empty.  The values read aren't used then.  Could
conceivably crash the server anyway, but it's unlikely.

Empty list happens when shp_nav_dir(), lnd_mar_dir() empty the list
and return zero.  Broken in commit beedf8d, v4.3.33.  Occurs in
navi-march-test (since the last commit) and in retreat-test.

Change shp_nav_dir() and lnd_mar_dir() to return one then.  For
additional safety, make shp_nav_gauntlet() and lnd_mar_gauntlet() oops
on empty list and recover safely.

I think I originally found this bug with -fsanitize, but I've since
upgraded, and I can't diagnose it that way anymore.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:51:07 +01:00
493dc5f941 tests/navi-march: Cover running out of mobility completely
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:51:07 +01:00
6888337afe bomb drop fly paradrop recon sweep: Fix read before array
The code computing the length of the flight path checks whether the
path ends with 'h'.  When getpath() returns an empty path, it accesses
flightpath[-1].  This could set the length to -1 (unlikely), or crash
(even less likely).  The former could be abused to gain mobility for
sufficiently inefficient or short-ranged planes.  Found with valgrind.

Broken in commit 404a76f7, v4.3.27.

Historically, getpath() could return paths with or without 'h', and
the check was necessary.  It returned an empty path only when the
player gave no input, aborting the command.  When the player entered
the assembly point's coordinates, it returned "h".

Commit 404a76f7 accidentally changed it to return "" then.  Also broke
flying to the assembly point's coordinates.  Commit 0f1e14f (v4.3.31)
fixed that part by changing getpath()'s contract: always return paths
without 'h' ("" simply means empty path), and return NULL on invalid
input, including no input.

The flawed check is superfluous since then.  Drop it.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:51:07 +01:00
b9375b14b1 Avoid shifting into sign bit
It's undefined behavior.  Found with gcc -fsanitize=undefined.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:50:54 +01:00
d58bea5458 Convert run-time to build-time assertion
There's just one, in show_product().

Use new BUILD_ASSERT() there, because its contract is even simpler
than BUILD_ASSERT_ONE()'s.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:43:28 +01:00
80bf4ec34b Provide proper build-time assertions for NSC_SITYPE()
We want to cause a diagnostic when NSC_SITYPE()'s argument isn't
implemented.  Commit aa6ad9d's solution is to have the macro expand
into 1/0 then.  Works with GCC, but Clang always warns "division by
zero is undefined".

The better, portable way to conditionally break the build is an array
type with a size that's negative when the build should fail, else
positive.  Implement that wrapped in a sizeof() to make it an
expression as macro BUILD_ASSERT_ONE(), and use it in NSC_SITYPE().

No more warnings from Clang 3.5.0.  GCC still produces its "may be
used uninitialized" false positives.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:42:40 +01:00
d074d29736 subs: Don't squash telegrams together when time goes backwards
We've always squashed them when the time difference is smaller than
TEL_SECONDS, regardless of sign.  This involves passing the difference
to abs(), implicitly casting from time_t to int, which triggers a
Clang warning.

I could clean this up to get rid of the warning, but time should never
go backwards, and trying to make things prettier when it does isn't
worthwhile.  Simply drop the abs().

While there, drop the function comment.  It's been inaccurate since
Empire 3 dropped mail.c, and bogus since commit 17223e8 (v4.3.29)
added tel_cont.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:16 +01:00
feb894cf1e info/Nuke-types: Document show columns avail, res, abilities
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:16 +01:00
659957c40c info/Unit-types: Belatedly remove capability xlight
L_XLIGHT was replaced in commit e28c14f, v4.3.0.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:16 +01:00
c0b41650c5 info/Plane-types: Belatedly remove stealth and half-stealth
P_X and P_H were removed in commit 61233e4, v4.3.23.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:16 +01:00
6787049ae5 info/Ship-types: Belatedly remove capability spy
M_SPY was removed in commit 498d9fb, v4.3.0.  It never did anything.

Reported-by: Harald Katzer
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:16 +01:00
5010240995 info: Belatedly update for change of stop prefix to '!'
Commit eb1512d (v4.3.6) added the '=' if stopped before efficiency.
Commit 016249c (v4.3.6) changed it to '!' without updating info ship,
plane, land, nuke.

Reported-by: Harald Katzer
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:16 +01:00
b031770040 info/version: Update example to current output
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:16 +01:00
58a6e7270f info: Fix option NOMOBCOST misinformation
The cost of firing naval guns is 15 mobility with option NOMOBCOST
disabled.  Mobility.t is correct.

Fix Options.t not to claim submarines pay half the sector movement
cost when NOMOBCOST is enabled.

Fix fire.t not to claim ships pay half the sector movement cost when
NOMOBCOST is disabled.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:15 +01:00
00abc9616d info/Options: Nicer markup, more consistent format
Don't list options separately for major server versions.  It's only of
historical interest, which "info History" satisfies.

Make it a list (.L) instead of preformatted text (.nf).

Fix up so the option explanations are full sentences, starting with a
capital letter and ending with a period.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:15 +01:00
b1525ef272 info/Options: Belatedly remove SAIL
Missed in commit dc73207.

Reported-by: Harald Katzer
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:15 +01:00
6986ac4778 lwp: Rename LwpSigCatched to LwpSigCaught
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:15 +01:00
6b6708a01b docs/coding: Explain function/struct/union comment conventions
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:41:15 +01:00
eba87789ab Fix and clean up some comments
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:31:08 +01:00
9f25de3dce Change comment style to use @foo rather than FOO
... when referring to a function's parameter or a struct/union's
member.

The idea of using FOO comes from the GNU coding standards:

    The comment on a function is much clearer if you use the argument
    names to speak about the argument values.  The variable name
    itself should be lower case, but write it in upper case when you
    are speaking about the value rather than the variable itself.
    Thus, "the inode number NODE_NUM" rather than "an inode".

Upcasing names is problematic for a case-sensitive language like C,
because it can create ambiguity.  Moreover, it's too much shouting for
my taste.

GTK-Doc's convention to prefix the identifier with @ makes references
to variables stand out nicely.  The rest of the GTK-Doc conventions
make no sense for us, however.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:13:17 +01:00
5cff5022a9 configure: Suppress Clang warning on carg()
Renaming carg() would be smarter, but I'd rather do that as part of a
consistent renaming of all command functions, and I'm not up to that
right now.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2015-12-05 12:11:37 +01:00