dwm-6.0-spawn_cwd.diff (1836B)
1 https://github.com/sunaku/.dwm/compare/tip...spawn_cwd 2 --- 3 diff --git a/dwm.c b/dwm.c 4 index 1d78655..156ee60 100644 5 --- a/dwm.c 6 +++ b/dwm.c 7 @@ -20,6 +20,7 @@ 8 * 9 * To understand everything else, start reading main(). 10 */ 11 +#include <assert.h> 12 #include <errno.h> 13 #include <locale.h> 14 #include <stdarg.h> 15 @@ -28,6 +29,8 @@ 16 #include <stdlib.h> 17 #include <string.h> 18 #include <unistd.h> 19 +#include <libgen.h> 20 +#include <sys/stat.h> 21 #include <sys/types.h> 22 #include <sys/wait.h> 23 #include <X11/cursorfont.h> 24 @@ -1661,11 +1664,45 @@ sigchld(int unused) { 25 while(0 < waitpid(-1, NULL, WNOHANG)); 26 } 27 28 +#define SPAWN_CWD_DELIM " []{}()<>\"':" 29 + 30 void 31 spawn(const Arg *arg) { 32 if(fork() == 0) { 33 if(dpy) 34 close(ConnectionNumber(dpy)); 35 + if(selmon->sel) { 36 + const char* const home = getenv("HOME"); 37 + assert(home && strchr(home, '/')); 38 + const size_t homelen = strlen(home); 39 + char *cwd, *pathbuf = NULL; 40 + struct stat statbuf; 41 + 42 + cwd = strtok(selmon->sel->name, SPAWN_CWD_DELIM); 43 + /* NOTE: strtok() alters selmon->sel->name in-place, 44 + * but that does not matter because we are going to 45 + * exec() below anyway; nothing else will use it */ 46 + while(cwd) { 47 + if(*cwd == '~') { /* replace ~ with $HOME */ 48 + if(!(pathbuf = malloc(homelen + strlen(cwd)))) /* ~ counts for NULL term */ 49 + die("fatal: could not malloc() %u bytes\n", homelen + strlen(cwd)); 50 + strcpy(strcpy(pathbuf, home) + homelen, cwd + 1); 51 + cwd = pathbuf; 52 + } 53 + 54 + if(strchr(cwd, '/') && !stat(cwd, &statbuf)) { 55 + if(!S_ISDIR(statbuf.st_mode)) 56 + cwd = dirname(cwd); 57 + 58 + if(!chdir(cwd)) 59 + break; 60 + } 61 + 62 + cwd = strtok(NULL, SPAWN_CWD_DELIM); 63 + } 64 + 65 + free(pathbuf); 66 + } 67 setsid(); 68 execvp(((char **)arg->v)[0], (char **)arg->v); 69 fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);