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 @@ -459,3 +459,9 @@ static char ascii_printable[] = " !\"#$%&'()*+,-./0123456789:;<=>?" "@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 @@ -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 @@ -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) { @@ -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 @@ -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 @@ -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> @@ -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) { @@ -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