Listing 1: Source code for SelectNews.pl 

#!/usr/local/bin/perl

# /u1/perl/SelectNews.pl		2 feb 1996

# @(#) SelectNews.pl shows the user news based on who the user is.
#      It's not meant to replace the Unix news command, but rather
#      to be run in addition to it.

# Associated files:
#    1. /etc/SelectNews has lines of the form
#	    directory user user user ...
#       where directory is where the news for this group of users is kept
#       and user is a Perl regular expression for a class of
#       user login names. For example,
#	  /u1/SelectNews/Operators       ^O[0-9][0-9]$    ^ajd$
#           /u1/SelectNews/Programmers  ^P[0-9][0-9]$     ^ajd$
#       says show user ajd and users like O12 and O34 the news in
#	/u1/SelectNews/Operators, and show user ajd and users like P34
#	and P95 the news in /u1/SelectNews/Programmers.
#       (note: the same user can appear on multiple lines.)
#    2. Each user gets a file named .SelectNews.pl in their home directory.
#       (If it doesn't already exist, SelectNews.pl creates it.) The file
#       is used to record the time the news was last displayed by SelectNews.pl

# Note: /etc/SelectNews uses Perl regular expressions, not Shell regular
#       expressions!

# Author: Art D'Adamo, dadamo@voicenet.com, BISYS Plan Services (215)-542-2522
#         Look for corrections/updated versions at http://www.voicenet.com/~dadamo

# Set the display commands. This version uses 'pg'. Systems that don't
# have 'pg' may need to use 'more'
$DisplayCmd = "/usr/bin/pg -p \"pg: q to exit > \" ";

&Initialize;

$LoginName = &GetLoginName;  # gets user's login name

$BaseTime = &GetBaseTime;   # get base time from this user's .SelectNews.pl

&SetNewsDirs;  # make list of news directory(s) for this user

# make list of news files to be displayed
foreach $Dir ( @NewsDir ) { &MakeDisplayFile( $Dir ); }

&ShowDisplayFile;  # display the news

&UpdateDotFileTime;   # update $DotFile time

exit;

#------------------------------- functions --------------------------------
sub Initialize {
  $RealUID = $<;	# get user's real UID
  $HomeDir = $ENV{"HOME"};
  $DotFile = $HomeDir . "/" . ".SelectNews.pl"; # has time of last news showing
  $TimeOfDay = $^T;
  # print " - UID: $RealUID, dir: $HomeDir, dot: $DotFile, time: $TimeOfDay\n";
  $ClearCmd = "/usr/bin/clear";
  $Date = `/bin/date \"+%A, %d %b %Y\"`;  chop($Date);
  $Host1 = `/bin/uname -a`;  ($p0,$Host) = split(/ +/,$Host1);
  $DirUserList = "/etc/SelectNews";  # system-wide list of users & news dirs.
  $Pid = getppid;  $DisplayFile = "/tmp/SelectNews.pl.$Pid";
  system("/bin/rm -f $DisplayFile");
  $ShowDisplayFile = 0;
  1;  # set return value
}

sub GetLoginName {
  # get and return login name of this real UID
  local($LogName);   $LogName = "";  local($NotFound);  $NotFound = 1;
  open(PASSWD, "/etc/passwd") || die " - Can't open /etc/passwd";
  while( ($Line = <PASSWD>) && $NotFound ) {
    chop;   ($login,$passwd,$uid) = split(/:/,$Line);
    # printf "RealUID: $RealUID, login: $login, passwd: $passwd, uid: $uid\n";
    if( $RealUID eq $uid ) { $LogName = $login; $NotFound = 0; }
  }
  close(PASSWD);
  if( "" eq $LogName ) { die " - Can't determine login name"; }
  # printf " - LoginName: [$LogName]\n";
  $LogName;  # set return value
}

sub GetBaseTime {
  # get base time
  local($RetVal);
  # create .SelectNews.pl if necessary.
  unless ( -e $DotFile ) {
    $Cmd = "/bin/touch -t 197001010101 $DotFile";
    system($Cmd) && die "(1) Command [$Cmd] failed.";
    # print " - created $DotFile\n";
  }
  # get base time from this user's .SelectNews.pl
  ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
      $atime,$mtime,$ctime,$blksize,$blocks) = stat($DotFile);
  $RetVal = $atime;   # print " - BaseTime: $RetVal []\n";
  $RetVal;  # set return value
}

sub SetNewsDirs {
  # make list of all news directory(s) for this user
  open(DUL,$DirUserList) ||
	die " - SelectNews.pl fatal error: Couldn't open [$DirUserList]";
  @NewsDir = "";   $NewsDirCount = 0;
  while( <DUL> ) {
    @Line = split(/\s+/,$_);  # printf "[@Line]\n";
    $Dir = shift(@Line);      # printf "{$Dir}\n";
    while( ($NameRegExp = shift(@Line) ) ) {
      # printf " NameRegExp: {$NameRegExp} - ";
      if( $LoginName =~ /$NameRegExp/ ) {
        # printf "<$LoginName> ";
        $NewsDir[$NewsDirCount++] = $Dir;
      }
      # printf "\n";
    }
  }
  close(DUL);
  # printf "$NewsDirCount, [@NewsDir]\n";
  if( $NewsDirCount < 1 ) { exit; }  # no news directories, so exit
  # remove any duplicates from @NewsDir
  @TempDir = sort @NewsDir;  @NewsDir = "";
  $LastDir = "";  $DirCount = 0;
  foreach $Dir ( @TempDir ) {
    if( $Dir ne $LastDir ) { $NewsDir[$DirCount++] = $Dir; }
    $LastDir = $Dir;
  }
  # printf " - {@NewsDir}\n";
  1;  # set return value
}

sub MakeDisplayFile {
  # concatenate news files to be displayed into one display file
  local($ThisDir);  $ThisDir=$_[0];
  opendir(DIR,$ThisDir) || die "Could open [$ThisDir]";
  while( $aFile = readdir(DIR) ) {
    $NewsFile = $ThisDir . "/" . $aFile;
    unless( -T $NewsFile ) { next; }
    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
        $atime,$mtime,$ctime,$blksize,$blocks) = stat($NewsFile);
    # print "NewsFile: $NewsFile, atime: $atime\n";
    if( $mtime > $BaseTime ) {
      # add this file to display list
      $Cmd = "/bin/cat $NewsFile >> $DisplayFile"; system($Cmd);
      $ShowDisplayFile = 1;
    }
  }
  1;  # set return value
}

sub ShowDisplayFile {
  # display file; get prompt before exiting
  $DisplayCmd = $DisplayCmd . " $DisplayFile";
  # print "$DisplayCmd"; exit;
  if( $ShowDisplayFile ) {
    # print " - DisplayCmd: $DisplayCmd\n";
    print " - Select News for $Host on $Date \n";
    system($DisplayCmd); # && die " - problem displaying Select News";
    print "\n - End of Select News for $Host on $Date \n";
    print " - press ENTER key to continue\n";
    $Continue = <STDIN>;
  }
  1;  # set return value
}

sub UpdateDotFileTime {
  # update time of user's .SelectNews.pl before exiting
  $Cmd = "/bin/touch $DotFile";
  system($Cmd) && die "(2) Command [$Cmd] failed.";
  system("/bin/rm -f $DisplayFile");  # remove the display file
  1;   # set return value
}

#end of file
 

