commit bd60559cbf8ecb68611d82055fde43552bc9df0f
parent 1a839ad07586a44a5513237d38f36ec0e6bf7a83
Author: m3cgx <m3cgx@airmail.cc>
Date: Sun, 25 Jan 2026 22:23:42 -0500
[tabbed][patch][cwd] Update cwd to apply cleanly on tabbed 0.9
Diffstat:
2 files changed, 117 insertions(+), 0 deletions(-)
diff --git a/tools.suckless.org/tabbed/patches/cwd/index.md b/tools.suckless.org/tabbed/patches/cwd/index.md
@@ -12,6 +12,7 @@ The target directory is actually the cwd of the first child process (the shell).
Download
--------
* [tabbed-cwd-20230128-41e2b8f.diff](tabbed-cwd-20230128-41e2b8f.diff)
+* [tabbed-cwd-0.9.diff](tabbed-cwd-0.9.diff)
Authors
-------
diff --git a/tools.suckless.org/tabbed/patches/cwd/tabbed-cwd-0.9.diff b/tools.suckless.org/tabbed/patches/cwd/tabbed-cwd-0.9.diff
@@ -0,0 +1,116 @@
+diff --git a/tabbed.c b/tabbed.c
+index aa45716..e4c5f90 100644
+--- a/tabbed.c
++++ b/tabbed.c
+@@ -10,6 +10,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <linux/limits.h>
+ #include <X11/Xatom.h>
+ #include <X11/keysym.h>
+ #include <X11/Xlib.h>
+@@ -85,6 +86,7 @@ typedef struct {
+ int tabx;
+ Bool urgent;
+ Bool closed;
++ pid_t pid;
+ } Client;
+
+ /* function declarations */
+@@ -168,6 +170,7 @@ static int cmd_append_pos;
+ static char winid[64];
+ static char **cmd;
+ static char *wmname = "tabbed";
++static pid_t nextpid;
+ static const char *geometry;
+
+ char *argv0;
+@@ -175,6 +178,49 @@ char *argv0;
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+
++// Given a pid, return its cwd to buf
++int getpidcwd(pid_t pid, char* buf, size_t bufsiz) {
++ static const int proc_max = 20; // '/proc/4194304/cwd'
++ int sn_ret;
++ ssize_t rl_ret;
++ char path[proc_max];
++
++ sn_ret = snprintf(path, proc_max, "/proc/%d/cwd", pid);
++ if(sn_ret < 0 || sn_ret >= proc_max)
++ return -1;
++
++ rl_ret = readlink(path, buf, bufsiz);
++ if(rl_ret < 0 || rl_ret == bufsiz)
++ return -1;
++
++ buf[rl_ret] = 0;
++ return 0;
++}
++
++// Given a pid, return a reasonable guess at its child pid
++pid_t getchildpid(pid_t pid) {
++ // '/proc/4194304/task/4194304/children'
++ static const int proc_max = 40;
++ int sn_ret;
++ char path[proc_max];
++ FILE* f;
++
++ // guessing tid == pid
++ sn_ret = snprintf(path, proc_max, "/proc/%d/task/%d/children", pid, pid);
++ if (sn_ret < 0 || sn_ret >= proc_max)
++ return -1;
++
++ f = fopen(path, "r");
++ if(f == NULL)
++ return -1;
++
++ // guess first child
++ if(fscanf(f, "%d ", &pid) != 1)
++ return -1;
++
++ return pid;
++}
++
+ void
+ buttonpress(const XEvent *e)
+ {
+@@ -737,6 +783,7 @@ manage(Window w)
+
+ c = ecalloc(1, sizeof *c);
+ c->win = w;
++ c->pid = nextpid;
+
+ nclients++;
+ clients = erealloc(clients, sizeof(Client *) * nclients);
+@@ -1102,11 +1149,17 @@ spawn(const Arg *arg)
+ {
+ struct sigaction sa;
+
+- if (fork() == 0) {
++ char sel_cwd[PATH_MAX];
++
++ pid_t pid = fork();
++ if (pid == 0) {
+ if(dpy)
+ close(ConnectionNumber(dpy));
+
+ setsid();
++ if (sel >= 0 && clients[sel] && clients[sel]->pid > 0 && getpidcwd(getchildpid(clients[sel]->pid), sel_cwd, PATH_MAX) == 0) {
++ chdir(sel_cwd);
++ }
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+@@ -1124,6 +1177,8 @@ spawn(const Arg *arg)
+ }
+ perror(" failed");
+ exit(0);
++ } else {
++ nextpid = pid;
+ }
+ }
+
+--
+2.51.0