Listing 1: pwexp.pl

#! perl
eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
& eval 'exec perl -S $0 $argv:q'
if 0;

#
# pwexp.pl - PERL program to check for password expiration times
#
#

#
# get the passwd file entry for this account.  $< is the numerical
# representation of our REAL UID
#
( $username, $passwd, $uid, $gid, $pwage, 
  $comment, $gcos, $dir, $shell ) = getpwuid($<);
#
# If passwd aging value is defined
#
if ( $pwage ne "" )
   {
   #
   # extract the maxweeks value
   #
   $maxweeks = &a64l( substr( $pwage, 0, 1 ) );
   #
   # extract the minweeks value
   #
   $minweeks = &a64l( substr( $pwage, 1, 1 ) );
   #
   # extract the last changed value
   #
   $lastchange = &a64l( substr( $pwage, 2 ) );
   #
   # what is NOW?
   #
   $now = time / 604800;
   #
   # If maxweeks < minweeks, the user can't change his passwd
   #
   if ( $maxweeks < $minweeks )
          {
          printf "You cannot change your password.  Ever. \n";
          }
   #
   # The special case where the password must be changed
   #
   elsif ( ( $minweeks == 0 ) && ( $maxweeks == 0 ) )
          {
          printf "You must change your password.  Now.\n";
          }
   #
   # if lastchanged is > now, then expired
   # if now > lastchanged + maxweeks, then expired
   #
   elsif ( $lastchange > $now  || 
                 ( $now > $lastchange + $maxweeks ) && 
                 ( $maxweeks > $minweeks ) )
          {
          printf "Your password has expired.\n";
          }
   #
   # tell the user when his password expires
   #
   else
          {
          printf "Your password expires in %d weeks.\n", 
                 $lastchange + $maxweeks - $now;
          printf "Please start thinking of a new one.\n";
          }
   }
else
   {
   printf "Password aging is not enabled.\n";
   }
exit(0);

#
# the a64l routine was written by Randall Schwartz after a call for help 
# in the comp.lng.perl newsgroup.  Thanks Randall!
#
sub a64l {
        local($_) = @_; # arg into $_

        die "a64l: illegal value: $_" unless m#^[./0-9A-Za-z]{0,6}$#;
        unless (defined %a64map) {
                @a64map{'.','/',0..9,'A'..'Z','a'..'z'} = 0..63;
        }
        local($result) = 0;
        for (reverse split(//)) {
                $result *= 64;
                $result += $a64map{$_};
        }
        $result;
}
