aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authoruser <user@clank>2026-09-02 16:24:41 +0200
committeruser <user@clank>2026-09-02 16:24:41 +0200
commitc58a875ef3bcb464cdbea72bdbd0a874b6f93729 (patch)
treef2000cae2b8ca1f110f344080dde1d70114b15ea /src
parentslosh --install-terminfo: the binary carries its own terminfo entry (diff)
downloadslosh-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.c56
-rw-r--r--src/pty.c46
2 files changed, 54 insertions, 48 deletions
diff --git a/src/main.c b/src/main.c
index 3fdbfe6..838d6f7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
diff --git a/src/pty.c b/src/pty.c
index f715acc..00fa190 100644
--- a/src/pty.c
+++ b/src/pty.c
@@ -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;
}