Snooping on xmh

If you're trying to find out how xmh uses MH commands so that you can change the way commands work without causing problems, try the techniques in this section.

Use the debug Resource

If you set the xmh*debug resource, xmh will write debugging information to its standard error. The easiest way to do that is by starting xmh from an xterm window (probably with a scrollbar). For example:

    % xmh -xrm '*debug:1'
    # 4 : /u/ehuser/.mh_profile
    # 4 : <Closed>
    # 4 : /u/ehuser/.xmhcheck
    # 4 : <Closed>
    Making screen ... Realizing... done.
     setting toc ... # 4 : /u/ehuser/Mail/inbox/.xmhcache
    # 4 : <Closed>
    # 4 : /u/ehuser/Mail/inbox/.mh_sequences
    # 4 : <Closed>
    done.
    (Checking for new mail... done)
    (Checking for new mail... done)
            ...etc....
    [magic toc check ... done]
            ...etc....
    (Checking for new mail... done)
    [magic toc check ...# 4 : /u/ehuser/Mail/inbox/.xmhcache
    # 4 : <Closed>
    Executing scan ... pid=13898 blocking.
    unblocked; child not done.
    reading alternate input...read.
    blocking.
    unblocked; child not done.
    reading alternate input...read.
    done
    # 4 : /u/ehuser/Mail/inbox/.xmhcache
    # 4 : <Closed>
    # 4 : /u/ehuser/Mail/inbox/.mh_sequences
    # 4 : <Closed>
     done]
    
Here's some brief explanation: To learn more, start xmh, try things, and watch the messages in your xterm window. You might want to browse through the source code to find out exactly what's happening as each debugging message is printed. Search the code for the string DEBUG.

Use Accounting Information

Many UNIX systems keep accounting data about the processes that each user runs. When xmh runs a standard UNIX command, it starts a process to do that. Therefore, to find out whether xmh used an MH command, run the xmh command, then check the accounting data. Many UNIX systems show that data with the lastcomm(1) program. For example, after I used the xmh Sort Folder command, lastcomm showed that the sortm and scan commands had been run:

    % lastcomm ehuser
    scan             ehuser   ??         0.23 secs Wed Jul 18 09:10
    sortm            ehuser   ??         0.48 secs Wed Jul 18 09:10
    xwud             ehuser   ttyp1      0.45 secs Wed Jul 18 08:48
            ...
    
Unfortunately, lastcomm doesn't show what command-line switches were used or what was in the command's environment as it ran. The next section can help with that.

Make a Front End Shell Script

A much more flexible way to snoop on xmh is by replacing MH commands with shell scripts. In fact, this method doesn't just work for snooping -- you can also use it to change the way that xmh runs MH commands.

The idea is to make a directory full of symbolic links to all the MH programs. Tell xmh to use that directory by adding it to your path or setting the MhPath resource. Then, when you want to see or change how xmh uses an MH command, replace the symbolic link with a shell script. The shell script can write log messages to a file, display command-line options that xmh called it with, and execute the MH command. The steps are explained in the next section.

CAUTION: With a radical change like this, there's always the chance of making a mistake that loses or corrupts your mail. If you use xmh for reading important email, I don't recommend this method unless you're very comfortable with UNIX and shell programming.

Making the MhPath Directory, Making xmh Use It

Here are the steps you need to follow to set up the MhPath directory. You only need to do this once.

  1. First, make a directory on your account with symbolic links to the executable MH commands. You could name it xmhbin. (To make the directory, use the command mkdir $HOME/xmhbin.)
  2. Next, link the MH commands. I use symbolic links because they're easy to list (with ls -l) and see where the links "point." But you may also be able to use UNIX "hard" links if the MH executables are on the same filesystem as your home directory.
  3. Then start xmh using the new executables and be sure it still works. Type one of the following commands.
  4. Try a couple of xmh commands that run MH commands, such as Incorporate New Mail or Sort Folder. Then use ls -lut to show the last access time of the symbolic links in your xmhbin; when xmh uses them, their last access time (atime) will be updated, and you can see that in the ls -lut output.

Replace a Link with a Shell Script

The next step is to replace a link with a front-end shell script. First, rename the link (or remove it):

    % pwd
    /xxx/yyy/xmhbin
    % mv sortm sortm.orig
    
Here's a simple shell script for sortm. (This file is in the book's online archive, too, at examples/xmh/bin/sortm.sh.) It writes a lot of information to a log file in your home directory, then executes the MH command:
    #! /bin/sh
    # sortm - front end to MH sortm command, run from xmh
    # appends logging information to $HOME/sortm.log first
    # use subshell to gather all command output, stdout and stderr:
    (date
    echo "args are: $0 $*"
    echo "environment has:"
    printenv) >> $HOME/sortm.log 2>&1

    # run the real command with exec, so this script
    # (and the shell that runs it) can exit now:
    exec /usr/local/mh/sortm $*
    
After you've installed the script, try it (in this case, use the Sort Folder command). The sortm.log file in your home directory should look something like this:
    % cat $HOME/sortm.log
    Wed Jul 18 10:12:46 EDT 1990
    args are: /xxx/you/xmhbin/sortm +/xxx/you/Mail/inbox -noverbose
    environment has:
    DISPLAY=unix:0.0
    EDITOR=/usr/ucb/vi
    HOME=/xxx/you
            ...
    
and, of course, your current folder should have been sorted.

Standard Output vs. Standard Error

If your shell script writes any messages to the standard output, xmh may ignore them. Or, in cases where xmh is expecting to read useful information on the standard output, xmh could accidentally include what your script writes to the standard output. For example, when you Rescan Folder, xmh runs scan and puts the scan standard output into the .xmhcache file.

xmh Release 4 added a nice new feature: if a command writes a message to the standard error, the message is displayed in a notice box. Your script can use this feature to send you messages. As a semi-useless but easy to understand example, here's a version of pick that shows the command-line options xmh uses. (This file is in the book's online archive, too, at examples/xmh/bin/pick.sh.)

    #! /bin/sh
    echo "pick arguments are: $*" | fmt -50 1>&2
    exec /usr/local/mh/pick ${1+"$@"}
    
The fmt -50 command folds lines at whitespace to keep the box width reasonable. If you don't have fmt, try fold instead. The ${1+"$@"} works around a problem with command-line parameters in sme older Bourne shells. I ran that pick front-end with search shown in the Figure Example of Pick skip button. The window I got after pick finishes is shown in the Figure below. (It makes me glad I did that with an xmh Pick window instead of typing the MH pick command myself.)

Figure: Making a notice box

makanobo.gif

I don't recommend using xmh notice boxes for commands that make a lot of output. I'd bet that they weren't really designed for this sort of abuse....

NOTE: xmh Release 3 isn't happy about unexpected output and doesn't make the nice notice boxes. Use a log file instead.

Read the Source Code

Here's one last idea: if your computer has the xmh source code online and you feel like digging into it, that's the best way to find out exactly what's happening. Look at the C programs (the *.c files) in the xmh subdirectory of your X source tree.