Skip to content

Port eBBS 3.1.4-rc2 to build and run on macOS/Darwin (Apple Silicon) - #2

Open
DrPitre wants to merge 5 commits into
virtadpt:masterfrom
DrPitre:master
Open

Port eBBS 3.1.4-rc2 to build and run on macOS/Darwin (Apple Silicon)#2
DrPitre wants to merge 5 commits into
virtadpt:masterfrom
DrPitre:master

Conversation

@DrPitre

@DrPitre DrPitre commented Jul 5, 2026

Copy link
Copy Markdown

Summary

  • Adds a DARWIN os profile in osdeps.h (based on FREEBSD) so the codebase can be identified/built on macOS
  • Updates Makefile CCFLAGS for modern clang's stricter K&R diagnostics (implicit-int, implicit-function-declaration are hard errors by default now); omits -lcrypt on Darwin (crypt is in libSystem)
  • Fixes terminal I/O on macOS: replaces ioctl(TIOCGETA/TIOCSETA) with tcgetattr()/tcsetattr() in pbbs/term.c — the ioctl path returned EFAULT/Bad address on Apple Silicon
  • Fixes two variadic functions (prints() in pbbs/screen.c, bbslog() in log.c) that lacked prototypes visible at their call sites — on ARM64 this caused va_arg() to read corrupted values, resulting in SIGSEGV crashes during login; adds extern declarations to clientui.h and pbbs/io.h so all translation units see the correct variadic ABI
  • Converts every K&R-style function definition across the codebase (~54 files) to ANSI C prototype form; zero warnings on modern clang
  • Fixes gram.y: converts K&R function definitions to ANSI C, adds forward declarations for all grammar-action functions, removes obsolete inline K&R-style local declarations; regenerates y.tab.c
  • Adds the missing standard-library #includes and cross-file function prototypes needed once -Wimplicit-function-declaration (a hard error by default on modern clang) was no longer suppressed
  • Fixes the outc/outcf termcap callback signatures to match tputs()'s real prototype on macOS's ncurses-backed termcap.h
  • Fixes two buffer-overflow-adjacent strncpy size arguments (login.c terminal field, bbsmaild.c sender name)
  • Fixes a handful of genuine call-site bugs uncovered by the now-correct prototypes (missing execute() argument in netmail.c, SelectBoard/yyerror signature mismatches in nmenus.c)
  • Adds etc -> config symlink and .gitignore entries for runtime files (log, tmp/, .shmkey, .utable)

Test plan

  • make clean && make builds all binaries (lbbs, chatd, addacct, delacct, bbslog, bbfinger, bbsmaild) with 0 errors and 0 warnings on macOS/Apple Silicon with Xcode clang
  • Verified full interactive login flow (SYSOP account) reaches the Main Menu without crashing
  • Smoke-tested all seven binaries' CLI entry points (usage output / expected startup behavior) after the full ANSI-C conversion

Adds a DARWIN os profile, updates CCFLAGS for modern clang stricter K&R diagnostics, and fixes two variadic functions (prints, bbslog) that lacked prototypes visible at their call sites. On ARM64 this caused va_arg to read corrupted values and crash with SIGSEGV.
@catskillmarina

Copy link
Copy Markdown

thanks

Converts every K&R-style function definition to ANSI C prototype form and
adds the missing standard-library #includes and cross-file function
prototypes that -Wimplicit-function-declaration (a hard error by default
on modern clang) exposed once removed from the Makefile's suppression
flags. Also fixes the outc/outcf termcap callback signatures to match
tputs()'s real prototype, two buffer-overflow-adjacent strncpy sizes,
and a handful of genuine call-site bugs (missing execute() argument,
SelectBoard/yyerror signature mismatches) uncovered by the now-correct
prototypes.

make clobber && make all now completes with 0 errors and 0 warnings,
and all seven binaries (lbbs, chatd, addacct, delacct, bbslog, bbfinger,
bbsmaild) still run correctly.
@virtadpt

virtadpt commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Hi! I saw your PR and I'll get it merged as soon as I can get it to build on my laptop. I don't have a Mac to test on I'm afraid, but I did try to compile it on my Linux box and it failed about halfway through. I saw that you added some more changes and once I get them pulled into my local copy I'll give it another try.

@virtadpt

virtadpt commented Jul 7, 2026

Copy link
Copy Markdown
Owner

make clobber passed. make all failed with an error in login.c:

gcc -O -DCOLOR -std=gnu89    -c -o login.o login.c
login.c: In function ‘get_remote_host’:
login.c:40:21: error: ‘UTMPX_FILE’ undeclared (first use in this function); did you mean ‘UTMP_FILE’?
   40 | #  define UTMP_FILE UTMPX_FILE
      |                     ^~~~~~~~~~
login.c:152:18: note: in expansion of macro ‘UTMP_FILE’
  152 |   if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) {
      |                  ^~~~~~~~~
login.c:40:21: note: each undeclared identifier is reported only once for each function it appears in
login.c:152:18: note: in expansion of macro ‘UTMP_FILE’
  152 |   if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) {
      |                  ^~~~~~~~~
make: *** [<builtin>: login.o] Error 1

I'm not sure yet if this is due to your changes or a bug that needs fixed in general.

Hardcoded DARWIN=1/FREEBSD=1 in osdeps.h broke builds on other platforms.
Replace with auto-detection via compiler predefined macros (__APPLE__,
__FreeBSD__, __linux__) so no manual edits are needed per platform.

Also add DARWIN to NO_TERMIO (macOS lacks termio.h, previously covered by
the FREEBSD=1 alias) and LINUX to USES_UTMPX (modern Linux has utmpx).

In login.c, fall back to _PATH_UTMPX from <paths.h> when UTMPX_FILE is
not defined - Linux's utmpx.h omits UTMPX_FILE unlike macOS.
@DrPitre

DrPitre commented Jul 8, 2026

Copy link
Copy Markdown
Author

Thanks for testing on Linux! I just pushed a fix for that. The root cause was that the macOS port hardcoded DARWIN=1 and FREEBSD=1 in osdeps.h, which got picked up on your Linux build and triggered the utmpx path — but Linux's <utmpx.h> doesn't define UTMPX_FILE the way macOS does.

The fix does two things:

  1. osdeps.h: Platform flags are now auto-detected from compiler predefined macros (__APPLE__, __FreeBSD__, __linux__), so the file no longer needs to be manually edited per platform.

  2. login.c: When UTMPX_FILE isn't defined (Linux), it now falls back to _PATH_UTMPX from <paths.h>, then /var/run/utmpx as a last resort.

make clobber && make all should work on your Linux box now without any manual changes. Let me know how it goes!

@catskillmarina

Copy link
Copy Markdown

It seems the original author is still working on this -> https://wq5l.net/ebbs/ .

I never knew !

@virtadpt

virtadpt commented Jul 8, 2026

Copy link
Copy Markdown
Owner

@DrPitre Thank you - I'll give it a try later today.

@catskillmarina I had no idea - holy crap!

- osdeps.h: add __APPLE__ to LACKS_MALLOC_H; define OLCUC/XCASE=0 for macOS
- pbbs/term.c: use tcgetattr/tcsetattr on macOS instead of ioctl(TIOCGETA)
  to fix 'Bad address' crash on Apple Silicon
- clientui.h, pbbs/io.h: declare prints() with variadic prototype so all
  callers use the correct ARM64 ABI (fixes SIGSEGV in va_arg)
- Makefile: omit -lcrypt on Darwin (crypt is in libSystem)
- gram.y: convert K&R functions to ANSI C, add forward declarations,
  fix assignment-in-condition warnings; regenerate y.tab.c
- All .c files: convert K&R function definitions to ANSI C prototypes,
  add missing return types and return statements, fix -Wparentheses and
  -Wpointer-sign warnings (zero warnings build)
- Add etc -> config symlink and ignore runtime files (log, tmp/, .shmkey)
@DrPitre DrPitre changed the title Port eBBS 3.1.1 to build and run on macOS/Darwin (Apple Silicon) Port eBBS 3.1.4-rc2 to build and run on macOS/Darwin (Apple Silicon) Jul 8, 2026
@DrPitre

DrPitre commented Jul 8, 2026

Copy link
Copy Markdown
Author

I just updated my fork to Ray's 3.1.4 rc2 code, so this is the latest!

@virtadpt

Copy link
Copy Markdown
Owner

Because I was having some trouble, I erased my old clone of the repo with your PR applied and re-pulled it. make all still fails:

gcc -O -DCOLOR -Wno-implicit-function-declaration -Wno-implicit-int    -c -o client.o client.c
client.c: In function ‘hit_alarm_clock’:
client.c:139:19: error: passing argument 2 of ‘signal’ from incompatible pointer type [[-Wincompatible-pointer-types](https://gcc.gnu.org/onlinedocs/gcc-16.1.0/gcc/Warning-Options.html#index-Wincompatible-pointer-types)]
  139 |   signal(SIGALRM, hit_alarm_clock);
      |                   ^~~~~~~~~~~~~~~
      |                   |
      |                   void (*)(void)
In file included from client.c:22:
/usr/include/signal.h:88:57: note: expected ‘__sighandler_t’ {aka ‘void (*)(int’} but argument is of type ‘void (*)(void)’
   88 | extern __sighandler_t signal (int __sig, __sighandler_t __handler)
      |                                          ~~~~~~~~~~~~~~~^~~~~~~~~
client.c:133:1: note: ‘hit_alarm_clock’ declared here
  133 | hit_alarm_clock()
      | ^~~~~~~~~~~~~~~
/usr/include/signal.h:72:16: note: ‘__sighandler_t’ declared here
   72 | typedef void (*__sighandler_t) (int);
      |                ^~~~~~~~~~~~~~
client.c: In function ‘set_idle_alarm’:
client.c:146:21: error: passing argument 2 of ‘signal’ from incompatible pointer type [[-Wincompatible-pointer-types](https://gcc.gnu.org/onlinedocs/gcc-16.1.0/gcc/Warning-Options.html#index-Wincompatible-pointer-types)]
  146 |     signal(SIGALRM, hit_alarm_clock);
      |                     ^~~~~~~~~~~~~~~
      |                     |
      |                     void (*)(void)
/usr/include/signal.h:88:57: note: expected ‘__sighandler_t’ {aka ‘void (*)(int’} but argument is of type ‘void (*)(void)’
   88 | extern __sighandler_t signal (int __sig, __sighandler_t __handler)
      |                                          ~~~~~~~~~~~~~~~^~~~~~~~~
client.c:133:1: note: ‘hit_alarm_clock’ declared here
  133 | hit_alarm_clock()
      | ^~~~~~~~~~~~~~~
/usr/include/signal.h:72:16: note: ‘__sighandler_t’ declared here
   72 | typedef void (*__sighandler_t) (int);
      |                ^~~~~~~~~~~~~~
make: *** [<builtin>: client.o] Error 1

hit_alarm_clock() was declared K&R-style with no parameters, which
modern compilers treat as void(*)(void) instead of the void(*)(int)
signal() expects. Reported by virtadpt building on Linux with gcc 16.
@DrPitre

DrPitre commented Jul 14, 2026

Copy link
Copy Markdown
Author

Thanks for testing again! Fixed — the issue was that hit_alarm_clock() in client.c was declared K&R-style with no parameters, which under strict modern compilers (gcc 16, clang) resolves to void (*)(void) instead of the void (*)(int) that signal() expects.

Pushed a fix (899ca42) that gives it an explicit int parameter. make clobber && make all builds clean here. Let me know how it goes on your box.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants