Your heuristics are pretty bad. Here's what they find on a Debian wheezy machine of mine (I've manually marked correct hits with a +
).
/usr/bin/gcm-calibrate
/usr/bin/gnome-terminal +
/usr/bin/mosh-client
/usr/bin/mosh-server
/usr/bin/mrxvt +
/usr/bin/mrxvt-full +
/usr/bin/roxterm +
/usr/bin/rxvt-unicode +
/usr/bin/urxvt +
/usr/bin/urxvtd
/usr/bin/vinagre
/usr/bin/x-terminal-emulator +
/usr/bin/xfce4-terminal +
/usr/bin/xterm +
If you pick the first alphabetic match, it's a color calibrator.
Here's the list of alternatives for x-terminal-emulator
, which is the correct answer (as far as distribution-managed programs is concerned) on this Debian machine:
/usr/bin/Eterm
/usr/bin/gnome-terminal.wrapper
/usr/bin/koi8rxterm
/usr/bin/konsole
/usr/bin/lxterm
/usr/bin/mlterm
/usr/bin/mrxvt-full
/usr/bin/roxterm
/usr/bin/rxvt-xpm
/usr/bin/rxvt-xterm
/usr/bin/urxvt
/usr/bin/uxterm
/usr/bin/xfce4-terminal.wrapper
/usr/bin/xterm
/usr/bin/xvt
You're finding 7 out of 15 (accounting for vagaries of names), which isn't a very good hit rate.
You could try to refine your heuristics, but it's a never-ending game. The minimum would be to retain only executables that both link against some X11 libraries and call some master terminal function or utility like getpt
or grantpt
, but that's bound to find a lot of spurious positives too, and to miss executables where the call is in a library (like konsole
). And this will miss native code executables that are accessed through a shell wrapper (there are several in my list).
Detecting whether a program is an X terminal emulator from the executable content is hopeless.
Detecting programs by name is a far better heuristic.
Note also that different programs have a different command line syntax. Most of them accept -T TITLE
and -e COMMAND
, but they have different parsing rules for -e
(going through a shell or not, taking multiple arguments or not) so you should pass a single parameter after -e
, not containing any shell special characters.
On Debian and derivatives, x-terminal-emulator
is guaranteed to be an X terminal emulator that supports -T
and -e
, such that -e
uses all subsequent command line parameters as a command and its argument and doesn't do shell expansion on them. Because some emulators behave differently, x-terminal-emulator
is sometimes a wrapper that takes a more xterm-like syntax (gnome-terminal.wrapper
and xfce4-terminal.wrapper
are two examples of this).
I don't know of anything like this on other unix variants. For anything like portability, a hard-coded list of program names is your best bet.
Furthermore, detecting installed terminal emulators won't give you any idea about the user's preferences. For example, if I use Gnome, I probably don't want your application to launch Konsole — unless I happen to prefer Konsole, but how would you know that?
The de facto standard for user preferences is via FreeDesktop.org specifications. Freedesktop publishes an xdg-utils
package which contains programs such as xdg-open
to open a document in the proper application, xdg-email
to launch the user's preferred email composing application, and more to the point xdg-terminal
to open the user's preferred terminal emulator.
This would make xdg-terminal
the right thing to use, and you should use it if it's there. Unfortunately, xdg-terminal
isn't available everywhere; for example, Debian doesn't ship it (it's a long-idle bug). Furthermore xdg-terminal
allows a single command argument, and is not consistent about what kind of expansion this argument undergoes.
Whatever you do, make sure to provide an easy way for the caller to specify a preference. Even xdg-terminal
doesn't always get it right.
Thus your best strategy is:
- if the user has specified a preference, use it
- else try
xdg-terminal
- else try
x-terminal-emulator
- else try a hard-coded list