MH & nmh: Email for Users & Programmers

May, 2006

New Message Notification: rcvtty

(xmh users: This rcvtty section applies to you if you have an xterm window open onto the host where your system mailbox is located. Otherwise, look at the rcvxterm shell script in the Section Replacing rcvtty with Pop-Up Windows.)

The rcvtty program sends scan-like information to your terminal about new messages. UNIX comes with other ways to tell you about new mail, such as biff(1) or the shells' mail-checking variables. But rcvtty has a big advantage over other notification setups: you can set .maildelivery to run rcvtty only for certain messages. Also, rcvtty uses MH formats so it can notify you in almost any format or formats you want.

Here's a sample entry for your .maildelivery file:

    *    -    ^    R    /x/y/rcvtty
That example sends a one-line summary of all new messages. If a 456-character message comes from Emma H. User at 5:52 p.m., you'd see a line like this on your screen:
    17:52:   456 Emma H User     Lo-cal pizza<<Do you have a recipe
The following sections explain how to change the places rcvtty notifies you, how to change what the notices look like, and how to make rcvtty run a separate command that shows you just what you want about your message.

Where rcvtty Notifies You

rcvtty can send the same notification to many places. By default, it writes to all the places you're logged in to on the host where your mail is actually delivered. (Actually, you'll see the message on all your login sessions listed in the /etc/utmp file. Some window systems won't list all your windows in the utmp file. Use the who(1) command to see where you're listed. Also, see the Section Control Your Listing in who(1).)

So, at companies with a central mail server computer (where users' computers run POP or mount their system mailbox filesystem over the network), rcvtty probably won't help. (In those cases, the shell's mail-notification variable or a program like xbiff would be better.)

Maybe you don't want to be notified everywhere you're logged in. Here are a few ways to control where.

The -biff Option

On many systems, the UNIX biff(1) program tells your system whether or not you want to be notified about new mail. biff does that by setting the owner-execute bit on your terminal (the tty file). It's arcane, but it works.

Normally, when you aren't using your .maildelivery file, a daemon program called comsat(8) does the notification. If a terminal has its execute bit set and mail comes in for that user, comsat sends a notice to the terminal. You can use .maildelivery to do this notification instead -- if your system has the biff utility, that is. (If your system doesn't have biff, you could try setting the terminal's execute bit, anyway -- and see if rcvtty will notice it:

    % chmod u+x `tty`
It's probably a good idea to talk this over with your system administrator. The execute bit may be used for something else on your system.)

If you use the rcvtty -biff option in your .maildelivery file, then rcvtty will only notify terminals where you've run biff y.

If you haven't used biff, here's a quick overview. To enable mail notification on your current terminal or window, type biff y. Typing the command biff n turns off notification for the terminal where you run it. Typing biff by itself will tell your current setting. For example:

    % biff y
    % biff
    is y

The mesg Command

If you can't use rcvtty -biff, the mesg(1) command might be the answer. mesg uses chmod to allow or deny access for other users who want to send messages to your terminal. rcvtty will only notify sessions where you've used mesg y.

If you use a window system, you can pick one window to get messages; run mesg y there and leave the window open all the time. Use mesg n in other windows.

If you also get messages with the talk(1) program, and you're logged on more than once, this one-window access can cause trouble. Some (or all?) versions of talk will only check for access on the first terminal you're logged in to. (Here's what I mean by "the first terminal": run the who(1) command, start at the top of its list, and look for the line nearest the top where you're listed. That's your first login.) If you've typed mesg n in your top-listed login session, talk may tell people that you are "refusing messages" -- implying that you've shut off messages in all login sessions, when you've really only shut them off in some. So, if you use talk, try to make your first window or login the one that grants mesg access -- and test to be sure it accepts messages.

On systems I've tested, the write(1) program doesn't have the same problem as talk; it seems to look for any terminal with mesg y set.

Control Your Listing in who(1)

When rcvtty wants to notify you, it checks the list in the who(1) command. (Actually, rcvtty reads the system /etc/utmp file.) It'll only try to notify you at slots where you're listed as logged in. You can use this to make rcvtty (and utilities like talk) ignore you.

For instance, in the X Window System, the terminal program xterm has an option to control whether a window will be listed in who (actually, in /etc/utmp). If you start xterm with its -ut option, your window won't be listed and you won't get notices in it. You'll be notified in the window or windows you start with the +ut option.

How rcvtty Notifies You

rcvtty gives you some control over the notice you get. The terminal bell will ring unless you add the -nobell option. The cursor will move to the left-hand side of the screen first unless you use -nonewline. As the next two sections explain, you can control the format of the notice and what messages you're notified about.

Changing the Output Format

I don't like the default rcvtty format. I usually won't see the single line rcvtty prints, especially if it's buried in the middle of a screen while I'm editing a file. To fix that, I've used the -form option and written a MH format file called rcvtty.format. It makes a three-line output with a highlighted top line. It's explained in the Section The rcvtty.format File. With my rcvtty.format file, I don't need the terminal bell; the highlighted first line is enough to make me notice. The output looks like this:

    * MAIL: 456ch @ 17:52 *
    Emma H User
      Lo-cal pizza<<Do you have recipes
I run that setup with the following line in my .maildelivery file:
    # Tell me about all new mail; use three lines and highlight:
    *  -  ^  R  "/x/y/rcvtty -form rcvtty.format -nobell"
Because the rcvtty.format file is in my MH directory (the directory listed in my MH profile Path: entry), I don't have to use its pathname.

Under nmh, rcvtty has a -width option to specify the width of output lines. For example, -width 40 would make 40-column lines. Without -width, the default is the width of the terminal.

Picking the Messages You're Notified About

Using an * (asterisk) in the field argument of .maildelivery entries makes rcvtty run for all new messages. If you don't want to be notified about all messages, use field and pattern arguments.

Of course, you can have more than one rcvtty entry in your .maildelivery file. One entry could notify you about all messages. Another could add an extra notice, maybe with the terminal bell, too, for important messages. For example, when you get mail from your manager, you can send a message to your terminals with from Big Boss, the size, and the subject. If you get mail about a full disk (usually from an automatic system monitor program), the bell can ring and the message DISK FULL! DISK FULL!... can be printed across the terminal.

The rcvtty -format option lets you give words and an MH format (Section MH Format Strings) without needing a form file. Here are the three entries I explained in the paragraph above.

    *,-,^,R,"/x/y/rcvtty -form rcvtty.format -nobell"
    From,simmons,|,R,"/x/y/rcvtty -nobell -format \"*** $(size) chars. from Big Boss: %{subject}\""
    Subject,"disk full",|,R,"/x/y/rcvtty -format \"DISK FULL! DISK FULL! DISK FULL! DISK FULL! DISK FULL!\""
Variables like $(size) are listed in the Table Variables Set for pipe and qpipe. The %{subject} is an MH format component escape, covered in the Section MH Format Strings.

The Section Replacing rcvtty with Pop-Up Windows shows another way to find out about mail: colored windows that pop up on an X Window screen.

Using a Message Preprocessor

If you give rcvtty the name of a command, it will run the command. rcvtty will give the message to the command's standard input; it will send the command's standard output to all the terminals where you're logged in. If the -form and -format command-line options don't give you enough control over the notice rcvtty sends -- this will!

Here's a simple example. To show the first ten lines of a message, this entry in your .maildelivery file would do the job:

    *   -   ^   R   "/x/y/rcvtty /x/y/head"
That uses the UNIX head command to read the first ten lines of the message. (If your system doesn't have head, use /bin/sed 10q instead.) A flexible program like awk or perl can do more with your message.

There are problems, though. If a terminal you're logged onto is running a full-screen application that puts the terminal in raw mode, the rcvtty output can:

    jump down
              the screen
                         like this
Also, if your cursor is in the middle of a screen of text, the message from rcvtty can be hard to see because it's buried in the text:
    jump downfh jlasfujarlh aelr uhgwp9t th p4yr hy49r5 y4ht wlth
    sdajflfja8the screeneasjfau eworu wepr d;9f ua4 aw4; hfuha4e;
    fdsa;fjw03pu 4hhertjjlike thisasdf;jasf0aura 0;o3u54t 9fh04o2
(Can you find the words?) The rcvtty.fixup shell script helps. You tell rcvtty to run the rcvtty.fixup shell script; tell rcvtty.fixup to run the command you really want to run. rcvtty.fixup will give the message from rcvtty to your command, and it will filter the output of your command this way: Here's how to run the head command via rcvtty.fixup:
    *   -   ^   R   "/x/y/rcvtty /x/y/rcvtty.fixup /x/y/head"
If your system can't directly execute files that start with #!, as Section How Does Your System Execute Files? explains, add /bin/sh before /x/y/rcvtty.fixup.

Here's the rcvtty.fixup script. (You can also get the script, with much more documentation, from this book's online archive. It's at examples/mh/bin/rcvtty.fixup.) If you haven't installed a shell script before, see the Section Writing Shell Scripts for MH.

    #! /bin/sh
    # $Id: rcvtty.fixup,v 1.1 92/07/31 08:09:24 jerry book2 $
    ### rcvtty.fixup - fix rcvtty output for raw-mode ttys
    ### Usage: rcvtty rcvtty.fixup command [command-args]

    cr="`echo x | tr x '\015'`"
    spaces="                                                                      "

    "$@" |
    sed -e "s/^[    ]*\$/$spaces/" -e "1s/^/$cr/" -e "s/\$/$cr/"