[dev] [st][PATCH] better plumbing on linux: find child shell cwd without shell gymnastics
 
 config.def.h |  6 +++++
 x.c          | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)
diff --git a/config.def.h b/config.def.h
index 87ebdbb..265a4ff 100644
--- a/config.def.h
+++ b/config.def.h
_AT_@ -467,3 +467,9 @@ static char ascii_printable[] =
         " !\"#$%&'()*+,-./0123456789:;<=>?"
         "_AT_ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
         "`abcdefghijklmnopqrstuvwxyz{|}~";
+
+/*
+ * plumber_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 *plumber_cmd = "plumb";
diff --git a/x.c b/x.c
index 4345892..f319129 100644
--- a/x.c
+++ b/x.c
_AT_@ -5,6 +5,9 @@
 #include <locale.h>
 #include <signal.h>
 #include <sys/select.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <dirent.h>
 #include <time.h>
 #include <unistd.h>
 #include <libgen.h>
_AT_@ -644,6 +647,77 @@ xsetsel(char *str)
         setsel(str, CurrentTime);
 }
+char *
+subprocwd()
+{
+	struct dirent* dent;
+	DIR* srcdir = opendir("/proc/self/task");
+	char path[PATH_MAX];
+	FILE *fp;
+	int chpid;
+
+	if (srcdir == NULL)
+	{
+		return NULL;
+	}
+
+	while((dent = readdir(srcdir)) != NULL)
+	{
+		struct stat st;
+		char newdir[PATH_MAX];
+
+		if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
+			continue;
+		if (snprintf(newdir, PATH_MAX, "%s/%s", "/proc/self/task",
dent->d_name) < 0)
+			return NULL;
+		if (stat(newdir, &st) < 0)
+			continue;
+
+		if (S_ISDIR(st.st_mode)) break;
+	}
+	closedir(srcdir);
+	if (snprintf(path, PATH_MAX, "/proc/self/task/%s/children",
dent->d_name) < 0)
+		return NULL;
+	if (!(fp = fopen(path, "r")))
+		return NULL;
+	if (fscanf(fp, "%d", &chpid) != 1) {
+		fclose(fp);
+		return NULL;
+	}
+	fclose(fp);
+	if (snprintf(path, PATH_MAX, "/proc/%d/cwd", chpid) < 0)
+		return NULL;
+	return realpath(path, NULL);
+}
+
+void
+plumb(char *sel) {
+	if (sel == NULL)
+		return;
+	char *cwd;
+	char *cmd;
+	pid_t child;
+	cwd = subprocwd();
+	if (cwd == NULL)
+		return;
+
+	switch(child = fork()) {
+		case -1:
+			return;
+		case 0:
+			if (cwd == NULL)
+				exit(1);
+			cmd = malloc(PATH_MAX+100);
+			if (snprintf(cmd, PATH_MAX+100, "(cd %s ; %s %s)", cwd, plumber_cmd,
sel) < 0)
+				exit(1);
+			free(cwd);
+			execvp("sh", (char *const []){"sh", "-c", cmd, 0});
+			exit(0);
+		default:
+			waitpid(child, NULL, 0);
+	}
+}
+
 void
 brelease(XEvent *e)
 {
_AT_@ -656,6 +730,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 Thu Nov 01 2018 - 08:46:06 CET
This archive was generated by hypermail 2.3.0
: Thu Nov 01 2018 - 08:48:07 CET