st-newterm-0.9-tmux.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
st-newterm-0.9-tmux.diff (3772B)
---
1 From 6640cf9809086d8cfb2363571d3e71a1a7a9f6bd Mon Sep 17 00:00:00 2001
2 From: meator <meator.dev@gmail.com>
3 Date: Tue, 25 Oct 2022 20:19:28 +0200
4 Subject: [PATCH] Add support for tmux in newterm
5
6 This commit tries to figure out if st's child is tmux and if so, it
7 launches a shell with the CWD of the current process in the tmux session
8 instead of the tmux client itself.
9
10 This is heavily inspired by
11 https://gist.github.com/TiddoLangerak/c61e1e48df91192f9554 (but
12 converted to C).
13
14 Tmux has to be a direct child of st. This means that you'll have to
15 usually use the 'exec' shell builtin to attach tmux sessions.
16
17 This patch only works on Linux. Other systems use different procfs which
18 is incompatible or don't have procfs at all (or it's optional).
19 ---
20 st.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
21 1 file changed, 82 insertions(+), 1 deletion(-)
22
23 diff --git a/st.c b/st.c
24 index 0261283..b95bf7a 100644
25 --- a/st.c
26 +++ b/st.c
27 @@ -221,6 +221,8 @@ static char base64dec_getc(const char **);
28
29 static ssize_t xwrite(int, const char *, size_t);
30
31 +static int gettmuxpts(void);
32 +
33 /* Globals */
34 static Term term;
35 static Selection sel;
36 @@ -1061,6 +1063,12 @@ tswapscreen(void)
37 void
38 newterm(const Arg* a)
39 {
40 + int pts;
41 + FILE *fsession, *fpid;
42 + char session[5];
43 + char pidstr[10];
44 + char buf[48];
45 + size_t size;
46 switch (fork()) {
47 case -1:
48 die("fork failed: %s\n", strerror(errno));
49 @@ -1072,7 +1080,37 @@ newterm(const Arg* a)
50 _exit(1);
51 break;
52 case 0:
53 - chdir_by_pid(pid);
54 + signal(SIGCHLD, SIG_DFL); /* pclose() needs to use wait() */
55 + pts = gettmuxpts();
56 + if (pts != -1) {
57 + snprintf(buf, sizeof buf, "tmux lsc -t /dev/pts/%d -F \"#{client_session}\"", pts);
58 + fsession = popen(buf, "r");
59 + if (!fsession) {
60 + fprintf(stderr, "Couldn't launch tmux.");
61 + _exit(1);
62 + }
63 + size = fread(session, 1, sizeof session, fsession);
64 + if (pclose(fsession) != 0 || size == 0) {
65 + fprintf(stderr, "Couldn't get tmux session.");
66 + _exit(1);
67 + }
68 + session[size - 1] = '\0'; /* size - 1 is used to also trim the \n */
69 +
70 + snprintf(buf, sizeof buf, "tmux list-panes -st %s -F \"#{pane_pid}\"", session);
71 + fpid = popen(buf, "r");
72 + if (!fpid) {
73 + fprintf(stderr, "Couldn't launch tmux.");
74 + _exit(1);
75 + }
76 + size = fread(pidstr, 1, sizeof pidstr, fpid);
77 + if (pclose(fpid) != 0 || size == 0) {
78 + fprintf(stderr, "Couldn't get tmux session.");
79 + _exit(1);
80 + }
81 + pidstr[size - 1] = '\0';
82 + }
83 +
84 + chdir_by_pid(pts != -1 ? atol(pidstr) : pid);
85 execl("/proc/self/exe", argv0, NULL);
86 _exit(1);
87 break;
88 @@ -1092,6 +1130,49 @@ chdir_by_pid(pid_t pid)
89 return chdir(buf);
90 }
91
92 +/* returns the pty of tmux client or -1 if the child of st isn't tmux */
93 +static int
94 +gettmuxpts(void)
95 +{
96 + char buf[32];
97 + char comm[17];
98 + int tty;
99 + FILE *fstat;
100 + FILE *fcomm;
101 + size_t numread;
102 +
103 + snprintf(buf, sizeof buf, "/proc/%ld/comm", (long)pid);
104 +
105 + fcomm = fopen(buf, "r");
106 + if (!fcomm) {
107 + fprintf(stderr, "Couldn't open %s: %s\n", buf, strerror(errno));
108 + _exit(1);
109 + }
110 +
111 + numread = fread(comm, 1, sizeof comm - 1, fcomm);
112 + comm[numread] = '\0';
113 +
114 + fclose(fcomm);
115 +
116 + if (strcmp("tmux: client\n", comm) != 0)
117 + return -1;
118 +
119 + snprintf(buf, sizeof buf, "/proc/%ld/stat", (long)pid);
120 + fstat = fopen(buf, "r");
121 + if (!fstat) {
122 + fprintf(stderr, "Couldn't open %s: %s\n", buf, strerror(errno));
123 + _exit(1);
124 + }
125 +
126 + /*
127 + * We can't skip the second field with %*s because it contains a space so
128 + * we skip strlen("tmux: client") + 2 for the braces which is 14.
129 + */
130 + fscanf(fstat, "%*d %*14c %*c %*d %*d %*d %d", &tty);
131 + fclose(fstat);
132 + return ((0xfff00000 & tty) >> 12) | (0xff & tty);
133 +}
134 +
135 void
136 tscrolldown(int orig, int n)
137 {
138 --
139 2.38.0
140