1From 85a6bb6ba81de493c0ceb9a8d4c2f78eb5d1567f Mon Sep 17 00:00:00 2001
2From: Michael Forney <mforney@mforney.org>
3Date: Wed, 2 Dec 2020 17:54:35 -0800
4Subject: [PATCH] Add support for plumbing via right click
5
6---
7 config.def.h | 5 ++++
8 st.c | 79 ++++++++++++++++++++++++++++++++++++++++++++--------
9 2 files changed, 72 insertions(+), 12 deletions(-)
10
11diff --git a/config.def.h b/config.def.h
12index 49ca50b..a63d2be 100644
13--- a/config.def.h
14+++ b/config.def.h
15@@ -460,3 +460,8 @@ static char ascii_printable[] =
16 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
17 "`abcdefghijklmnopqrstuvwxyz{|}~";
18
19+/*
20+ * plumb_cmd is run on mouse button 3 click, with first NULL set to
21+ * current selection and with cwd set to the cwd of the active shell
22+ */
23+static char *plumb_cmd[] = {"plumb", NULL, NULL};
24diff --git a/st.c b/st.c
25index 20a3c3c..914fdd5 100644
26--- a/st.c
27+++ b/st.c
28@@ -44,6 +44,9 @@ char *argv0;
29 #elif defined(__FreeBSD__) || defined(__DragonFly__)
30 #include <libutil.h>
31 #endif
32+#if defined(__OpenBSD__)
33+ #include <sys/sysctl.h>
34+#endif
35
36
37 /* Arbitrary sizes */
38@@ -558,6 +561,8 @@ static void *xmalloc(size_t);
39 static void *xrealloc(void *, size_t);
40 static char *xstrdup(char *);
41
42+static int subprocwd(char *, size_t);
43+
44 static void usage(void);
45
46 static struct wl_registry_listener reglistener = { regglobal, regglobalremove };
47@@ -579,6 +584,7 @@ static struct wl_data_source_listener datasrclistener =
48 { datasrctarget, datasrcsend, datasrccancelled };
49
50 /* Globals */
51+static int plumbsel;
52 static DC dc;
53 static Wayland wl;
54 static WLD wld;
55@@ -763,6 +769,21 @@ utf8validate(Rune *u, size_t i)
56 return i;
57 }
58
59+int
60+subprocwd(char *path, size_t len)
61+{
62+#if defined(__linux__)
63+ if (snprintf(path, len, "/proc/%d/cwd", pid) < 0)
64+ return -1;
65+ return 0;
66+#elif defined(__OpenBSD__)
67+ int name[3] = {CTL_KERN, KERN_PROC_CWD, pid};
68+ if (sysctl(name, 3, path, &len, 0, 0) == -1)
69+ return -1;
70+ return 0;
71+#endif
72+}
73+
74 void
75 selinit(void)
76 {
77@@ -1165,6 +1186,29 @@ wlsetsel(char *str, uint32_t serial)
78 wl_data_device_set_selection(wl.datadev, sel.source, serial);
79 }
80
81+void
82+plumbinit(void)
83+{
84+ for (plumbsel = 0; plumb_cmd[plumbsel]; ++plumbsel)
85+ ;
86+}
87+
88+void
89+plumb(char *sel)
90+{
91+ char cwd[PATH_MAX];
92+
93+ if (!sel || subprocwd(cwd, sizeof(cwd)) != 0)
94+ return;
95+ plumb_cmd[plumbsel] = sel;
96+
97+ if (fork() == 0) {
98+ if (chdir(cwd) == 0)
99+ execvp(plumb_cmd[0], plumb_cmd);
100+ _exit(1);
101+ }
102+}
103+
104 void
105 die(const char *errstr, ...)
106 {
107@@ -1227,15 +1271,18 @@ sigchld(int a)
108 int stat;
109 pid_t p;
110
111- if ((p = waitpid(pid, &stat, WNOHANG)) < 0)
112- die("Waiting for pid %hd failed: %s\n", pid, strerror(errno));
113-
114- if (pid != p)
115- return;
116-
117- if (!WIFEXITED(stat) || WEXITSTATUS(stat))
118- die("child finished with error '%d'\n", stat);
119- exit(0);
120+ for (;;) {
121+ p = waitpid(-1, &stat, WNOHANG);
122+ if (p == 0)
123+ break;
124+ if (p < 0)
125+ die("waitpid: %s\n", strerror(errno));
126+ if (pid == p) {
127+ if (!WIFEXITED(stat) || WEXITSTATUS(stat))
128+ die("child finished with error '%d'\n", stat);
129+ exit(0);
130+ }
131+ }
132 }
133
134
135@@ -4224,16 +4271,23 @@ ptrbutton(void * data, struct wl_pointer * pointer, uint32_t serial,
136
137 switch (state) {
138 case WL_POINTER_BUTTON_STATE_RELEASED:
139- if (button == BTN_MIDDLE) {
140+ switch (button) {
141+ case BTN_MIDDLE:
142 selpaste(NULL);
143- } else if (button == BTN_LEFT) {
144+ break;
145+ case BTN_LEFT:
146 if (sel.mode == SEL_READY) {
147 getbuttoninfo();
148 selcopy(serial);
149- } else
150+ } else {
151 selclear();
152+ }
153 sel.mode = SEL_IDLE;
154 tsetdirt(sel.nb.y, sel.ne.y);
155+ break;
156+ case BTN_RIGHT:
157+ plumb(sel.primary);
158+ break;
159 }
160 break;
161
162@@ -4557,6 +4611,7 @@ main(int argc, char *argv[])
163 } ARGEND;
164
165 run:
166+ plumbinit();
167 if (argc > 0) {
168 /* eat all remaining arguments */
169 opt_cmd = argv;
170--
1712.37.3
172