tabbed-cwd-20230128-41e2b8f.diff (3021B)
1 From 50753359eb7a760bcadd54611431c0888867c21c Mon Sep 17 00:00:00 2001 2 From: Casey Fitzpatrick <kcghost@gmail.com> 3 Date: Sat, 28 Jan 2023 09:46:53 -0500 4 Subject: [PATCH] Spawn new tabs in working directory of selected clients child 5 6 When used with st or xterm the working directory of the new tab 7 should be the same as the currently selected tab. 8 --- 9 tabbed.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 10 1 file changed, 56 insertions(+), 1 deletion(-) 11 12 diff --git a/tabbed.c b/tabbed.c 13 index eafe28a..eb046d0 100644 14 --- a/tabbed.c 15 +++ b/tabbed.c 16 @@ -10,6 +10,7 @@ 17 #include <stdlib.h> 18 #include <string.h> 19 #include <unistd.h> 20 +#include <linux/limits.h> 21 #include <X11/Xatom.h> 22 #include <X11/Xlib.h> 23 #include <X11/Xproto.h> 24 @@ -84,6 +85,7 @@ typedef struct { 25 int tabx; 26 Bool urgent; 27 Bool closed; 28 + pid_t pid; 29 } Client; 30 31 /* function declarations */ 32 @@ -168,6 +170,7 @@ static int cmd_append_pos; 33 static char winid[64]; 34 static char **cmd; 35 static char *wmname = "tabbed"; 36 +static pid_t nextpid; 37 static const char *geometry; 38 39 char *argv0; 40 @@ -175,6 +178,49 @@ char *argv0; 41 /* configuration, allows nested code to access above variables */ 42 #include "config.h" 43 44 +// Given a pid, return its cwd to buf 45 +int getpidcwd(pid_t pid, char* buf, size_t bufsiz) { 46 + static const int proc_max = 20; // '/proc/4194304/cwd' 47 + int sn_ret; 48 + ssize_t rl_ret; 49 + char path[proc_max]; 50 + 51 + sn_ret = snprintf(path, proc_max, "/proc/%d/cwd", pid); 52 + if(sn_ret < 0 || sn_ret >= proc_max) 53 + return -1; 54 + 55 + rl_ret = readlink(path, buf, bufsiz); 56 + if(rl_ret < 0 || rl_ret == bufsiz) 57 + return -1; 58 + 59 + buf[rl_ret] = 0; 60 + return 0; 61 +} 62 + 63 +// Given a pid, return a reasonable guess at its child pid 64 +pid_t getchildpid(pid_t pid) { 65 + // '/proc/4194304/task/4194304/children' 66 + static const int proc_max = 40; 67 + int sn_ret; 68 + char path[proc_max]; 69 + FILE* f; 70 + 71 + // guessing tid == pid 72 + sn_ret = snprintf(path, proc_max, "/proc/%d/task/%d/children", pid, pid); 73 + if (sn_ret < 0 || sn_ret >= proc_max) 74 + return -1; 75 + 76 + f = fopen(path, "r"); 77 + if(f == NULL) 78 + return -1; 79 + 80 + // guess first child 81 + if(fscanf(f, "%d ", &pid) != 1) 82 + return -1; 83 + 84 + return pid; 85 +} 86 + 87 void 88 buttonpress(const XEvent *e) 89 { 90 @@ -725,6 +771,7 @@ manage(Window w) 91 92 c = ecalloc(1, sizeof *c); 93 c->win = w; 94 + c->pid = nextpid; 95 96 nclients++; 97 clients = erealloc(clients, sizeof(Client *) * nclients); 98 @@ -1090,11 +1137,17 @@ sigchld(int unused) 99 void 100 spawn(const Arg *arg) 101 { 102 - if (fork() == 0) { 103 + char sel_cwd[PATH_MAX]; 104 + 105 + pid_t pid = fork(); 106 + if (pid == 0) { 107 if(dpy) 108 close(ConnectionNumber(dpy)); 109 110 setsid(); 111 + if (sel >= 0 && clients[sel] && clients[sel]->pid > 0 && getpidcwd(getchildpid(clients[sel]->pid), sel_cwd, PATH_MAX) == 0) { 112 + chdir(sel_cwd); 113 + } 114 if (arg && arg->v) { 115 execvp(((char **)arg->v)[0], (char **)arg->v); 116 fprintf(stderr, "%s: execvp %s", argv0, 117 @@ -1106,6 +1159,8 @@ spawn(const Arg *arg) 118 } 119 perror(" failed"); 120 exit(0); 121 + } else { 122 + nextpid = pid; 123 } 124 } 125 126 -- 127 2.25.1 128