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 /src | |
| 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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.c | 56 | ||||
| -rw-r--r-- | src/pty.c | 46 |
2 files changed, 54 insertions, 48 deletions
@@ -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; } |
