141 lines
3.7 KiB
Diff
141 lines
3.7 KiB
Diff
From 6640cf9809086d8cfb2363571d3e71a1a7a9f6bd Mon Sep 17 00:00:00 2001
|
|
From: meator <meator.dev@gmail.com>
|
|
Date: Tue, 25 Oct 2022 20:19:28 +0200
|
|
Subject: [PATCH] Add support for tmux in newterm
|
|
|
|
This commit tries to figure out if st's child is tmux and if so, it
|
|
launches a shell with the CWD of the current process in the tmux session
|
|
instead of the tmux client itself.
|
|
|
|
This is heavily inspired by
|
|
https://gist.github.com/TiddoLangerak/c61e1e48df91192f9554 (but
|
|
converted to C).
|
|
|
|
Tmux has to be a direct child of st. This means that you'll have to
|
|
usually use the 'exec' shell builtin to attach tmux sessions.
|
|
|
|
This patch only works on Linux. Other systems use different procfs which
|
|
is incompatible or don't have procfs at all (or it's optional).
|
|
---
|
|
st.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 82 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/st.c b/st.c
|
|
index 0261283..b95bf7a 100644
|
|
--- a/st.c
|
|
+++ b/st.c
|
|
@@ -221,6 +221,8 @@ static char base64dec_getc(const char **);
|
|
|
|
static ssize_t xwrite(int, const char *, size_t);
|
|
|
|
+static int gettmuxpts(void);
|
|
+
|
|
/* Globals */
|
|
static Term term;
|
|
static Selection sel;
|
|
@@ -1061,6 +1063,12 @@ tswapscreen(void)
|
|
void
|
|
newterm(const Arg* a)
|
|
{
|
|
+ int pts;
|
|
+ FILE *fsession, *fpid;
|
|
+ char session[5];
|
|
+ char pidstr[10];
|
|
+ char buf[48];
|
|
+ size_t size;
|
|
switch (fork()) {
|
|
case -1:
|
|
die("fork failed: %s\n", strerror(errno));
|
|
@@ -1072,7 +1080,37 @@ newterm(const Arg* a)
|
|
_exit(1);
|
|
break;
|
|
case 0:
|
|
- chdir_by_pid(pid);
|
|
+ signal(SIGCHLD, SIG_DFL); /* pclose() needs to use wait() */
|
|
+ pts = gettmuxpts();
|
|
+ if (pts != -1) {
|
|
+ snprintf(buf, sizeof buf, "tmux lsc -t /dev/pts/%d -F \"#{client_session}\"", pts);
|
|
+ fsession = popen(buf, "r");
|
|
+ if (!fsession) {
|
|
+ fprintf(stderr, "Couldn't launch tmux.");
|
|
+ _exit(1);
|
|
+ }
|
|
+ size = fread(session, 1, sizeof session, fsession);
|
|
+ if (pclose(fsession) != 0 || size == 0) {
|
|
+ fprintf(stderr, "Couldn't get tmux session.");
|
|
+ _exit(1);
|
|
+ }
|
|
+ session[size - 1] = '\0'; /* size - 1 is used to also trim the \n */
|
|
+
|
|
+ snprintf(buf, sizeof buf, "tmux list-panes -st %s -F \"#{pane_pid}\"", session);
|
|
+ fpid = popen(buf, "r");
|
|
+ if (!fpid) {
|
|
+ fprintf(stderr, "Couldn't launch tmux.");
|
|
+ _exit(1);
|
|
+ }
|
|
+ size = fread(pidstr, 1, sizeof pidstr, fpid);
|
|
+ if (pclose(fpid) != 0 || size == 0) {
|
|
+ fprintf(stderr, "Couldn't get tmux session.");
|
|
+ _exit(1);
|
|
+ }
|
|
+ pidstr[size - 1] = '\0';
|
|
+ }
|
|
+
|
|
+ chdir_by_pid(pts != -1 ? atol(pidstr) : pid);
|
|
execl("/proc/self/exe", argv0, NULL);
|
|
_exit(1);
|
|
break;
|
|
@@ -1092,6 +1130,49 @@ chdir_by_pid(pid_t pid)
|
|
return chdir(buf);
|
|
}
|
|
|
|
+/* returns the pty of tmux client or -1 if the child of st isn't tmux */
|
|
+static int
|
|
+gettmuxpts(void)
|
|
+{
|
|
+ char buf[32];
|
|
+ char comm[17];
|
|
+ int tty;
|
|
+ FILE *fstat;
|
|
+ FILE *fcomm;
|
|
+ size_t numread;
|
|
+
|
|
+ snprintf(buf, sizeof buf, "/proc/%ld/comm", (long)pid);
|
|
+
|
|
+ fcomm = fopen(buf, "r");
|
|
+ if (!fcomm) {
|
|
+ fprintf(stderr, "Couldn't open %s: %s\n", buf, strerror(errno));
|
|
+ _exit(1);
|
|
+ }
|
|
+
|
|
+ numread = fread(comm, 1, sizeof comm - 1, fcomm);
|
|
+ comm[numread] = '\0';
|
|
+
|
|
+ fclose(fcomm);
|
|
+
|
|
+ if (strcmp("tmux: client\n", comm) != 0)
|
|
+ return -1;
|
|
+
|
|
+ snprintf(buf, sizeof buf, "/proc/%ld/stat", (long)pid);
|
|
+ fstat = fopen(buf, "r");
|
|
+ if (!fstat) {
|
|
+ fprintf(stderr, "Couldn't open %s: %s\n", buf, strerror(errno));
|
|
+ _exit(1);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * We can't skip the second field with %*s because it contains a space so
|
|
+ * we skip strlen("tmux: client") + 2 for the braces which is 14.
|
|
+ */
|
|
+ fscanf(fstat, "%*d %*14c %*c %*d %*d %*d %d", &tty);
|
|
+ fclose(fstat);
|
|
+ return ((0xfff00000 & tty) >> 12) | (0xff & tty);
|
|
+}
|
|
+
|
|
void
|
|
tscrolldown(int orig, int n)
|
|
{
|
|
--
|
|
2.38.0
|
|
|