Sourcery of dmenu

Jason Kantz
Sep 2018

"dmenu" is a program I use for starting other programs. It's written for the X Window System and my installation binds it to a hot key. When I press the hot key, an input box displays at the top of the screen along with a horizontal list of completions. So for example, if I type "ch" it shows "chromedriver", "chromium", "chroot" and some other options, which I can arrow between and then press enter to run the selected command.

On an overcast Saturday morning, I wandered over to the frugal and started taking a peek at the sourcery of Garbe and van Dijk (2006).

git clone git://
git checkout bbc464dc80225b8cf9390f14fac6c682f63940d2
git checkout -b sourcery

My question: how exactly do they run the selected program? My dip into their code started with a hunt for a system call like "exec" or "system" ... because that's how you run a program from C right?

I jumped right into dmenu.c, and saw "main", which calls "run", which calls "keypress", which at the bottom of it all calls ...

"puts"!? Ah, the forgotten man page, dmenu.1.

 When the user selects an item and presses Return, their
 choice is printed to stdout and dmenu terminates.

This means it can be used to do cool things like,

emacsclient $(find ./ | dmenu)

So after realizing that dmenu itself is a filter, I opened dmenu_run, which is just

 dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &

dmenu_path is a shell script that gets all of the programs in the path and prints them to standard out. It uses "stest", which comes with dmenu. stest has it's own man page that tells us,

 stest takes a list of files and filters by the files' properties,
 analogous to test (1).

and dmenu_path has this interesting line,

 stest -flx $PATH | sort -u | tee "$cache"

and I thought hmm, stest, that's cool, let me try,

 $ stest -flx $PATH

Hmm, it returned nothing, tz. How about something specific from $PATH?

$ stest -flx /usr/bin
... and more programs

What's going on?

I went back to dmenu_path and noticed this interesting line,


What is that? I turned to "man bash" where Ramey (2016) tells us

IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is ``<space><tab><newline>''.

Oh, how about that.

$ IFS=:
$ echo $PATH
/usr/bin /usr/sbin /sbin /bin
$ stest -flx $PATH
... and even more programs, tz.

So back to my question: how exactly do Garbe and van Dijk run the selected program?

  1. "stest" filters all files in my path down to executable ones.
  2. "dmenu_path" caches that list, passes it on to dmenu.
  3. dmenu filters it to a single value based on user input.
  4. The single command is piped to a shell for execution.

With that, I noticed something about my process tree,

\_ chromium

 \_ emacs

I don't think I need all of those bash processes, tz. So I decided to tidy things up by changing my dmenu_run to,

 cmd=$(dmenu_path | dmenu "$@")
 /bin/sh -c "exec ${cmd}" &

Is the question answered? Well, I did start out looking for some form of "exec", so there it was in dmenu_run--after I added it.

Actually, the final bit unfolded for me with the key binding that brings this into a user's hands. This depends on the window manager, and for dwm, there's a config.def.h file that happens to have:

static const char *dmenucmd[] = { "dmenu_run", "-m", \
dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", \
col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };

which is configured to be an "arg" to "spawn" when the hot key is pressed. I pulled up "spawn" over in "dwm.c", and what does spawn do? It forks and then,

execvp(((char **)arg->v)[0], (char **)arg->v);

The End


Fox, B. (1989). bash [computer software]. Boston, MA: Free Software Foundation. Available from

Garbe, A.R., & van Dijk, S. (2006). dmenu [computer software]. München, Germany: e.V. Available from

Garbe, A.R., Salmi, J., & van Dijk, S., (2006). dwm [computer software]. München, Germany: e.V. Available from

Gettys, J., Karlton, P., & McGregor, S. (1990). The X window system version 11. Software Practice and Experience, 20(S2), 35-67. Retrieved from

Ramey, C. (2016). bash - GNU Bourne-AGain SHell. General Commands Manual for bash.