diff options
| author | user <user@clank> | 2026-09-02 16:24:41 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-02 16:24:41 +0200 |
| commit | c58a875ef3bcb464cdbea72bdbd0a874b6f93729 (patch) | |
| tree | f2000cae2b8ca1f110f344080dde1d70114b15ea | |
| parent | slosh --install-terminfo: the binary carries its own terminfo entry (diff) | |
| download | slosh-c58a875ef3bcb464cdbea72bdbd0a874b6f93729.tar.gz slosh-c58a875ef3bcb464cdbea72bdbd0a874b6f93729.tar.xz slosh-c58a875ef3bcb464cdbea72bdbd0a874b6f93729.zip | |
pty: install the terminfo entry implicitly when it is missing everywhere
The lookup miss now writes the embedded entry to ~/.terminfo and
uses it, so a bare box gets the full TERM with no step at all. An
entry that exists anywhere is respected -- possibly newer, certainly
somebody's -- and a HOME that cannot be written leaves the
xterm-256color fallback standing. --install-terminfo stays as the
by-hand spelling; the writer moved to pty.c where the panes are.
| -rw-r--r-- | docs/slosh.1 | 27 | ||||
| -rw-r--r-- | include/slosh.h | 4 | ||||
| -rw-r--r-- | src/main.c | 56 | ||||
| -rw-r--r-- | src/pty.c | 46 |
4 files changed, 71 insertions, 62 deletions
diff --git a/docs/slosh.1 b/docs/slosh.1 index cce0b64..6436f6a 100644 --- a/docs/slosh.1 +++ b/docs/slosh.1 @@ -152,12 +152,9 @@ Write the .B xterm-ghostty terminfo entry the binary carries into .I ~/.terminfo -(no root, no package), so panes on a machine without ghostty's entry -get the full -.B TERM -instead of the -.B xterm-256color -fallback. +(no root, no package). +Sessions do this on their own when the entry is missing everywhere; the +flag is the by-hand spelling, for provisioning and for saying so. See ENVIRONMENT. .TP .BI \-\-server\ name @@ -364,14 +361,16 @@ Set in every pane: .TP .B TERM .B xterm-ghostty -when the machine's terminfo database has the entry (it ships with ghostty), -.B xterm-256color -when it does not: an entry curses cannot find makes editors exit on -the spot and backspace guess. -.B slosh \-\-install\-terminfo -puts the real entry in -.IR ~/.terminfo ; -new sessions then use it. +\(en found in the machine's terminfo database, or, when it is missing +everywhere, installed into +.I ~/.terminfo +from the copy the binary carries (an entry curses cannot find makes +editors exit on the spot and backspace guess). +Only when even that write fails (no +.BR $HOME , +read-only) do panes get +.BR xterm-256color , +and everything still works. .TP .B SLOSH .B 1 diff --git a/include/slosh.h b/include/slosh.h index 75aa658..47d8220 100644 --- a/include/slosh.h +++ b/include/slosh.h @@ -162,6 +162,10 @@ typedef struct { /* `cell_w`/`cell_h` are the client's cell size in pixels, so the pty's * winsize carries real pixel dimensions: a program that draws images asks the * tty how big a cell is, and zeroes there mean it cannot size one. */ +/* Write the embedded xterm-ghostty terminfo into ~/.terminfo (0 on + * success). Panes do this on their own when the entry is missing + * everywhere; `slosh --install-terminfo` is the by-hand spelling. */ +int pty_terminfo_install(void); int pty_spawn(pty_t *p, const char *const argv[], uint16_t cols, uint16_t rows, const char *cwd, uint16_t cell_w, uint16_t cell_h); int pty_resize(pty_t *p, uint16_t cols, uint16_t rows, uint16_t cell_w, @@ -26,58 +26,18 @@ #include "version.h" #ifndef _WIN32 -#include <errno.h> -#include <sys/stat.h> - -#include "terminfo.h" - -/* Write the embedded xterm-ghostty terminfo entry into ~/.terminfo, which - * is the first place curses looks: no root, no package, no conflict with a - * ghostty the machine may install later (its own entry in the system - * database simply stops being needed). Written under every name the entry - * answers to, in the letter layout and Darwin's hashed one, because the - * lookup is by filename. */ +/* The write itself lives in pty.c (pty_terminfo_install), because panes do + * it on their own when the entry is missing everywhere. This flag is the + * by-hand spelling, with a report around it. */ static int install_terminfo(void) { - const char *home = getenv("HOME"); - if (!home || !*home) { - fputs("slosh: no $HOME to install into\n", stderr); + if (pty_terminfo_install() != 0) { + fputs("slosh: could not write ~/.terminfo (no $HOME, or not writable)\n", + stderr); return 1; } - /* dir, then name inside it: x/ and 78/ for xterm-ghostty, g/ and 67/ for - * the ghostty alias. */ - static const char *const spots[][2] = { - {"x", "xterm-ghostty"}, - {"78", "xterm-ghostty"}, - {"g", "ghostty"}, - {"67", "ghostty"}, - }; - char path[1024]; - snprintf(path, sizeof path, "%s/.terminfo", home); - if (mkdir(path, 0755) != 0 && errno != EEXIST) { - fprintf(stderr, "slosh: mkdir %s: %s\n", path, strerror(errno)); - return 1; - } - for (size_t i = 0; i < sizeof spots / sizeof *spots; i++) { - snprintf(path, sizeof path, "%s/.terminfo/%s", home, spots[i][0]); - if (mkdir(path, 0755) != 0 && errno != EEXIST) { - fprintf(stderr, "slosh: mkdir %s: %s\n", path, strerror(errno)); - return 1; - } - snprintf(path, sizeof path, "%s/.terminfo/%s/%s", home, spots[i][0], - spots[i][1]); - FILE *f = fopen(path, "wb"); - if (!f || fwrite(TERMINFO_GHOSTTY, 1, sizeof TERMINFO_GHOSTTY, f) != - sizeof TERMINFO_GHOSTTY) { - fprintf(stderr, "slosh: write %s: %s\n", path, strerror(errno)); - if (f) fclose(f); - return 1; - } - fclose(f); - } - printf("installed xterm-ghostty (and the ghostty alias) into %s/.terminfo\n" + printf("installed xterm-ghostty (and the ghostty alias) into ~/.terminfo\n" "new sessions use it; a session already running keeps the TERM it\n" - "chose at startup until it is restarted\n", - home); + "chose at startup until it is restarted\n"); return 0; } #endif @@ -8,6 +8,9 @@ #include "slosh.h" #include <errno.h> +#include <sys/stat.h> + +#include "terminfo.h" #include <fcntl.h> #include <signal.h> #include <stdio.h> @@ -33,6 +36,41 @@ * lookup happens where it matters: panes run on the server's machine. * * Computed once, in the parent, before the first fork. */ +/* Write the embedded xterm-ghostty terminfo entry into ~/.terminfo, which + * is the first place curses looks: no root, no package, no conflict with a + * ghostty the machine may install later. Written under every name the + * entry answers to, in the letter layout and Darwin's hashed one, because + * the lookup is by filename. Quiet: pty_term() below calls this on its own + * when the entry is nowhere to be found, and `--install-terminfo` is the + * same write with a friendly report around it. */ +int pty_terminfo_install(void) { + const char *home = getenv("HOME"); + if (!home || !*home) return -1; + static const char *const spots[][2] = { + {"x", "xterm-ghostty"}, + {"78", "xterm-ghostty"}, + {"g", "ghostty"}, + {"67", "ghostty"}, + }; + char path[1024]; + snprintf(path, sizeof path, "%s/.terminfo", home); + if (mkdir(path, 0755) != 0 && errno != EEXIST) return -1; + for (size_t i = 0; i < sizeof spots / sizeof *spots; i++) { + snprintf(path, sizeof path, "%s/.terminfo/%s", home, spots[i][0]); + if (mkdir(path, 0755) != 0 && errno != EEXIST) return -1; + snprintf(path, sizeof path, "%s/.terminfo/%s/%s", home, spots[i][0], + spots[i][1]); + FILE *f = fopen(path, "wb"); + if (!f || fwrite(TERMINFO_GHOSTTY, 1, sizeof TERMINFO_GHOSTTY, f) != + sizeof TERMINFO_GHOSTTY) { + if (f) fclose(f); + return -1; + } + fclose(f); + } + return 0; +} + static bool term_add(char *dirs, size_t cap, size_t *n, const char *d) { if (!d || !*d) return false; int w = snprintf(dirs + *n, cap - *n, "%s%s", *n ? ":" : "", d); @@ -74,6 +112,14 @@ static const char *pty_term(void) { break; } } + + /* Nowhere at all: put our own copy in ~/.terminfo and use it. The write + * happens only when the entry is missing everywhere -- an entry that + * exists is somebody's, possibly newer than ours, and stays theirs. On a + * $HOME that cannot be written the fallback stands, and everything still + * works at xterm-256color. */ + if (strcmp(cached, "xterm-256color") == 0 && pty_terminfo_install() == 0) + cached = "xterm-ghostty"; return cached; } |
