Cover V05, I05
Article
Listing 1
Sidebar 1
Sidebar 2

may96.tar


SelectNews.pl: Perl Script for Selective News Delivery

Art D'Adamo

You can use UNIX mail to send a message to a particular user. You can use UNIX news to send a message to all users. But what about when you'd like to send a message to a select group of users, for example, to everyone in accounting or programming? SelectNews.pl is a perl script that does just that.

SelectNews.pl is modeled on the UNIX news program. It doesn't replace news, however, but supplements it. Like news, SelectNews.pl shows the user all the news they haven't already seen. A user sees a particular message file only once, then it is "old news" and not displayed again.

Background

news is a UNIX utility that has two parts. The first part is news creation, which happens when a systems administrator, or any other authorized user, creates a news item in the form of an text file and copies it into a directory, (/usr/news on an HP-UX system).

The second part is news reading, which happens when a user runs the news program (which for HP-UX is /usr/bin/news). The news program is typically run when the user logs in, as part of the systemwide /etc/profile file, or perhaps as part of their Korn shell .profile file.

How does /usr/bin/news work? First, it checks the date and time of .news_time, a file in the user's home directory. It's typical for a configuration file (like .news_time) to have a name that starts with a period. The period prevents some versions of the ls command from displaying the file, although a ls -a will display it. The logic is, I suppose, that a user listing files usually isn't interested in seeing configuration files, too.

The .news_time configuration file is unusual in that it has zero bytes; its only purpose is to provide a time, ctime to be specific. Like all UNIX files, .news_time has not one but three times associated with it: atime, the time it was last read; ctime, the time its inode information (permissions, owner, group, etc.) was last changed; and mtime, the time it was last written to. (By the way, mtime is sometimes mistakenly called the time of file creation. It isn't. UNIX doesn't store the time a file was created.) Of the three times, news uses ctime.

Once /usr/bin/news knows ctime, it displays all the files in directory /usr/news that have a more recent mtime. After the files are displayed, news updates the user's .news_time file, so that it knows what files to display next time.

Now for SelectNews.pl.

SelectNews.pl is similar to news. For example, SelectNews.pl reads the mtime of a file (named .SelectNews.pl) in the user's directory. Then like news, SelectNews.pl displays all the files with a newer mtime. However, instead of reading the news from just one directory, SelectNews.pl has many directories to read news from. It selects the directory (or directories) based on the user's login name.

SelectNews.pl looks in the appropriate directory(s) and displays all the news that is newer than the user's .SelectNews.pl file. Then, like news, it updates the time of .SelectNews.pl so it knows which files to display next time.

The ability to place a user in more than one SelectNews group is useful. For example, you may want to put a programmer who works at the Anytown branch office in both the Programmer group and the Anytown group, because sometimes you need to send a message to all the programmers, while other times you need to send a message to everyone at the branch office.

To handle multiple news directories, SelectNews.pl uses a configuration file, called /etc/SelectNews. Each line of /etc/SelectNews has the same form: a SelectNews directory and then one or more Perl regular expressions. Here's an example:

/u1/SelectNews/Operators   ^O[0-9][0-9]$   ^ajd$
/u1/SelectNews/Programmers ^P[0-9][0-9]$   ^ajd$
/u1/SelectNews/Anytown     ^O0[1-5]$   ^P[012][0-9]$   ^S[0-9][0-9]$

This /etc/SelectNews file says show user O34 the news in /u1/SelectNews/Operators, show user P45 the news in /u1/SelectNews/Programmers, and show user ajd the news in both directories. News in /u1/SelectNews/Anytown is shown to O02, O05, P00, P29, S00 and S99, but not O06, P30, or SAB.

These nontypical login names are a holdover from the Wang computer that our HP replaced. A lot of our in-house applications determine permissions from login name, so the names had to stay. Unfortunately, they cause a problem when logging in over a serial line. Refer to the sidebar "Logging in with Nontypical Names."

There are a few things to notice about the configuration file /etc/SelectNews. First, spaces and tabs (i.e., whitespace) are used as delimiters. Second, a user can be in one or more lines (and therefore see the news that's in one or more directories). Finally, and more importantly, Perl regular expessions are used, not shell regular expressions.

SelectNews.pl's use of Perl regular expressions is perhaps its biggest stumbling block. It's very easy to forget, use a shell regular expression, and get unexpected results. For example, a* as a regular expession means something quite different to Perl than it means to the shell. (Refer to the sidebar "Perl Regular Expressions" for more details.)

With all that background, understanding SelectNews.pl is straightforward. Here is the algorithm.

1. When a user logs in, a line in a system login file, /etc/profile or, perhaps, his or her private login file, calls SelectNews.pl.

2. Function GetLoginName determines the user's login name,.

3. Function GetBaseTime gets the time it last ran for this user, which is stored in the ctime of .SelectNews.pl, a file in the user's home directory.

4. Function SetNewsDirs makes a list of all directories that have news for the user. It finds the directories by looking in /etc/SelectNews. After it has the directories, it checks for and deletes duplicates.

5. For each directory, function MakeDisplayFile concatenates all files that are more recent than the time determined in Step 3 into a concatenation output file. The file is created in /tmp and has the user's PID as part of its name, to ensure uniqueness.

6. Function ShowDisplayFile displays the concatenated output file, using the UNIX pg command. If your system doesn't have pg, modify the "$DisplayCmd = ..." line, which is the first executable line of SelectNews.pl, to call some other display program.

7. Function UpdateDotFileTime updates the time of the user's .SelectNews.pl file. It also deletes the concatenated output file.

Implementation

The Initialize and GetLoginName functions are straightforward. The GetBaseTime function creates a .SelectNews.pl file for the user, if one doesn't already exist, and then reads that file's ctime. The SetNewsDirs function examines the /etc/SelectNews file, picking out the directories that may have news for this user. It exits if it finds no directories.

SetNewsDirs has a line:

if( $LoginName =~ /$NameRegExp/ ) {

that compares the user's login name to the Perl regular expression from /etc/SelectNews. If you'd rather not use Perl regular expressions and use literal login names instead, change this line to:

if( $LoginName eq $NameRegExp ) {

With this change, /etc/SelectNews would use literal login names, rather than Perl regular expressions. This approach would work on small systems. On my system, however, the /etc/passwd file has more than 1,000 entries, so Perl regular expressions are definitely the way to go.

The MakeDisplayFile gets all the recent news files in the user's directory(s) and concatenates them into one big file, which is displayed by ShowDisplayFile. It uses the UNIX function defined by $DisplayCmd, which is the first executable line of SelectNews.pl. Systems that don't have the UNIX pg command may have to change $DisplayCmd to point to more, less, or some other paging command. The UpdateDotFileTime function updates the time of the user's .SelectNews.pl file for next time.

Another implementation feature is that debugging print statements have been left in SelectNews.pl, although they're commented out. Uncomment them if you want to see how SelectNews.pl works in more detail.

Now that you've seen how SelectNews.pl works, and how to configure /etc/SelectNews, you should have no trouble getting SelectNews.pl to work for you. With a small investment in setup time, SelectNews.pl can help improve communication within your company in a big way.

About the Author

Art D'Adamo has been working with computers professionally since 1980. He began as a scientific programmer using FORTRAN, on an IBM mainframe and then a VAX. Later, he did image processing in C on a Sun 480 and became the default parttime systems administrator. For the past two years he has been a full-time adminstrator for a HP T500 with about 300 users, 2 Gb of RAM, and over 120 Gb of disk. Art can be reached at dadamo@voicenet.com. Any improved versions of SelectNews.pl will be available at http://www.voicenet.com/~dadamo.