Re: [dev] [st][PATCH] better plumbing on linux: find child shell cwd without shell gymnastics

From: John Soros <j_AT_roxor.me>
Date: Fri, 2 Nov 2018 10:06:40 +0100

On 01/11/2018 17:54, Markus Wichmann wrote:
> On Thu, Nov 01, 2018 at 04:12:40PM +0100, John Soros wrote:
>> Yes! This is much, much better! Thanks. Pity that it still doesn't work
>> on OpenBSD.
>
> If the info I gathered over the course of the last hour is correct, then
> the way to query CWD in OpenBSD is
>
> #include <sys/sysctl.h>
> char cwd[PATH_MAX];
> size_t sz = sizeof cwd;
> int name[3] = {CTL_KERN, KERN_PROC_CWD, pid};
> sysctl(name, 3, cwd, &sz, 0, 0);
Nice!

> Also, if my understanding of Linux /proc is correct, then realpath()
> might be overkill, and readlink() would already suffice.
Looks to me like even readlink is overkill!

> The question is how to incorporate such code. Do we create OS specific
> source files and compile in the ones needed, or do we go for conditional
> compilation? The former is more complicated, as it involves mapping out
> an interface that each OS source file has to follow. And in the long
> run, it might start sucking, as the OSes aren't as orthogonal as
> originally thought, and we end up copying some functions, and then
> having to copy bugfixes... sucks a bit. Conditionals also suck a bit, as
> we end up seeing a lot of what amounts to commented-out code. Giving up
> on unportable features also sucks, as it precludes useful features like
> the one in this submission. So, which option sucks least?
I decided to use conditional compilation because the code already
contains some of that, and I would feel bad for creating a separate file
for so little code.

>
> Ciao,
> Markus
>
Thank you for the help, Markus, I am really happy with the result! I
guess freebsd, apple, netbsd and dragonfly are still a question, so I'm
not sure this patch should be included in the main distribution anyways.
I would be very happy if it was in the patches section, already.
I tested the patch on linux and openbsd 6.4.
Cheers,
John

 config.def.h | 6 ++++++
 st.c | 21 ++++++++++++++++++++-
 st.h | 2 ++
 x.c | 26 ++++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/config.def.h b/config.def.h
index 823e79f..08e6ed4 100644
--- a/config.def.h
+++ b/config.def.h
_AT_@ -459,3 +459,9 @@ static char ascii_printable[] =
         " !\"#$%&'()*+,-./0123456789:;<=>?"
         "_AT_ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
         "`abcdefghijklmnopqrstuvwxyz{|}~";
+
+/*
+ * plumb_cmd is run on mouse button 3 click, with argument set to
+ * current selection and with cwd set to the cwd of the active shell
+ */
+static char *plumb_cmd = "plumb";
diff --git a/st.c b/st.c
index 46cf2da..9a2ad65 100644
--- a/st.c
+++ b/st.c
_AT_@ -27,6 +27,9 @@
 #elif defined(__FreeBSD__) || defined(__DragonFly__)
  #include <libutil.h>
 #endif
+#if defined(__OpenBSD__)
+ #include <sys/sysctl.h>
+#endif

 /* Arbitrary sizes */
 #define UTF_INVALID 0xFFFD
_AT_@ -232,6 +235,22 @@ static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80,
0xE0, 0xF0, 0xF8};
 static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800,
0x10000};
 static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF,
0x10FFFF};

+int
+subprocwd(char *path)
+{
+#if defined(__linux)
+ if (snprintf(path, PATH_MAX, "/proc/%d/cwd", pid) < 0)
+ return -1;
+ return 0;
+#elif defined(__OpenBSD__)
+ size_t sz = PATH_MAX;
+ int name[3] = {CTL_KERN, KERN_PROC_CWD, pid};
+ if (sysctl(name, 3, path, &sz, 0, 0) == -1)
+ return -1;
+ return 0;
+#endif
+}
+
 ssize_t
 xwrite(int fd, const char *s, size_t len)
 {
_AT_@ -810,7 +829,7 @@ ttynew(char *line, char *cmd, char *out, char **args)
                 break;
         default:
 #ifdef __OpenBSD__
- if (pledge("stdio rpath tty proc", NULL) == -1)
+ if (pledge("stdio rpath tty proc ps exec", NULL) == -1)
                         die("pledge\n");
 #endif
                 close(s);
diff --git a/st.h b/st.h
index 38c61c4..1f87287 100644
--- a/st.h
+++ b/st.h
_AT_@ -110,6 +110,8 @@ void *xmalloc(size_t);
 void *xrealloc(void *, size_t);
 char *xstrdup(char *);

+int subprocwd(char *);
+
 /* config.h globals */
 extern char *utmp;
 extern char *stty_args;
diff --git a/x.c b/x.c
index 00cb6b1..e03dc71 100644
--- a/x.c
+++ b/x.c
_AT_@ -5,6 +5,7 @@
 #include <locale.h>
 #include <signal.h>
 #include <sys/select.h>
+#include <sys/wait.h>
 #include <time.h>
 #include <unistd.h>
 #include <libgen.h>
_AT_@ -635,6 +636,29 @@ xsetsel(char *str)
         setsel(str, CurrentTime);
 }

+void
+plumb(char *sel) {
+ if (sel == NULL)
+ return;
+ char cwd[PATH_MAX];
+ pid_t child;
+ if (subprocwd(cwd) != 0)
+ return;
+
+ switch(child = fork()) {
+ case -1:
+ return;
+ case 0:
+ if (chdir(cwd) != 0)
+ exit(1);
+ if (execvp(plumb_cmd, (char *const []){plumb_cmd, sel, 0}) == -1)
+ exit(1);
+ exit(0);
+ default:
+ waitpid(child, NULL, 0);
+ }
+}
+
 void
 brelease(XEvent *e)
 {
_AT_@ -647,6 +671,8 @@ brelease(XEvent *e)
                 selpaste(NULL);
         else if (e->xbutton.button == Button1)
                 mousesel(e, 1);
+ else if (e->xbutton.button == Button3)
+ plumb(xsel.primary);
 }

 void
Received on Fri Nov 02 2018 - 10:06:40 CET

This archive was generated by hypermail 2.3.0 : Fri Nov 02 2018 - 10:12:07 CET