Xenmenu: An ASCII Menu Generator LG #39

Rate this post

Even though the world is moving toward slick graphical user interfaces and World Wide Web (WWW) technology, there is still a need to cater to those who use ASCII-based terminals. For example, many Internet Service Providers offer shell accounts, and even more public-access systems see a lot of use of their text-based interfaces. The systems that offer ASCII front-ends often have programs to automate common tasks that a user would want to accomplish, but the user still has to learn how to run those programs from a shell prompt. Some organizations have developed complex menu systems that shield the user from the intricacies of the underlying system. However, those programs– usually written in some shell scripting language–are often slow, offer minimal security, consume an inordinate amount of resources, and may be confusing to maintain.

Having experience as an administrator for a few public-access systems, I have been faced with the challenge of not only designing browser independent WWW interfaces, but also easy-to-use text-based interfaces. After creating mixtures of clunky shell scripts and inflexible C programs to address the latter, I decided that it would make things easier for me and other administrators to have a fast, easy-to-manage, and highly configurable method for generating text menus. The solution that I came up with, and which I will be discussing in this article, is Xenmenu, (pronounced zen-menu).

During the initial design of Xenmenu, a few major goals were addressed. First and foremost, a solution that strives to make things easy should not be overly complex to use or administrate. At the same time, this solution should be flexible enough to allow administrators to tailor the system to meet their exacting specifications. These requirements may include a security policy for a site, so Xenmenu needs to incorporate features that allow it to be used as a secure shell. Finally, Xenmenu should be as small and fast as possible.

The four main components of Xenmenu are the core program, the configuration files, the menu description files, and the support files. The job of the core program is to first configure itself, then go into a loop of reading the menu description files, formating and displaying them to the user, and reading the user’s input. Each of these stages will now be described in detail.

There are three configuration files which may or may not exist. The first two of these files are analogous to the system-wide and user-specific shell configuration files such as /etc/csh.login and ~/.login. The final configuration file, which also may or may not exist, is the secure configuration file; any previous action taken by the first two configuration files may be overridden by the secure configuration file. This allows administrators to give users access to change their environment without compromising security. Of course, the installer may also opt to disallow the user from creating a personalized configuration file at all if security is a major concern.

The configuration files only allow two directives: the setting of environment variables and the execution of programs. For this reason the configuration language is simple. The format of the configuration files are:


The first line is an example of setting an environment variable. An example of this in use would be: PAGER /usr/bin/more. This would set the environment variable PAGER equal to /usr/bin/more. The second line is an example of executing an external program from within the configuration file. An example of this would be: run /bin/cat /etc/motd.

Once the configuration files are acted upon, a menu file is read and displayed to the user. These menu files are the most important part of Xenmenu from an administrator’s standpoint since they define how the menu will look and react to the user. Since most of an administrator’s time will be spent writing the menu files, they are designed to be easy to create. At the same time, flexibility is a major concern.

Menu files are plain text files that may be modified and reinstalled even while people are actively using Xenmenu. Each line of a menu file is a command, comment, or a blank line. Commands may have zero or more arguments separated by one or more spaces depending on the command. Comments are inserted by placing a # as the first non-space character on a line and continue until a new line is reached. Blank lines are ignored.

There are three main parts to a menu file: global options, formatting and display options, and choice declarations. Global options should appear before any choice declarations are made and affect the overall look and feel of the menu. Currently, there are only two global options: checkcase and nocheckcase. If checkcase is defined, then choice declarations will be case sensitive. This means that if the user enters a « Q », it will be acted upon differently than if they entered a « q ». The default behavior is nocheckcase which means that a user may enter either a « Q » or a « q » and the same action will be taken.

The bulk of the commands available for use in menu files are the formatting and display options. These options define how a menu will be drawn on a user’s screen and may be given at any point within a menu file. The available commands and the arguments they accept, (if any), are given below. Arguments given in marks are required, while those in [] marks are optional. Some references are made to the file config.h. This file is part of the Xenmenu distribution and may be edited before compilation when installing Xenmenu.

  • center : Centers the given string on the screen. The string will be wrapped as needed to fit on the user’s screen.
  • columns [number]: Set the number of columns in which to print options to [number]. If [number] is not defined, then 1 column is used. This is analogous to the HTML declaration.
  • header [header]: Defines the menu header to be [header]. If header is blank, then MENUHEAD as defined in config.h is used.
  • name [name]: Defines the menu name to be [name]. If [name] is blank, then [name] is cleared.
  • notype: Suppresses the printing of the option type, (i.e. menu, file, or exit) after the option name.
  • opttail [string]: Defines [string] as the string to be printed after an option value, (it is what separates the option value and the option name).
  • print [-n] [string]: Prints [string] to the screen. If no string is defined, a blank line will be printed. If [string] contains something between  » marks, it is taken as a command to be run. To print a ‘ character, enter it as  ». Environment variables may be printed by preceding them with a $ mark. To print a $ character, enter it as $$. If the -n argument is given, than a newline is not appended to the end of [string]. Usually, all leading spaces and tabs are removed from [string] before it is printed to the screen. In order to print leading spaces, begin the string with a double quote. Any double quotes within the string are treated as literals and printed to the screen. A double quote found at the end of a string, if the string begins with a double quote, is not printed, however. A double quote may also be used if you want to print a -n at the beginning of the string. Finally, the string to print will be wrapped as needed in order to fit nicely on the user’s screen.
  • printfile : Prints the to the screen. If SECURE, (defined in config.h), is > 4, then the path to is taken from SECUREDIR, otherwise should contain a path.
  • printheader: Prints the menu header. The [header] will be printed on the left side of the screen and the [name] on the right side. A default header value, defined in config.h is used if header is not defined. No name is printed if not defined.
  • printline [string]: Prints a line across the screen. If [string] is not defined, a line of dashes will be printed, otherwise a line composed of [string] will be printed.
  • prompt [string]: Sets the menu prompt to [string]. If [string] is not defined, then DEFAULTPROMPT defined in config.h is used. NOTE: Everything after the keyword prompt and a space is taken as the prompt, (including spaces).
  • run : Runs the defined file. If SECURE, (defined in config.h), is a 1, 3, 5, or 7, then the path to is taken from SECURERUN, otherwise should contain a path.
  • type: Prints the option type, (i.e. menu, file, etc.) after the option name. This is the default.
Lire aussi...  XML parsing in AOLserver LG #63

Choice declarations define how the menu should react to user input. A choice may either run an external program, display a file, load and display another menu, or exit the menu system. Each choice may contain a value, a name, a comment, or a combination of the three. Choices are defined in the following way:

option {

The part may contain one or more of the commands listed below. The argument convention is the same as above with required arguments contained in marks, and optional ones enclosed in [] marks. Again, references to the file config.h are given.

  • exit: This means that the menu will exit if this option is chosen.
  • file : This is the filename that will be read if the menu option is chosen. If SECURE, (defined in config.h), is > 4, then the path to will be taken from SECUREDIR, otherwise should contain a path.
  • menu a;: This means that the menu will be loaded if this option is picked. If SECURE, (defined in config.h), is a 2, 3, 6, or 7, then the path to is taken from MENUHOME, otherwise should contain a path.
  • run : This means that the program will be run if this option is picked. If SECURE, (defined in config.h), is a 1, 3, 5, or 7, then the path to is taken from SECURERUN, otherwise should contain a path.
  • comment : This is an optional field which holds a description of the menu item.
  • name : This is the name of the option.
  • noprint: This will cause the option not to be printed to the screen.
  • value : This is an optional field that holds the menu NOTE: Values will be automatically assigned by the menu if none is given.

As mentioned above, Xenmenu may also be used as a secure shell. When compiling Xenmenu, the administrator may select various security options. Zero–the default–or more of these options may be given at compile time. The options allow for:

  1. The ability to only run programs in a given path,
  2. The ability to only view files under a certain directory,
  3. The ability to only view menus under a certain directory, and
  4. The ability to turn off parsing a user’s personal configuration file.

It is important to realize that Xenmenu can not make any guarantees as to the security of any external program that it calls; if you allow the user to run the mythical program foo from Xenmenu, and foo contains a security hole, than the user may be able to exploit that hole to violate your security policy. However, by using Xenmenu as a user’s shell in conjunction with the above security options, an administrator can limit what a user may do on the system.

Finally, there are a couple small features that Xenmenu offers which are not listed above. First of all, if the user enters something which is not an option for the menu they are viewing, what they input is sent to a shell for parsing. This allows the user to enter valid shell commands even if they are not a menu option. This does not allow them to violate any security settings, however. Secondly, the user may resize their screen and the next menu loaded will adjust itself to fit within the new screen size.

I hope that this article gives you a good understanding of Xenmenu and what it can do. I also hope that Xenmenu provides a solution to your need for an ASCII menu generator, (if you have such a need). Currently, Xenmenu is still under development, however it is actively being heavily used on more than one system. The source code for Xenmenu is released under the Gnu Public License and may be found at http://www.xenos.net/~xenon/software/xenmenu. The author welcomes any suggestions, comments, or complaints you may have via E-Mail to xenon@xenos.net.

indexnew-5261144 homenew-5586890 back2-8482074 fwd-1305928