diff options
| author | user <user@clank> | 2026-08-26 16:11:42 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-26 16:11:42 +0200 |
| commit | 087b2bd1d31dac24f8b0ffe79c33f4ebf1f60bd3 (patch) | |
| tree | 282ce9a0e243333bb769bae231426cb4f9cf3a86 /src/server.c | |
| parent | compact: shared borders instead of gaps (D23) (diff) | |
| download | slosh-087b2bd1d31dac24f8b0ffe79c33f4ebf1f60bd3.tar.gz slosh-087b2bd1d31dac24f8b0ffe79c33f4ebf1f60bd3.tar.xz slosh-087b2bd1d31dac24f8b0ffe79c33f4ebf1f60bd3.zip | |
macos: the kernel still knows, it just spells /proc differently
Portability fixes contributed by our macOS developer, applied with one
hardening tweak (below).
Darwin has no /proc, so everything that read one gets the native answer:
live_cwd via proc_pidinfo(PROC_PIDVNODEPATHINFO), the foreground command
via sysctl(KERN_PROCARGS2) parsed back into the NUL-separated shape
/proc/<pid>/cmdline gives, and SLOSH_BIN via _NSGetExecutablePath plus
realpath. The pty gets its winsize set on the slave after opening it,
because Darwin attaches no line discipline to the master until then and
the earlier TIOCSWINSZ was silently dropped -- a pane born 0x0. The
shader repl binds tab in libedit's own words, since macOS ships Python's
readline as a libedit wrapper that accepts GNU syntax in silence.
Two finds are cross-platform bugs: a toast wider than the screen minus
the gap computed a negative x that uint16_t made ~65533, drawing the
longest messages -- the ones most worth reading -- off screen; now the
middle is elided (a path's tail is the half you needed) and x clamps.
And a pane label was 128 bytes, which a Homebrew interpreter's full path
exceeds before its arguments even start; dump-layout wrote the
truncation down and a restore ran it, so it is 1024 now.
Saving a layout learned cwd_as_named: the kernel answers with the
physical path, and on macOS /tmp is a symlink to /private/tmp, so a
layout that said cwd="/tmp" stopped round-tripping through a save.
If realpath(named) is where the pane still is, the named spelling wins.
Tests follow: realpath'd tmpdirs, the scroll test reads the shell's
first prompt instead of spelling out bash 5.3, and wrapped pane text is
joined before matching a long path.
One tweak on top of the contribution: the elision needs five columns
for a head, the dots and a tail -- below that `avail - 3` goes
negative, and negative as size_t is a pointer into the weeds; a
terminal that narrow gets a plain clip.
Diffstat (limited to 'src/server.c')
| -rw-r--r-- | src/server.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/src/server.c b/src/server.c index 4679e04..ab811d9 100644 --- a/src/server.c +++ b/src/server.c @@ -4,6 +4,10 @@ #define _GNU_SOURCE #include "server.h" +#ifdef __APPLE__ +#include <mach-o/dyld.h> /* _NSGetExecutablePath: Darwin has no /proc/self/exe */ +#endif + #include "config.h" /* The config-file watcher speaks the OS's native change-notification API: @@ -338,11 +342,20 @@ void session_env(const char *name) { else unsetenv("SLOSH_SESSION"); char self[512]; +#ifdef __APPLE__ + /* Darwin's answer to /proc/self/exe. What it hands back can still contain + * symlinks and .., so realpath() finishes the job. */ + char raw[512]; + uint32_t sz = sizeof raw; + if (_NSGetExecutablePath(raw, &sz) == 0 && realpath(raw, self)) + setenv("SLOSH_BIN", self, 1); +#else ssize_t sn = readlink("/proc/self/exe", self, sizeof self - 1); if (sn > 0) { self[sn] = 0; setenv("SLOSH_BIN", self, 1); } +#endif } int server_run(const char *name, const char *const argv[], uint16_t cols, |
