Troubleshooters.Com Presents

The Universal Menu System (umenu) Open Source Project

Project Specifications

 >  <^

Copyright (C) 1999-2004 by Steve Litt

Top Level Functionality


Current Dir  --.             Location of config file
and Env var     >---------------------------------------->---.                                               &bsp;          |
UMENU_CONFIG --'                                             |
     V       Menu Def file location and other info
Config File --------------------------------------------->---.
     V                 Submenus, commands, args, prompts, directories
Menu Definition Files ----------------------------------->---.
         &nb                                                      |
     V        Script to run intended command in intended environment
Menu Program -------------------------------------------->---.
OS Shell ------------>Command is executed


Environment variable UMENU_CONFIG and the directory from which UMENU is run represent the single entry point to the UMENU system. UMENU_CONFIG contains the name and location of the UMENU Configuration File. If this environment variable does not exist, all programs look to file umenu.cnf, in the current directory, for configuration. This means that on simple systems, everything can be self-contained in a tree relative to the current directory, which is the program directory (whatever/umenu/program).

The UMENU configuration file defines menu system wide configurations, including the following:

Note that if any of the directories contain the string "$HOME", the user's home directory is substituted for that string. Thus it can be assured that the user has create/write rights to the temporary scripts he writes, and the user can be assigned a menu system unique to himself if desired. The default umenu.cnf, as shipped with the distribution, points to ../menudir for the Menu Definition File directory, and $HOME as the temporary script directory. This will work perfectly on any Linux system.

The directory containing all menu definition files (at least for the user, if menudir= contains a $HOME string), contains a menu definition file for each submenu. The filename will contain only lower case alpha letters, with an exteonly lower case alpha letters, with an extension of .mnu. The first letter of the filename corresponds to the main menu to use. Therefore, the directory may contain up to 25 main menus (q is a reserved letter). The choice of main menu is made on the command line when invoking umenu. The remaining letters of the filename, up to but excluding the dot and extension, correspond to the keystroke sequence the user pressed to navigate to the submenu.

Thus, if the user accessed the "c" menu system, then pressed (in sequence) keys d, o and g to navigate to a submenu, the Menu Definition File defining that submenu would be cdog.mnu.

Object Architecture

As of version 0.7.0, UMENU uses a much simpler object architecture to make the program more robust and maintainable:
  • Getopt::Long
  • Node
Older versions used a much more complex and hard to maintain object architecture:
  • OS object
  • CONFIG object
  • CHOICE object
  • UMENUGLOBAL object

Getopt::Long object

This assists with the acquisition of command line arguments. It is a Perl OOP front end to the getopt_long() C command. See man getopt for details.

Node object

I created a tool called This perl module handles data hierarchies with the utmost in ease. It even has a parser to convert an outline to a Node hierarchy, although this feature isn't used in UMENU.

I've rewritten several programs, with the new version using In every case the new version was easier to maintain, more stable, and in many cases faster. UMENU version 0.7.0 has been written from the ground up around The data formerly handled by the OS, CONFIG, CHOICE and UMENUGLOBAL objects is now placed in Node hierarchies. is available at There's also a great reference at

Installation is as simple as untarring the tarball. A directory called Node is created below the current directory. That new Node directory is called "The Node directory", and needs to be assigned to the nodedir variable in the UMENU configuration file umenu.cnf. One excellent place for the Node directory is /usr/local/Node.

Configuration File Specifications


The Universal Menu System Program is intended to provide all users with the easiest possible use of a computer, any computer. We want, to the extent possible, to provide this experience without regard to their computer's features, or what they have loaded on their computer. We specifically will not store data or configuration in any OS-specific database (like the Windows registry). Instead, we store the information in a configuration file at ./umenu.cnf.

However, the location (in any operating system) can be changed via the UMENU_CONFIG environment variable. This provides a great way to standardize menu configuration across a network, without client configuration.

Information Stored in the UMENU System Configuration File

The Node directory. Location of the file and the EMDL to UMENU parser/converter.
menudir= The directory containing the menu files. Typically $HOME/.umenu/menudir.
scriptdir= A directory into which the user can write script files to execute. Note that this can be achieved with environment variables to point to the user's home directory. Scripts are erased right after they're executed, so this will not result in file buildup.

Scripts have filenames designed to make them unique. Otherwise multitasking and multiuser use of the menu program would fail, as commands and script files become switched. To accommodate this, script filenames start with the menu string of the invoked command, followed by the Unix date/time as the number of seconds since the epoch. To accommodate large number of users and processes, it's anticipated that later script filenames will also include the username, and possibly a terminal or process id.

Valid values are unix and windows. Note that to get UMENU to work you must use unix, because at present UMENU does not work with Windows. Version 0.7.0 replaced the earlier error prone "OS autodetection" code with code that looks to the configuration file to derive the operating system. The new way is much more robust.
The distribution umenu.cnf file sets this to 1, and hopefully you won't need to change it. Valid values are 1 and 0, each of which cause the keystroke acquisition routine to be configured slightly differently. If UMENU appears to fail just before or during keystroke acquisition, you can try changing this value. Modern Linuces and FreeBSD 5.1 work well with a value of 1, but for other Unices or several year old Linuces, you might need to change this setting.

Menu Definition File Specifications


The Universal Menu System Menu Program is intended to provide all users with the easiest possible use of a computer, any computer. We want, to the extent possible, to provide this experience without regard to their computer's features, or what they have loaded on their computer. For that reason, we chose not to store menu data in any kind of database. Putting an entire menu system in a single text file is certainly possible, but it would be resource intensive, prone to corruption, difficult to maintain, and it wouldn't model the hierarchical structure of a menu system. Fortunately, we can completely mimic the menu hierarchy using a file naming convention. The first letter of each menu file represents the menu system it belongs to, so there can be 25 different menu systems in a single directory (q is a reserved letter). Throughout this document we will refer to the a menu system. Thus, to invoke a menu system, the user simply need get into the menu executable directory and type
perl a
Note that it's quite easy to create a script, in a directory on the executable path, to change directories and run this command for you. Note also that as other UMENU system implementations are developed, the command may change but the menu system letter will always appear on the command line.

The above mentioned command will bring up the main menu, whose information is contained in a file called a.mnu. Now let's say that the main menu, whose data is contained in a.mnu, contains a choice called "Editors", meant to bring up a submenu of all the possible editors. Let's further say that menu choice is invoked when the user presses the E key. In such a case, the data for the Editors submenu would be contained in ae.mnu. If the Editors menu had a choice L for Linux editors submenu, the had a choice L for Linux editors submenu, the Linux editors submenu would be contained in ael.mnu. Naturally, in DOS systems, this scheme would confine us to seven levels of submenu -- not a particularly confining restriction. In modern operating systems, it wouldn't constrain us at all.

It is an absolute specification of this system that all letters in the filename must be lower case. This makes life much easier in case sensitive operating systems, and allows easy transfer of a menu between operating systems.

A fundimental design criteria is that this menu system can easily be maintained by any text editor, such as DOS edit, Windows Notepad, or Linux vi. While we would expect programmers to add automated configuration tools, we want to be sure that the user's menu system is never "held captive" by such a tool. To accomplish that, we have created a simple convention within each file that does not require fixed length lines, allows for future expansion, and is easy to understand and edit.

Allowable Menu Choice Letters

Due to file naming constraints in the various operating systems, we confine menu choices to the following:

File is a Text File

Each Menu Definition File is comprised of lines of reasonable length, reasonable being less than 255 character. However, to accommodate very long paths and commands with prompts, a well designed UMENU implementation will work with lines up to 1024 characters.

Each line describes one and only one property of a menu choice. Each line is ended by the newline native to the OS. Each line is composed only of printable characters. The first character of each line is a flag indicating the purpose of the line.

Version 0.7.0 allows multiple C lines, which concatinate in order separated by a space. If you want each of these to be a separate command, end each with a semicolon.

To reduce the likelihood of corruption, the file is absolutely NOT fixed record length.

The File is Delineated by Menu Choice Letters

Each menu choice is represented by menu choice letter line, which begins with L. Each menu choice is represented by a single choice letter (the letter the user presses to invoke the choice). Each menu choice letter line (record) in the file starts a new menu choice, whose data follows until the next letter line or EOF is encountered. The data above the first letter line describes the submenu as a whole -- its title, for instance. Letter lines have an upper case L in column 1. A lowercase letter in column 1 is considered an error and is ignored. Lines starting with a hash (#) are ignored.

Structure of Lines in the Menu File

Note: It is the menu program's responsibility to strip trailing blanks from each line.
Here's a small example file containing a title and two commands, shutdown and search files in a tree for specific text:

T_Networking Menu
T_Shutdown now
C_/sbin/shutdown -h now
C_find -type f | xargs grep -l | less
T_Search /etc/*.conf tree for old ip

Types of Lines In Menu Definition Files

As mentioned earlier, other types of lines are subordinate to the Letter line preceeding them, unubordinate to the Letter line preceeding them, unless they come before any Letter line, in which case they're subordinate to the submenu as a whole. Each line conforms to the structure described earlier.
Description Handling multiples
L Menu Letter The letter the user must press to invoke this menu choice. All lines under a letter line describe that menu choice, until another letter line or EOF is encountered.  Since Letter lines delineate menu choices, by definition it's impossible to have two per menu choice. If two choices on a menu have the same letter, it's up to the menu program to decide how to handle it, either by always running the first, always running the last, or giving the user a choice.
T Text The text to be placed on the menu. Menu programs will truncate as necessary for screen considerations. If this line appears above all  Letter lines, it's the submenu's title. Having two text lines in a menu choice is an error, but it should not terminate the menu system. It shall be handled by ignoring all but the first. Optionally, the program may issue a message, then return to normal operation.
C Command The exact command to be issued, or the exact command combined with prompted user-input substitutions, or a special character telling the menu program where to go next.

The next section of this document contains a detailed discussion of Menu Definition File Command Line Syntax.

As of version 0.7.0, multiple command lines for a given choice are concatenated separated by spaces. If these commands are intended to be separate Bash commands, each should end in a semicolon.

In versions before 0.7.0, having two command lines in a menu choice was an error.

D Directory The directory to switch to before issuing the command. This directory should appear exactly as it would in a cd command.  Having two directory lines in a menu choice is an error, but it should not terminate the menu system. It shall be handled by ignoring all but the first. Optionally, the program may issue a message, then return to normal operation.
V driVe For DOS compatibility, the menu program will switch to this drive before executing the cd command to the directory. If accidentally used in a UNIX type system, it will be ignored. Having two drive lines in a menu choice is an error, but it should not terminate the menu system. It shall be handled by ignoring all but the first. Optionally, the program may issue a message, then return to normal operation.
P Prepath One or more directories that should be added to the existing path, at the beginning of the existing path, in order to successfully run the command.

The menu program will prepend this exact data to the existing path, so this data must end with the path  separator for the OS in question. It is the responsibility of the menu program to remove these directories from the path at the conclusion of the command.
Having two prepath lines in a menu choice is an error, but it should not terminate the menu system. It shall be handled by ignoring all but the first. Optionally, the program may issue a message, then return to normal operation.
# Comment Ignore this line completely. Note that this ONLY works in column 1, nowhere else. Multiples are fine. These are just comments.
E Environment Var A command to set an enviro E Environment Var A command to set an environment variable. The menu program will execute the command, and must reset or remove this set at the conclusion of the command (so it must know prior state). Unlike most other lines, it is perfectly OK to have multiple E lines.

Because of the difficulty of implementing this across different operating systems, handling E lines is optional for a menu program, but it works for UMENU.

It is perfectly permissible to have multiple environment lines, in which case each one will be set.
S Stop Stop after running the program so the user can see the screen. Without this, the menu program would appear over the concluded program's output, eraseing it.

The data portion of the line will be a prompt. If there's no data, the menu program will print "Press Enter to continue==>"

Having two stop lines in a menu choice is an error, but it should not terminate the menu system. It shall be handled by ignoring all but the first. Optionally, the program may issue a message, then return to normal operation.
= Special
Originally, lines starting with an equal sign hold temporary info, such as the original and new menu files and choice letters and location in the menu, during execution of lint or config programs. These should be deleted at the conclusion of such programs, and never thought of as permanent data. Menu programs should ignore these lines, and Lint programs should issue stern warnings upon finding such lines in menu definition files (unless that lint program put it in).

Because EMDL is a much better way to configure a UMENU menu system than were the old scripts, modern versions of UMENU no longer have scripts that use the equal sign in this way, but it's still reserved for that purpose.
In config and lint programs, there are typically several equal sign lines. The following characters determine their use. The existance of such lines during execution of a menu pance of such lines during execution of a menu program is considered a non-important error, and should be ignored.

Menu Definition File Command Line Syntax


All menu choices must have at least one command line with an upper case C in column 1. Multiple command lines are concatinated with a single space as a separator.


Before version 0.7.0, it was an error to have multiple command lines.

Also, before 0.7.0 it was permissible to leave the command line off any choice whose menu letter was Q, because any such choice defaulted to exit. As of 0.7.0, the Q letter does not cause the choice to exit, and as a warning prints the string nop, standing for No OPeration, before the menu letter on the menu.

Command lines can be either pseudo command lines, which define menu system navigation, or real command lines, which trigger the operating system to perform the command. Real command lines can be configured to prompt the user for arguments.

Pseudo Command Lines

Pseudo command lines define menu system naviagation and do not issue actual commands to the operating system. Pseudo command lines come in the following flavors:
 ^  Go up one menu level, or exit the menu program if already at the top.
Note that the ^ command can be considered the inverse of the ~ command explained below.
 ~  Go down one level. Execute the submenu defined by the present menu's definition file filename, with this Letter choice tacked on to the end. In other words, if from menu ab.mnu, the user pressed the c key, and letter c has a command of ~, the menu program would execute the menu defined by file abc.mnu.

If no menu definition file exists for the new submenu (abc.mnu in the example above), the program will issue an error message, prompt the user to hit a key signifying he's seen the error message, then return the user to the original menu (ab.mnu in the example above).

Real Command Lines

In its simplest form, the Real Command Line is a command which would, if typed by the user on the command line, run the desired process. For instance:
T_Files current dir
C_ls -ltr
The D choice illustrated above would run the command, giving a directory listing of the current directory, showing a single column with details, in reverse time order.

Command Environment

Before executing the command, the menu program can switch directories, add directories to the front of the execution path, or create/change environment variables. The menu program will back out these changes after executing the command. In addtion, the menu program can pause after command execution so the user can see the command's results on the screen. The user continues the action by pressing a key.

These modifications to the command environment are accomplished by placing other kinds of lines after the Choice Letter Line. Such lines include the Prepath line (P), the Directory line (D), the drive line (V, dos/win only), and the Stop line (S).

Argument Replacement With Prompts

Perhaps the most powerful feature of the UMENU Universal Menu System is the prompted argument replacement feature. Imagine a Menu Definition File letter, text and command line and stop like this:
T_Search a directory
C_ls -ltr %1%Directory to be searched%%
After the user presses S, the menu program will pause with the following prompt:
Directory to be searched==>
The user will then type in the directory, for instance, /etc. The program will replace the %1%Directory to be searched%% token with the user-input string /etc, and run the command ls -ltr /etc. A replacement token is defined by a percent sign, followed by a single character, followed by another percent sign, followed by a string, followed by two consecutive percent signs.

Multiple Replacement Arguments

The real power of argument replacement appears with commands involving several replaceble arguments. Lets say you want to search an entire user-specified tree for any files containing a user-specified string, sort the derived list of files either forward or reverse, as specified by the user, and write the resulting sorted list to a user-specified file. Take a "recursive grep" command. Lets say you want to query the user first for the root of the tree to search, then for the search string, then for the output file, and finally for whether the sort should be reverse order. Sounds like an app, right?

But using UMENUs argument replacement feature, it can be set up in one minute, as follows:
C_find %1%Tree to search%% -type f | xargs grep -l %2%Search string%% | sort %4| xargs grep -l %2%Search string%% | sort %4%Type -r for reverse, otherwise type nothing%%  -o  %3%Output file%%

Note that this would be entirely one line in the file, even though it word wraps in this HTML document. When the user chooses this item, he'd respond to the following four prompts in following order. Let's imagine the user responded to the prompts as indicated by the bolded text in the example below:

Tree to search==>/etc
Search string==>192.168.103
Output file==>junk.jnk
Type -r for reverse, otherwise type nothing==>
This would create file junk.jnk, containing a list of all files in directory /etc and below containing string 192.168.102. This file would be sorted in non-reverse order.

The order of the prompts is determined by the character between each replacible argument's initial percent signs. If two arguments contained the same char between their initial percent signs, their order would be determined by the sort order of the entire replacement prompts.

Note that the above example was meant to be very complex. Most are simpler. Check out this interface to the locate command:
C_locate %1%Search text%%


 >  <^

Copyright (C) 1999-2004 by Steve Litt