journal_entry_pr(S, N) writes up to N characters from zero-terminated
string S. journal_input() passes -1 for N to write all characters.
Unclean. SIZE_MAX would do, but it's C99, and MSC doesn't provide it.
Simplify journal_entry_pr() to write exactly N characters. This makes
it more similar to write() than to pr(), therefore rename.
pln_equip() refuses to abandon its base sector. Unfortunately, it
checks even when flying off carriers, and refuses to load the last
civilian or military depending on what happens to be in uninitialized
variable sect.
Broken in commit 91139692, v4.3.0.
Adjacent announcements are squashed together when the sender is the
same and the timestamp is "close enough". Except typed_wu()
increments natstr member nat_ann regardless. Fix that to work exactly
like nat_tgms.
Adjacent telegrams are squashed together if type and sender are the
same, and the timestamp is "close enough". This is done in two
places: rea() and typed_wu(). They're inconsistent: typed_wu()
ignores the timestamp for production reports since Empire 2, but rea()
doesn't.
Record typed_wu()'s decision in new telstr member tel_cont. Use it in
rea().
typed_wu() counts telegrams to update nat_tgms and, since Empire 2,
send C_INFORM messages. Adjacent telegrams are squashed together if
type and sender are the same, and the timestamp is within TEL_SECONDS.
typed_wu() increments nat_tgms when it sends a telegram that read
doesn't squash into the previous one.
Since Empire 2, it also sends a C_INFORM message then. Inexplicably,
it fails to use the same condition: it tests just new_tele, not
new_tele || np->nat_tgms == 0. C_INFORM messages got missed, until
4.0.18 made rea() call clear_telegram_is_new(). Convoluted.
Send C_INFORM exactly when incrementing nat_tgms, and back out
4.0.18's fix.
During the update, wu() sends TEL_UPDATE telegrams ("Production
Report") instead of TEL_BULLETIN telegrams, but typed_wu() has no such
logic. It's used by tele(), which doesn't run during the update, and
mpr(), which may, e.g. called from ship or mission code used by
autonav or sail. This inserts bulletins in the middle of the
production report, splitting it apart.
Happens since mpr() was added in Empire 2. Before, only tele() used
typed_wu() directly, and everything else wu().
Change mpr() to use wu().
Leave nat_ann, nat_tgm alone and return -1 on all errors. Before,
only failed open was handled that way. Failed write and close were
logged and ignored. While there, improve the log messages a bit.
Note: the return value fix has little effect. It makes tele() log the
failure, which is redundant. Everything else goes through wu() and
ignores the value.
POGO can navigate dead ships, and march dead land units. The ghosts
even get sighted and interdicted, and can hit mines (landmines only
until commit fe372539, v4.3.27). Noted for ships in commit 9100af0b.
Has always been broken. Fix by making shp_sel() and lnd_sel()
explicitly reject ghosts.
Same code pattern also exists in pln_sel, but dead plains fail the
efficiency test, so it's harmless there. Apply the same fix anyway.
When updating in-place (old==new), we must not write through new
before we're done reading the same memory through old.
Bug: we write the carrier uids too early. Cargo lists aren't updated
when a carrier dies in an in-place update. No such updates are known.
Broken in commit 64a53c90, v4.3.17.
When units somehow get stuck on a dead carrier, a new build reusing
the dead carrier's UID picks up its cargo. The cargo gets teleported
to its new carrier when the carrier moves.
Oops when a ship, plane or land unit is created with cargo. To
recover, destroy the cargo.
copy_utf8_to_ascii_no_funny() eats the character following a replaced
non-ASCII character. Buffer overrun possible when the terminating
zero gets eaten. Broken in commit b5ff7e3b, v4.2.21.
Affected commands:
* players column "last command" in ASCII sessions: struct player
member combuf is UTF-8, uprnf() filters to ASCII.
* read in ASCII sessions: telegram chunks are UTF-8, uprnf() filters
to ASCII.
* flash and wall with message argument in ASCII sessions: argument is
used raw, i.e. UTF-8, pr_flash() filters to ASCII. Safe as long as
we have input filtering sanitizing the raw argument. command() does
that, but execute() doesn't (bug, to be fixed in a later commit).
* execute prompting for its argument in UTF-8 sessions: prmptrd()
receives user text, and filters to ASCII.
Unaffected:
* dispatch() argument redir is UTF-8, uprnf() can filter to ASCII.
Safe as long as we have input filtering sanitizing the raw argument.
command() does that. execute() doesn't, but rejects redirections
before calling dispatch().
* getele() buffer is UTF-8, uprnf() can filter to ASCII. Safe,
because its contents comes from uprmptrd(), which filters input.
pln_zap_transient_flags() fixes up planes stuck in the air (commit
7ca4f412, v4.3.12). Since commit 4e9e58bf (v4.3.14), it writes back
the fixed planes. This is wrong for empdump.
empdump should touch data only on successful import. When it fails
because ef_verify() fails, and any planes are found stuck in the air,
the plane file gets rewritten.
Make parameter ef_verify() take parameter may_put to let empdump
suppress the plane write-back. The plane file still get written out
on successful import, along with the other imported game state.
Spy units are now enabled when a land unit type with capability spy
exists. To disable them, deities have to customize table land-chr.
Before, spy units types were ignored when option LANDSPIES was
disabled. Except for xdump land-chr, which happily dumped unusable
spy unit types.
Trade ships are now enabled when a ship type with capability trade
exists. No such type exists by default; to enable trade ships,
deities have to customize table ship-chr.
Before, trade ship types were ignored when option TRADESHIPS was
disabled. Except for xdump ship-chr, which happily dumped unusable
trade ship types.
Configuration table entries not defined by builtin and custom
configuration files remain blank. They get misinterpreted as sentinel
in tables that use one. Affected are tables product, ship-chr,
plane-chr, land-chr and nuke-chr. Tables item, sect-chr and
infrastructure are immune despite using a sentinel, because omitting
entries is not permitted there.
Code relying on the sentinel fails to pick up entries after the first
blank one. They don't get set up correctly, they're invisible to
build and show, and not recognized as symbolic selector values (the
frg in ship ?type=frg). xdump is fine, because it doesn't rely on
sentinels. It dumps blank entries normally.
The bugs don't bite in the stock game, because the builtin
configuration files are all dense.
The sentinels are all null strings. Set them to "" in the affected
tables' oninit callback. Fix up code iterating over the tables to
ignore such entries. This is precisely the code relying on sentinels,
plus xdump's xdvisible().
They set up invariants, and thus should be always active, not just in
the server. Since ef_blank() isn't used for these files outside the
server right now, this isn't a bug fix, just cleanup.
New struct empfile member nent replaces ef_open() parameter nelt.
Cleaner, because the expected size is a property of the file, not of
how it's used. Also fixes empdump to check file sizes.
Complication: with EFF_CREATE, ef_open() creates an empty file, to be
extended to the correct size. Callers passed nelt argument -1 along
with EFF_CREATE, to make ef_open() accept the empty file. Can't do
the same for empfile member nent. Instead, make ef_open() not check
the (zero) size then.
Replaces commit 5750107b, v4.3.15.
New struct empfile member base replaces ef_open_view() parameter base.
Cleaner, because the base table is a property of the view, not of how
it's used.
Use it to clean up verify_fail()'s base table access, and for extra
sanity checks in ef_open() and ef_open_view().
ef_open() handles onresize() failing incorrectly. Instead of fixing
that, drop the failure mode. It's not really used: unit_onresize()
fails only when used incorrectly. It isn't. If it ever is, ignoring
the failure is safe.
This was probably neglected when the techlists feature was added in
v4.0.0, because compiled-in nukes were sorted by tech, unlike ships,
planes and land units. Customization can break that.
Fighters, SAMs, ABMs and anti-sats could intercept, and tactical
missiles could interdict ships or land units.
Missed when the other missions were fixed in v4.2.7.
getstarg(), snxtitem() and snxtsct() can yield the processor, because
they call getstring(). But only for null or empty arguments. For
other arguments, we should call ef_make_stale(), to catch errors.
Problem: if a caller never passes null or empty arguments, it may rely
on these functions not yielding. We'd get false positives. In
general, we can't know whether that's the case. But we do know in the
common special case of player arguments. Call ef_make_stale() for
those.
Without ARG1, display_region_map() formats a rectangular area around
CURX,CURY, so it can use do_map(). Ugly, and duplicates some
unit_map() functionality.
Factor snxtsct_around() out of unit_map(). Inline do_map() into
display_region_map(), so we can use snxtsct_around().
Don't mess with player->condarg. Leftover from when we abused map()
here.