https://github.com/sunaku/.dwm/compare/tip...spawn_cwd --- diff --git a/dwm.c b/dwm.c index 1d78655..156ee60 100644 --- a/dwm.c +++ b/dwm.c @@ -20,6 +20,7 @@ * * To understand everything else, start reading main(). */ +#include #include #include #include @@ -28,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -1661,11 +1664,45 @@ sigchld(int unused) { while(0 < waitpid(-1, NULL, WNOHANG)); } +#define SPAWN_CWD_DELIM " []{}()<>\"':" + void spawn(const Arg *arg) { if(fork() == 0) { if(dpy) close(ConnectionNumber(dpy)); + if(selmon->sel) { + const char* const home = getenv("HOME"); + assert(home && strchr(home, '/')); + const size_t homelen = strlen(home); + char *cwd, *pathbuf = NULL; + struct stat statbuf; + + cwd = strtok(selmon->sel->name, SPAWN_CWD_DELIM); + /* NOTE: strtok() alters selmon->sel->name in-place, + * but that does not matter because we are going to + * exec() below anyway; nothing else will use it */ + while(cwd) { + if(*cwd == '~') { /* replace ~ with $HOME */ + if(!(pathbuf = malloc(homelen + strlen(cwd)))) /* ~ counts for NULL term */ + die("fatal: could not malloc() %u bytes\n", homelen + strlen(cwd)); + strcpy(strcpy(pathbuf, home) + homelen, cwd + 1); + cwd = pathbuf; + } + + if(strchr(cwd, '/') && !stat(cwd, &statbuf)) { + if(!S_ISDIR(statbuf.st_mode)) + cwd = dirname(cwd); + + if(!chdir(cwd)) + break; + } + + cwd = strtok(NULL, SPAWN_CWD_DELIM); + } + + free(pathbuf); + } setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);