ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β βββββββ βββββββ βββββββ βββ βββ βββββββββββ β
β ββββββββββββββββ βββββββββββ βββ βββββββββββ β
β βββββββββββ βββββββββββββββ βββ βββββββββββ β
β βββββββ βββ ββββββββββ βββ βββ βββββββββββ β
β βββ ββββββββββββ βββββββββββββββββββββββββ β
β βββ βββββββ βββ ββββββββ βββββββ ββββββββ β
β β
β v2026.1.0 - by Tony Mattke aka tonhE β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Modernization patches for Playground+. Takes v1.0.11 talkers to v2026.1.0, builds on modern Linux, fixes security holes, and keeps your customizations.
Playground+ is a C-based telnet talker server popular in the late 1990s. Stock Playground+ (circa 1995-2000) won't build on modern 64-bit systems, and if you do get it running there are several bugs that make it run terribly. These patches fix all of that: compiler errors, security vulnerabilities, and deprecated API usage. They're small enough to apply to talkers that have been modified over the years.
Note
This patch is specifically designed to bring Playground+ v1.0.11 up to date with the v2026.1.0 release. Neither this repository nor playground-plus/playground-plus on GitHub are official repositories maintained by the original Playground+ developers.
# 1. CD into the root directory of your talker
cd /path/to/your/talker/directory
# 2. Make a backup of your src directory
cp -a src src-backup-pre-2026-update
# 3. Clone the patch release alongside your talker source
git clone --branch v2026.1.0 https://github.com/playground-plus/playground-plus-patches.git playground-plus-patches-v2026.1.0
# 4. Test what applies cleanly
./playground-plus-patches-v2026.1.0/apply.sh --dry-run ./src
# 5. Apply everything
./playground-plus-patches-v2026.1.0/apply.sh ./src
# 6. Build and verify (expect 0 errors, 0 warnings)
cd src
make clean && makeTo apply just one category instead of everything:
./playground-plus-patches-v2026.1.0/apply.sh --category 03-security ./srcNote
You can apply patches before or after the PG+ first-run setup (make β make newos β make config β make dep). If you patch before, the OOBE runs normally and generates a correct Makefile from the patched template. If you patch after, apply.sh detects the generated Makefile and fixes it automatically.
Each category is independent. Apply only the ones you need. Within a category, patches must be applied in order.
Version bump (optional)
| Patch | What it fixes |
|---|---|
0001-version-bump |
Updates PG_VERSION to 2026.1.0 and INTERCOM_VERSION to 1.2.0 |
Required to build on GCC 10+
| Patch | What it fixes |
|---|---|
0001-sprintf-wrestrict-overlapping-buffers |
-Wrestrict warnings from sprintf() writing into its own source buffer |
0002-strncpy-truncation-null-termination |
-Wstringop-truncation warnings; adds explicit null terminators after strncpy() |
0003-ignore-ret-unchecked-returns |
-Wunused-result warnings for intentionally unchecked write() calls; adds IGNORE_RET macro to config.h |
0004-zero-warnings-final-pass |
Remaining warnings: unused variables, address-of-array, operator precedence, misleading indentation |
0005-unused-params-sa-mask |
Unused parameter warnings, sigemptyset() for signal mask init |
Per-file sub-patches are provided in 0002-strncpy-per-file/, 0003-ignore-ret-per-file/, and 0004-zero-warnings-per-file/ for when the combined patch doesn't apply to your modified files. Apply individual file patches instead. The robot_int sub-patch in 0004-zero-warnings-per-file/ fixes the remaining -Waddress warnings in robot_int.c and is included in the default apply.sh series.
Prevents buffer overflow exploits
| Patch | What it fixes |
|---|---|
0001-sprintf-to-snprintf |
Replaces sprintf() with snprintf() in admin2.c, commands.c, glue.c, plists.c, room.c |
Fixes exploitable vulnerabilities
| Patch | What it fixes |
|---|---|
0001-command-injection-email-welcome |
Replaces system() shell call with fork()/execlp() in the email welcome feature to prevent shell injection via crafted email addresses |
Replaces deprecated network APIs. Required on some modern systems.
| Patch | What it fixes |
|---|---|
0001-getaddrinfo-getnameinfo |
gethostbyname()/gethostbyaddr() to getaddrinfo()/getnameinfo(). The old functions are removed in some modern libc |
0002-bulk-socket-reads |
Replaces byte-at-a-time read() with 4KB bulk reads for a massive performance improvement |
0003-select-to-poll |
select() to poll(), removing the FD_SETSIZE (1024) file descriptor limit |
Important
All three patches in this category modify socket.c. If your socket.c is heavily modified, you may need to apply these manually.
Upgrades password security from DES to SHA-512
| Patch | What it fixes |
|---|---|
0001-des-to-sha512 |
New passwords use SHA-512 via crypt(); existing DES passwords still work for login |
0002-des-upgrade-prompt |
Prompts users with old DES passwords to set a new one on login |
0003-fix-login-hang-after-upgrade |
Fixes a state machine bug that caused login to hang after the upgrade prompt |
Important
Apply all three patches in this category or none. 0002 and 0003 depend on 0001.
Hardening for the intercom server binary
| Patch | What it fixes |
|---|---|
0001-sigchld-handler-crash |
Fixes crash: fatal_error() called inside signal handler (async-signal-unsafe) |
0002-getaddrinfo |
gethostbyname()/gethostbyaddr() β getaddrinfo() in intercom |
0003-audit-fixes |
Buffer overflows, strcpy β strncpy, division-by-zero guard, vsprintf β vsnprintf |
0004-packet-null-termination |
Fixes non-null-terminated packet data (strcpy β memcpy + explicit terminator) |
0005-list-output-formatting |
Adds leading newline before intercom list output |
Note
If you don't use intercom, skip this entire category.
Build system fixes
| Patch | What it fixes |
|---|---|
0001-makefile-wc-display-fix |
Fixes wc -l display in build output (Makefile.template) |
0002-makefile-template-modern-gcc |
Removes obsolete -Wl,-qmagic linker flag; adds -fcommon for GCC 10+ (Makefile.template) |
Note
These patch Makefile.template. See the Quick Start note above for OOBE timing details.
Required for modern Linux (glibc 2.34+, 64-bit)
| Patch | What it fixes |
|---|---|
0001-rename-log-to-pg_log |
Renames custom log() to pg_log() to avoid collision with glibc log() from <math.h> |
0002-rename-strcasestr-to-pg_strcasestr |
Renames custom strcasestr() to pg_strcasestr() to avoid collision with POSIX strcasestr() |
0003-include-modernization |
Removes obsolete <memory.h> / <malloc.h>; adds missing <time.h>, <stdlib.h>, <string.h>, <sys/types.h> |
0004-platform-portability |
Removes HAVE_SOCKLEN_T / HAVE_BZERO ifdefs; bzero β memset; simplifies <sys/un.h> includes; removes sigpause(), RLIMIT_RSS, sys_errlist |
64-bit safety, bug fixes, and cleanup
| Patch | What it fixes |
|---|---|
0001-code-quality-fixes |
Pointer arithmetic casts for 64-bit ((int)ptr - (int)ptr β (int)(ptr - ptr)); execlp() sentinel 0 β (char *)NULL; format-string security (printf(var) β printf("%s", var)); unused variable removal; operator precedence bug in tag.c; semicolon-after-if bug in admin.c; sizeof() format specifiers %d β %zu |
A drop-in server management script installed to bin/ctl by apply.sh.
bin/ctl start # Start the server stack (angel + talker)
bin/ctl stop # Stop everything gracefully
bin/ctl restart # Full restart (stop + start)
bin/ctl status # Show running processes and uptime
bin/ctl reboot # Seamless reboot via angel
bin/ctl log error # Tail a log file (angel|error|boot|connection|intercom)The script auto-detects its location relative to your talker's directory structure. No configuration needed. If proxy support is enabled (HAVE_PROXY in autoconfig.h or a proxy binary in bin/), proxy management is automatically included.
Most PG+ talkers have been customized. Here's how to deal with patches that don't apply cleanly:
./playground-plus-patches-v2026.1.0/apply.sh --dry-run ./srcThis shows which patches will apply and which won't, without changing anything.
The three largest patches (0002-strncpy, 0003-ignore-ret, 0004-zero-warnings) have per-file sub-patches. If the combined patch fails because you modified socket.c, apply the sub-patches for the files you haven't changed:
# Apply strncpy fix only for admin.c and room.c (from your talker root)
patch -p1 -d ./src < ./playground-plus-patches-v2026.1.0/patches/01-compiler-warnings/0002-strncpy-per-file/admin.patch
patch -p1 -d ./src < ./playground-plus-patches-v2026.1.0/patches/01-compiler-warnings/0002-strncpy-per-file/room.patch# More permissive matching (allows offset line numbers)
./playground-plus-patches-v2026.1.0/apply.sh --fuzz 3 ./src
# Collect all reject files in one place for review
./playground-plus-patches-v2026.1.0/apply.sh --reject-dir /tmp/pgplus-rejects ./srcFor heavily modified files, read the .patch file. They're standard unified diffs, easy to read. The changes are typically mechanical (add a null terminator, change sprintf to snprintf, etc.) and straightforward to apply by hand.
These patches were developed and tested against:
- Base: Stock Playground+ v1.0.11
- Compiler: GCC 13.3.0
- OS: Linux 6.8.0 x86_64, glibc 2.39
- Result: 0 errors, 0 warnings across all 4 binaries (talker, angel, ident_server, intercom)
These patches are released under the MIT License. The patches apply to Playground+ source code, which is distributed under its own Playground Plus licence.