xresources
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index 02db465..4edd7ce 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/wait.h>
 #include <X11/cursorfont.h>
 #include <X11/keysym.h>
@@ -209,6 +210,7 @@ static void resizeclient(Client *c, int x, int y, int w, int h);
 static void resizemouse(const Arg *arg);
 static void restack(Monitor *m);
 static void run(void);
+static void runautostart(void);
 static void scan(void);
 static int sendevent(Client *c, Atom proto);
 static void sendmon(Client *c, Monitor *m);
@@ -254,7 +256,11 @@ static void load_xresources(void);
 static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
 
 /* variables */
+static const char autostartblocksh[] = "autostart_blocking.sh";
+static const char autostartsh[] = "autostart.sh";
 static const char broken[] = "broken";
+static const char dwmdir[] = "dwm";
+static const char localshare[] = ".local/share";
 static char stext[256];
 static int screen;
 static int sw, sh;           /* X display screen geometry width, height */
@@ -1400,6 +1406,83 @@ run(void)
                        handler[ev.type](&ev); /* call handler */
 }
 
+void
+runautostart(void)
+{
+       char *pathpfx;
+       char *path;
+       char *xdgdatahome;
+       char *home;
+       struct stat sb;
+
+       if ((home = getenv("HOME")) == NULL)
+               /* this is almost impossible */
+               return;
+
+       /* if $XDG_DATA_HOME is set and not empty, use $XDG_DATA_HOME/dwm,
+        * otherwise use ~/.local/share/dwm as autostart script directory
+        */
+       xdgdatahome = getenv("XDG_DATA_HOME");
+       if (xdgdatahome != NULL && *xdgdatahome != '\0') {
+               /* space for path segments, separators and nul */
+               pathpfx = ecalloc(1, strlen(xdgdatahome) + strlen(dwmdir) + 2);
+
+               if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) {
+                       free(pathpfx);
+                       return;
+               }
+       } else {
+               /* space for path segments, separators and nul */
+               pathpfx = ecalloc(1, strlen(home) + strlen(localshare)
+                                    + strlen(dwmdir) + 3);
+
+               if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) {
+                       free(pathpfx);
+                       return;
+               }
+       }
+
+       /* check if the autostart script directory exists */
+       if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) {
+               /* the XDG conformant path does not exist or is no directory
+                * so we try ~/.dwm instead
+                */
+               char *pathpfx_new = realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3);
+               if(pathpfx_new == NULL) {
+                       free(pathpfx);
+                       return;
+               }
+   pathpfx = pathpfx_new;
+
+               if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) {
+                       free(pathpfx);
+                       return;
+               }
+       }
+
+       /* try the blocking script first */
+       path = ecalloc(1, strlen(pathpfx) + strlen(autostartblocksh) + 2);
+       if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) {
+               free(path);
+               free(pathpfx);
+       }
+
+       if (access(path, X_OK) == 0)
+               system(path);
+
+       /* now the non-blocking script */
+       if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) {
+               free(path);
+               free(pathpfx);
+       }
+
+       if (access(path, X_OK) == 0)
+               system(strcat(path, " &"));
+
+       free(pathpfx);
+       free(path);
+}
+
 void
 scan(void)
 {
@@ -2230,6 +2313,7 @@ main(int argc, char *argv[])
                die("pledge");
 #endif /* __OpenBSD__ */
        scan();
+       runautostart();
        run();
        cleanup();
        XCloseDisplay(dpy);