Sourcery of dmenu

tzbitsby
Jason Kantz
Sep 2018
 vol 1.

"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 suckless.org and started taking a peek at the sourcery of Garbe and van Dijk (2006).

git clone git://git.suckless.org/dmenu
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

 #!/bin/sh
 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
curl
pwck
... and more programs

What's going on?

I went back to dmenu_path and noticed this interesting line,

IFS=:

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
curl
pwck
... 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,

/bin/bash
\_ chromium

/bin/bash
 \_ 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,

 #!/bin/sh
 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

References

Fox, B. (1989). bash [computer software]. Boston, MA: Free Software Foundation. Available from https://git.savannah.gnu.org/cgit/bash.git

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

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

Gettys, J., Karlton, P., & McGregor, S. (1990). The X window system version 11. Software Practice and Experience, 20(S2), 35-67. Retrieved from http://www.hpl.hp.com/techreports/Compaq-DEC/CRL-90-8.pdf

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