Chapter 8: Making Unix Do One Thing Well

Overview

Most of what we've covered thus far has been abstract. Although we have seen that there are practical reasons behind every tenet of the Unix philosophy, some of you may still believe that they wouldn't work in the real world. "Small is beautiful" is fine, but what about the big jobs? Is it really possible to build a complete application from a collection of small programs? Can a program without a CUI serve a useful purpose? These are fair questions, to be sure. You will find the answers to them and more in this chapter.

We're going to look at MH, a mail-handling application developed by the RAND Corporation. It consists of a series of programs that when combined give the user an enormous ability to manipulate email messages. A complex application, it shows that not only is it possible to build large applications from smaller components, but also that such designs are actually preferable.

If a program is valuable, it will be ported from one platform to the next. Such is the case with MH. The original ideas remain the same, but newer versions have come along through the years that enhance the original. In today's Linux distributions, New MH (NMH) has largely superceded MH. NMH incorporates all of the major features of MH and-most importantly- adheres to the original philosophy of MH. For the purpose of this discussion, we will be covering the ideas behind MH, recognizing that they apply equally well to NMH.

Before Web-based email came along, two programs-/bin/mail and Berkeley Mail-had been used almost exclusively for many years to process email under Unix. Although Berkeley Mail was used heavily, both programs are poor examples of applications with respect to the Unix philosophy. Both employ CUIs, have limited capabilities as filters, and, in the case of Berkeley Mail, can hardly be considered small programs. Neither focuses on doing one thing well, opting instead to incorporate a range of mail-related functions within a single user interface.

MH provides capabilities equivalent to those in both /bin/mail and Berkeley Mail. It is a collection of small programs, each of which performs a function found in the other two mailers. MH also provides other small programs that perform actions not available with the other two, almost as if to underscore the ease with which one can incorporate new functions in an application modeled under the Unix philosophy.

The following is a partial list of the commands contained within MH:

ali

List mail aliases

anno

Annotate message

burst

Explode digests into messages

comp

Compose a message

dist

Redistribute a message to additional addresses

folder

Set/list current folder/message

folders

List all folders

forw

Forward messages

inc

Incorporate new mail

mark

Mark messages

mhl

Produce formatted listing of MH messages

mhmail

Send or read mail

mhook

MH receive-mail hooks

mhpath

Print full pathnames of MH messages and folders

msgchk

Check for messages

msh

MH shell (and BBoard reader)

next

Show the next message

packf

Compress a folder into a single file

pick

Select messages by content

prev

Show the previous message

prompter

Prompting editor front end

rcvstore

Incorporate new mail asynchronously

refile

File messages in other folders

repl

Reply to a message

rmf

Remove folder

rmm

Remove messages

scan

Produce a one-line-per-message scan listing

send

Send a message

show

Show (list) messages

sortm

Sort messages

vmh

Visual front end to MH

whatnow

Prompting front end for send

whom

Report to whom a message should go

MH uses a collection of folders to organize a user's mail. It stores each mail message as a separate file within a folder. The inbox folder has a special purpose: The contents of the user's system mailbox are first placed in the inbox by the inc command. Once mail has been moved to the inbox, it can then be selected and acted upon by the rest of the MH commands without having to specify a folder.

As you can see from the list, MH provides all of the capabilities you would expect from a comprehensive email application. The scan command displays the sender, date, and subject line of a range of messages in the current folder. The commands show, next, and prev show the contents of selected mail messages, the next message in the current folder, or the previous message in the folder, respectively. Comp and repl allow you to create a new mail message or reply to an existing one.

The major difference between MH and the other Unix mailers is that you can invoke any of the mail-handling functions from the shell-prompt level. This gives MH tremendous flexibility. Since each function is a command unto itself, you can call functions like any other command under Unix.

The commands can be used within shell scripts and as filters. The output of scan, for example, can be "piped" into the Unix grep text-search command to locate mail from a specific sender quickly. If the folder contains so many messages that scan's output scrolls off the screen, the output can be piped into the Unix more command to allow the user to view the list a page at a time. If the user wanted to look at a listing of only the last five messages, scan | tail -5 does the trick.[1]

The point here is that the user is not limited to the functional capabilities built into MH by the original programmer. One need only combine MH commands with other Unix commands to create new and useful functions. This requires no new programming. The user mixes and matches the commands as desired. If the desired capability doesn't exist, it can be created immediately with very little effort. Many new functions are developed on the fly on the user's command line using this simple yet powerful architecture.

A valid question people sometimes raise about MH is, how do you remember which commands are available? Those who are familiar with the Berkeley Mail command, for example, know that they can always type "?" to get a list of available commands. MH really shines in this area. Since it doesn't use a CUI, you can refer to the on-line Unix manual pages at any time. These manual pages are considerably more thorough than the short list of commands provided by Mail. MH's operation is therefore much better documented as there is typically a full page of documentation (or more!) per individual command.

What about the user who prefers a CUI? MH provides one with the msh command for those users who enjoy being prompted for the next action to take. Obviously, though, users are not locked into using msh if they choose not to. They are free to write their own user interface that works as a layer on top of the MH command set. For example, xmh is a user interface to MH that runs as a client under the X Window System. Buttons and menu items in the xmh application simply call underlying MH commands as appropriate. The xmh user interface presents a seamless interface to the user, however. It appears as if it were written as an application that performs the mail-handing functions directly.

MH offers us an excellent example of a specific way to build a complex application under Unix. Figure 8.1 illustrates the more general case.

click to expand
Figure 8.1

The Small Programs Layer consists of a set of Unix commands or shell scripts, each of which carries out one function of the application. As new capabilities are needed, it is an easy matter to create other small programs to provide the desired functions. On the other hand, if a more limited application is wanted, nothing need be done. The Application Layer simply refrains from calling those programs that are unnecessary.

The Application Layer determines the functions that are essential to the user. The functions themselves are carried out by the Small Programs Layer. It encapsulates the business rules and provides boundaries around the application. The Application Layer operates primarily as a liaison between the Small Programs Layer and the User Interface Layer. By unifying elements of the Small Programs Layer in a single environment, it helps establish the relationship among the small programs and provides the framework that ties them together. In other words, it is the integration layer.

The User Interface Layer is the part that the user sees on the screen when the application is invoked. It is highly malleable in that a variety of user interface styles can be used depending on the desired presentation. Three styles of user interfaces are most common in the Unix environment: the command-driven user interface, where parameters are passed to the command from the command line; the scrolling menu type, a kind of CUI where parameters are collected from a series of interactive dialogs with the user; and the GUI, typically found on a PC with graphical capabilities such as those found under the X Window System.

A well-constructed Application Layer allows the user to choose from a variety of user interface styles, implying that the User Interface Layer should almost never be "hardwired." The user should be free to choose whatever user interface suits the particular circumstances. Thus, a user can take advantage of the superior power afforded by a GUI for occasional usage, yet still choose to use, say, a scrolling menu interface when performance is important. MH and its companion xmh provide an example of an application that incorporates this kind of flexibility.

[1]These are not the only ways to perform these functions. As in the rest of Unix, many paths lead to the same conclusion. The examples shown were chosen to illustrate the flexibility of a Unix-style architecture.



Linux and the Unix Philosophy
Linux and the Unix Philosophy
ISBN: 1555582737
EAN: 2147483647
Year: 2005
Pages: 92
Authors: Mike Gancarz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net