I THINK ∴ I'M DANGEROUS

ebindkeys

Ebindkeys, not to be mistaken with xbindkeys nor ebindkeys for Zipit, is a linux program for binding key-presses or key-combos.

Improvements over ebindkeys for zipit include support for multiple event devices, the option of key-press order relevance, an (IMHO) infinitely better configuration file syntax.

Possible downsides include being potentially slower. The core logic is written in an interpreted language.

Features

  • Single configuration File
  • Multiple event devices supported
  • Suitable for embedded devices
  • Uses Tcl (based on jim) for configuration and program logic
  • Unlike xbindkeys, works regardless of what's in the foreground, be it X11, a virtual console, or a framebuffer.

Downloads

Source

Note: To compile ebindkeys you need to have jim installed.

Binaries

Here's a binary for i686 linux. It is statically compiled and compressed with upx.

Here is a statically compiled ARM binary suitable for use on embedded arm devices. There is also an example file for the zipit available (complete with key-mapping).

Configuration Samples

This is a sample configuration file for generic linux systems (i.e. standard ps/2 or usb keyboard).

This is a sample configuration file for zipits. It has all the zipit keypad keys mapped out.

Compilation

The requirements for compiling ebindkeys are pretty light. You need a c compiler, jim, and make (though you could manually run the commands that make runs).

Unpack the source. Compile with make, optionally make dist which strips and tries to compress with upx if upx is available.

tar -jxf ebindkeys-1.0b.tar.bz2
cd ebindkeys-1.0b
make
make dist #optional

Installation

Whether you compiled from source or downloaded a binary, installation is the same (and manual). Plunk your binary ('ebindkeys') into somewhere in your path like /bin. Put your ebindkeysrc file in /etc/ and installation is done. Proceed to configuration.

Configuration

Ebindkeys looks for the following files in order /etc/ebindkeysrc, ~/.ebindkeysrc, ./ebindkeysrc. The first file it finds it uses it. You will note that if a global config file is found (the /etc one) it will not load the user directory file (~/). This is intentional as ebindkeys binds keys based on physical keypresses and thus responds to actions global to the whole system. It is primarily intended to be used in embedded devices, but can also be used to make extra input devices (like usb keypads) or the power button on your keyboard work no matter what is currently running in the foreground, be it a virtual terminal or X11.

ebindkeysrc

The ebindkeysrc is a tcl script, based on jim. For full details on jim's implementation of tcl, check jim's homepage. Ebindkeys relevant information will be presented here.

You can set values and have them expanded anywhere else in the rc file. Let's look at a small example. String literals don't need to be quoted if they don't contain a space. Brackets quote without substitution, double quotes quote with substitution, single quotes are not used for quoting.

The event command is what lets you define events to respond to input events. The first argument is a event device, you can use either the direct path or the udev created alias under /dev/input/by-path or /dev/input/by-id. The second argument specifies whether or not key-press order matters. The options are ordered and unordered. The third argument is a single button or a list of buttons. Lists should be encapsulated with double quotes. The last argument is a block of commands to run if the previously set criteria match.

  set L_CTRL 29
  set keyboard /dev/input/event0
 
  event $keyboard ordered $L_CTRL {
    exec echo Left Control Key Pressed | wall
  }

The above example, if it isn't obvious enough, will cause “echo Left Control Key Pressed | wall” to be ran every time the left control key is pressed.

Here's a more useful example which puts the computer to sleep when the sleep key is pressed and hibernates when left control + sleep is pressed.

  set L_CTRL 29
  set SLEEP 142
  set keyboard /dev/input/event0
 
  event $keyboard ordered $SLEEP {
    exec pm-suspend
  }
 
  event $keyboard ordered "$L_CTRL $SLEEP" {
    exec pm-hibernate
  }

You maybe wondering where the values for the keys come from. These are determined by the kernel. A sample ebindkeysrc file with a standard mapping is provided in the downloads section. I also have provided a sample ebindkeysrc file for the zipit, though you may have to adjust values / event devices depending on what linux distro you use on your zipit.

Advanced Configuration

Because jim is a complete and powerful language you can coax some rather complex behavior out of ebindkeys like command chaining.

For example, you can simulate switching between two different bindings for keys.

  set L_CTRL 29
  set SLEEP 142
  set keyboard /dev/input/event0
 
  set alt_set 0
  event $keyboard ordered $SLEEP {
    #flip alt_set between 0 and 1 when the SLEEP key is pressed
    global alt_set
    set alt_set [expr ! $alt_set]
  }
 
  event $keyboard ordered "$L_CTRL" {
    global alt_set
    if {$alt_set} {
      exec some-command
    } else {
      exec some-different-command
    }
  }

Under The Hood

This version of Ebindkeys (meant to update and replace ebindkeys for Zipit) uses jim tcl for configuration and pretty much all of the program logic. The C program basically connects jim and the tcl-code.

The core functionality remains the same between the older version and this version–ebindkeys reads input events from the kernel's input event interface and reacts according based on the configuration file.

Security Concerns

If ebindkeys is launched as root, everything it runs, by default is as root. Since jim is rather complete and powerful programming language, if someone slipped code in to the ebindkeysrc file it could potentially be used to elevate privileges or root a system. The solution to this is easy and up to the user: either run as a non-root user (but don't forget to give appropriate access to /dev/input/event* device) or run as root and keep ebindkeysrc chmod 600. If you run as root you can drop privs depending on what command you run via passing your command through su.

Known Issues

Endianness Bug

Possibly the largest issue is that both the program and the Makefile assume little endianness. As is, without modification, ebindkeys will not work on big endian systems. Since I don't have any big endian systems I am not too concerned about this, but if someone runs into this problem, let me know and I'll figure away around it. (Probably by rewriting the Makefile and changing the program itself to use binary scan rather than unpack).

Error Handling

My error handling is not the best. This is the main issue to be resolved between 1.0b and 1.0.

If you're getting weird errors it's probably error in ebindkeysrc or an issue with reading the input devices. If you are having trouble getting commands to run double check you've got the right device node specified.