WorkShop Teamware: Solutions Guide: -

# Getting the Most From the Configuring Tool Notifications |

The notification feature of the Configuring tool automatically sends email when a workspace-related command (such as a putback) is executed. Users have expanded on this feature to perform a variety of tasks. This topic describes some of these tasks and how they can be implemented.

A complete script that takes advantage of the notification feature is also presented, beginning on page 82. The script can be adapted to a variety of uses.

## Typical Use of Notification

As an example of the way notifications are typically used, consider the user `chip`, who wishes to be notified whenever the file `foo`.`cc` is put back from a development workspace into an integration workspace. To register the event with the Configuring notification feature, `chip` can use either the graphical user interface or a text editor to place the following entry in the `Codemgr_wsdata/notification` file in the integration workspace. This entry causes Configuring to send `chip` a message when anyone performs a putback of `foo`.`cc` that changes `foo`.`cc` in the parent:

    chip@monk putback-to
    BEGIN
    foo.cc
    END

This basic use of the notification feature is valuable in itself, but many sites have found more creative uses for notification. The key to exploiting the notification feature is recognizing that it calls `mail`, a flexible program with capabilities that are often overlooked. For example, `mail` can send messages not only to users but to other programs through a pipe, the operating system feature that allows the output from one program to become the direct input to another.

## The Ins and Outs of `mail`

The `mail` program can send messages to aliases as well as to users. If you place the name of an alias in the `notification` file of a workspace, a mail message is sent to all users listed in the alias. By substituting a pipe symbol (`|`) and a program name for a user name, the contents of the message are passed to the program instead of mailed to a user.

As an example, assume that user `chip` wants to compile a list of the names of users who bring over his file (`foo`.`c`) into their workspaces. He could place the following lines in the `notification` file, either with the Configuring GUI or directly with a text editor:

    foo_alias@monk bringover-from
    BEGIN
    foo.cc
    END

These entries cause a message to be sent to `foo_alias` whenever `foo`.`cc` is brought over into another workspace. If `foo_alias` is defined as follows in the `/etc/aliases` file:

    	foo_alias:chip@monk, | /home/chip/bin/foo_log.sh

then user `chip` receives the notification message, and it is also piped to `chip`'s private program `foo_log`.`sh`. In this case, `foo_log`.`sh` is a script that extracts the `Date:` and `User:` lines from the mail message and appends them to a log file. Because these lines contain the date the message was sent and the name of the user who performed the bringover, the log file accumulates a concise history of who brought over this important file.

## Mailing a Policy Statement

Real-world examples of custom notification scripts are common among Sun WorkShop TeamWare sites. One example, taken from the annals of SunOS development, is described briefly on page 12. In that case, a notification is placed in top-level workspaces that causes a policy statement to be sent to users who bring over files for the first time. The policy statement details the responsibilities of users who edit files from top-level workspaces and alerts new users that are not able to put back files to top-level workspaces without special permission.

A mail alias provides a straightforward way to automate sending the policy statement. First, the person responsible for the top-level workspace places the required line in the `Codemgr_wsdata/notification` file of the workspace. For example, the following line, entered without `BEGIN` and `END` keywords, causes a message to be sent to `newuser_alias` whenever someone brings a file over from the workspace:

    	newuser_alias@mach bringover-from

A line is then placed in the `/etc/aliases` file on `mach` to define the alias. The following line causes a message that is mailed to the alias to be piped to the script `newuser`.`sh`. The script is designed to parse the mail messages and take the desired action.

    	newuser_alias: | newuser.sh

When a new user brings over a file from the top-level workspace into a development workspace, the following occurs:

  1. Configuring checks the `notification` file to determine whether or not to send a mail message in response to the bringover event. The `notification` file instructs Configuring to send a message to `newuser_alias`.

  2. Configuring launches the `mail` program to send a message to `newuser_alias`, one member of which is `|newuser.sh`. The mail message is routed through a pipe to `newuser.sh`.

  3. The `newuser.sh` script parses the mail message and extracts the name of the user who performed the bringover.

  4. The script reads a list, searching for the user name. If the name is in the list, then the user is not a new user, and the script quits.

  5. If the user name is not in the list, then the user is a new user, and the script adds the user name to the list.

  6. The script launches `mail` to send a policy statement to the new user and quits. The `mail` program sends the policy statement to the new user in a mail message.

## Other Uses of Notifications

The last section described one use of a script that parses mail messages; that is, to send a message to a user whose name does not appear in a list of users. Some other possible uses of message-parsing scripts are to:

- Mail messages only to users who perform certain activities such as reparenting workspaces

- Log notification messages categorized by user, date, activity, or workspace (parent or child)

- Maintain statistics on how often certain events such as putbacks occur in specific workspaces

- Change the subject line of the notification message, add commentary, and forward the message to interested parties or save it to a log file. For example, the script could parse the `Parent` `workspace:` lines to determine the project or release level to which the event applied. On that basis, the script could change the `Subject:` line to provide more detail before forwarding the message.

- Search the message for a bug identifier, and log or forward the message based on the bug identification number

- Schedule (following the putback of a source file) in the parent workspace an overnight build and automatic test of executables that depend on the source file.

The next section provides details of how to accomplish these goals.

## Parsing Mail Messages

This section describes ways to write scripts that parse mail messages from Configuring, including an example script you can modify for almost any use. The examples are not the only ways to accomplish their stated goals, and may not be the most elegant ways. They are presented here because they have been proven to work.

### Typical Mail Message

The mail message shown in Figure 20 is typical of those sent by the Configuring notifier. This message was sent in response to the putback of three files from the child workspace `develop_1` to the parent workspace `integrate_1` by user `jdoe`. This message is used as the example for the rest of this topic.

    From jdoe Thu Jan 26 13:01 PDT 1995
    Date: Thu, 26 Jan 1995 13:01:50 +0800
    From: jdoe (Jan Doe)
    To: script_alias@conundrum
    Subject: Code Manager notification
    Event: putback-to
    Parent workspace: integrate_1
    	(holymoly:/export/home/holymoly/jdoe/src/ws/integrate_1)
    Child workspace: develop_1
    	(holymoly:/export/home/holymoly/jdoe/src/ws/develop_1)
    User: jdoe
    Comment:

    	In my attempt to fix BUG-12, I fixed BUG-121 instead!
    Files:
    create: file_1
    create: file_2
    create: file_3

#### Figure 20 Typical Notification Mail Message

### Copying the Message

Before attempting to parse a mail message, most scripts make a copy of the message. For example, when a script receives its input from `stdin`, the following line in the script stores a temporary copy of the incoming message in `/tmp`:

    	cat > /tmp/incoming_message

The message can then be parsed or appended to a more permanent log file.

### Parsing Techniques

Most scripts that parse mail messages make heavy use of filters and utilities such as `grep`(1) (or `egrep`(1)), `sed`(1), `awk`(1), and `tr`(1). Consult the man pages for complete information.

#### Checking Message Validity

Messages from the Configuring notifier contain the string "`Code Manager notification`" in their subject lines. A script may check this line to make sure the message was indeed sent to the script by the notifier. The following lines perform this check.:

    SUBJECT=\Qegrep -i '^Subject:' /tmp/incoming_message \
    			 | head -1 | awk -F: '{print $2}'\Q
    if [ "$SUBJECT" != " Code Manager notification" ]; then
    	Process misdirected message ...
    	exit
    fi
    Continue processing ...

The first part of the statement,

    	egrep -i '^Subject:' /tmp/incoming_message

finds every line in the message that begins with the string `Subject:`.
The command

    	| head -1

outputs only the first of these lines. This step is a safety mechanism to ensure that messages forwarded to the alias (which in general may contain more than one `Subject:` line) are handled properly. Finally, the `awk` command

    	| awk -F: '{print $2}'

defines the colon (:) as the field separator in the record (line) and outputs the second field (the string "`Code` `Manager` `notification`" if the message was sent by Configuring). This is the value placed in the variable `SUBJECT`.

#### Extracting the User Name

The following line extracts the user name from the stored copy of the message and places its value in the script variable `USER`:

    USER =\Qegrep -i '^User:' /tmp/incoming_message \
    				head -1 | awk -F: '{print $2}' | awk '{print $1}'\Q

#### Extracting the Event

The following line extracts the event from the message and places its value in the script variable `EVENT`:

    EVENT=\Qegrep -i '^Event:' /tmp/incoming_message \

    					| head -1 | awk -F: '{print $2}'\Q

Other information can be extracted with similar commands. For example, the date can be extracted by searching for ``^Date:'`.

#### Example Script

Some of the constructs described in the last section are used in the Bourne shell script shown in Figure 21. Refer to the comments in the script for an explanation of its operation.

Configuring notification mail sent to the alias `script_alias@conundrum` is piped to the script. The script is designed to examine each message sent by Configuring in response to putback events. If the putback is related to a bug fix, group policy requires developers to name the bug with an identifying number in the comment that is included in the message. Bug ID numbers are of the form BUG-number. The script searches each message for these ID numbers and, if the numbers appear in a database file, forwards the message to interested managers.

Interested managers are identified in a database file named `bug`.`dbase`. The file is a list of ordered pairs of bug IDs and user names. For example, the entry

    	BUG-12 nod@naptime

identifies nod@naptime as the manager interested in BUG-12.

If a bug ID that is not in the bug database appears in the message, the message is forwarded for clarification to the user who performed the putback.

#### Figure 21 Example Script for Detecting Bug IDs in Mail Files.

    #!/bin/sh -
    #
    # Name: bugcheck.sh
    #	This script checks an incoming Configuring notification mail
    #	message to determine whether or not it contains bug ID numbers
    of
    #	the form BUG-<number> in the putback comments message.
    #	If it does, the bug IDs are extracted and compared
    #	to a database that contains current bugs and the mail
    #	address of the manager(s) responsible for each bug ID.
    #	If the bug ID is found in the database, the bug ID is
    #	added to the original Configuring notification message,
    #	which is then forwarded to the responsible manager(s).
    #	If the bug ID is not in the database, the message is forwarded
    #	the user who entered the comment.
    #
    #	The format of lines in the bug ID/manager list is as follows:
    #	BUG-bug_id_number manager_name@machine_name
    #
    #	The prefix "BUG-" must appear at the beginning of the bug ID.
    #	The bug ID and manager name can be separated by tabs or spaces.
    #	Only one bug ID and manager can appear on each line in the
    database,
    #	but the same bug ID or manager can appear more than once.
    # Define variables.
    BUGPREFIX=BUG-	# String prefix for bug ID.
    BDB=/home/host/bug.dbase	# Path name of bug id/manager database.
    WD=/tmp/bugcheck.dir	# Temporary working directory.
    NDB=$WD/ndb$$	# New bug database with tabs stripped.
    IM=$WD/im$$ 	# Temp file for incoming message.
    RT=$WD/rt$$ 	# Temp file for returned message.
    BF=$WD/bf$$	# Temp file of message bug IDs.
    # Create the temporary working directory.
    mkdir -p $WD
    # Store the incoming message in a temporary file.
    cat > $IM
    # Change all spaces, tabs, and punctuation (except "-") in message
    # to newlines in order to place each word in the message
    (including
    # the bug IDs) on a separate line.
    # Delete duplicates, filter for bug IDs, and store bug IDs in $BF.
    cat $IM | \
    tr	\Q\001'-'\054''\056'-'\057''\072'-'\100''\133'-'\140'
    `\173'-'\177' \Q\012' | \
    sort | uniq | grep "$BUGPREFIX" > $BF
    # Change tabs to spaces and make a copy of bug list.
    cat $BDB | tr -s \Q\011' \Q\040' > $NDB
    # If the bug IDs from the message are in the bug database,
    # construct a new SUBJECT line and send the original notification
    # message to the registered manager.
    # If a bug ID from the message is not in the bug database,
    # forward the message (with commentary) to the user
    # who executed the putback.
    for BUGID in \Qcat $BF\Q
    do
    	MGR=\Qgrep $BUGID\ $NDB | awk \Q{print $2}'\Q
    	if [ "$MGR" ] ;
    		then
    		mail -s "Configuring putback notification ($BUGID)" \
    		$MGR < $IM
    	else
    		echo " The putback comment in your message refers to" > $RT
    		echo " a bug with ID number $BUGID." >> $RT
    		echo " This bug ID is not in the active bug database." >> $RT
    		echo " Make sure you have entered the correct bug ID." >> $RT
    		echo "" >> $RT
    		echo "" >> $RT
    		echo "---------Begin Included Message---------------" >> $RT
    		cat $IM >> $RT
    		echo "" >> $RT
    		echo "" >> $RT
    		echo "---------End Included Message----------------" >> $RT
    		USER=\Qegrep -i \Q^User:' $IM \
    		 | head -1 | awk -F: \Q{print $2}' | awk \Q{print $1}'\Q
    		cat $RT | \
    		mail -s "Invalid bug ID ($BUGID) in putback comment" $USER
    	fi
    done
    # Clean up and exit
    rm -r $WD
    exit

#### Example Output

Consider a `bug`.`dbase` file that contains the following lines (note the absence of `BUG-121`).

    	BUG-12			nod@naptime

    	BUG-3456			torq@inquisition

    	BUG-6789			hoover@fbi

When this file is used with the mail message shown in Figure 20, the script sends two mail messages. The first message is mailed to nod@naptime as a result of being listed in the `bug`.`dbase` file on the same line as `BUG-12`. The second is sent to `jdoe`, the user who initiated the putback, because he mentioned `BUG-121` in his comments, which is not in the `bug`.`dbase` file.

The reference to `BUG-12` generates the message shown in Figure 22.

#### Figure 22 Mail to Interested Manager About `BUG-12`

    From jdoe Thu Jan 26 13:05 PDT 1995
    To: nod@naptime
    Subject: Configuring putback notification (BUG-12)
    Content-Type: text
    Content-Length: 532
    From jdoe Thu Jan 26 13:01 PDT 1995
    Date: Thu, 26 Jan 1995 13:01:50 +0800
    From: jdoe (Jan Doe)
    To: script_alias@conundrum
    Subject: Code Manager notification
    Event: putback-to
    Parent workspace: integrate_1
     (holymoly:/export/home/holymoly/jdoe/src/ws/integrate_1)
    Child workspace: develop_1
     (holymoly:/export/home/holymoly/jdoe/src/ws/develop_1)
    User: jdoe
    Comment:
    In my attempt to fix BUG-12, I fixed BUG-121 instead!
    Files:
    update: foo
    update: bar
    update: foobar

The reference to nonexistent `BUG-121` generates the message shown in Figure 23.

#### Figure 23 Returned Message Due to Nonexistent Bug ID

    From jdoe Thu Jan 26 13:05 PDT 1995
    To: jdoe
    Subject: Invalid bug ID (BUG-121) in putback comment
    Content-Type: text
    Content-Length: 820
     The putback comment in your message refers to
     a bug with ID number BUG-121.
     This bug ID is not in the active bug database.
     Make sure you have entered the correct bug ID.
    ------------Begin Included Message--------------------
    From jdoe Thu Jan 26 13:01 PDT 1995
    Date: Thu, 26 Jan 1995 13:01:50 +0800
    From: jdoe (Jan Doe)
    To: script_alias@conundrum
    Subject: Code Manager notification
    Event: putback-to
    Parent workspace: integrate_1
     (holymoly:/export/home/holymoly/jdoe/src/ws/integrate_1)
    Child workspace: develop_1
     (holymoly:/export/home/holymoly/jdoe/src/ws/develop_1)
    User: jdoe
    Comment:

    In my attempt to fix BUG-12, I fixed BUG-121 instead!
    Files:
    update: foo
    update: bar
    update: foobar
    ------------End Included Message----------------------