sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

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]);