Summary - Date conversion script

From: Kathy Ange <kathyange_at_yahoo.com>
Date: Thu Aug 04 2005 - 15:39:57 EDT
I want to say thanks to John F Wall, Kalyan Manchikanti, Aaron
Lineberger, C. G. Sellers, Brad_Morrison, Crist J. Clark and Rob
Thompson, for the great answers and quick response.

They had some excellent ideas, I knew someone already had this figured
out.  Thanks it has helped me a lot.

Below are there e-mails

===============================================================
Hi,

I use PHP at the command line to do lots of these types of things, it
has a great function for dealing w/ UNIX Epoch time (seconds since Jan
1st, 1970) as well as an easy mail() function.

<?

// Current Time
$now = time();

// Time in the password file as $passexpire
$difference = $now - $passexpire;

// Now you have the number of seconds ($difference) between now and
the expiration.. you // can easily fill the code to divide by this
into hours, seconds, whatever..

?>

-Rob

===============================================================

Kathy,

Here are some ksh functions which might help.
# Define the functions we will use.

function isLeap {
# isLeap(Year)
        if (( ((($1 % 4) == 0) && (($1 % 100) != 0)) ||
                ((($1 % 400) == 0) && ( ($1 % 4000) != 0)) ))
            then
                return 0
            else
                return 1
        fi
}

function dayOfYear {
# dayOfYear (Month, Day, Year)

        integer Count
        integer Day
        integer Month
        integer Year
        integer TotalDays

        Month=$1
        Day=$2
        Year=$3

        set -A DaysInMonth 0 31 28 31 30 31 30 31 31 30 31 30 31

        if isLeap ${Year}
            then
                DaysInMonth[2]=29
        fi

        Count=1
        TotalDays=0
        while
                (( Count < Month ))
            do
                (( TotalDays += DaysInMonth[$Count] ))
                (( Count += 1 ))
            done
        (( TotalDays += Day ))
        print "${TotalDays}"
        return
}

function daysSinceEpoch {
# daysSinceEpoch (Month, Day, Year)
        integer Count
        integer Day
        integer Month
        integer Year
        integer DSE
        integer numLeaps

        Month=$1
        Day=$2
        Year=$3

        (( DSE = (Year - 1970) * 365 - 1 ))     # DSE for 1/1/1970 is
0.

        Count=1970
        numLeaps=0
        while
                (( Count < Year ))
            do
                if isLeap ${Count}
                    then
                        (( numLeaps += 1 ))
                fi
                (( Count += 1 ))
            done
        (( DSE += numLeaps ))
        (( DSE += $(dayOfYear ${Month} ${Day} ${Year}) ))
        print "${DSE}"
        return
}

John

===============================================================
Kathy,

And here is an nawk script which processes the output of the "passwd
-sa" command as you theorized.
#!/usr/bin/nawk -f
BEGIN           {
                  FMT1 = "%-12s\t%-9s\t%-10s\t%s.\n"
                  FMT2 = "%-12s\t%-9s\t%-10s\t"

                  "date '+%m %d %Y'" | getline

                  ThisMonth     = $1 + 0
                  ThisDay       = $2 + 0
                  ThisYear      = $3 + 0

                  Today = daysSinceEpoc(ThisMonth, ThisDay, ThisYear)
                }

$4 == "LK"      { printf FMT1, $1, $2, $3, "Password is locked" }

$4 == "NP"      { printf FMT1, $1, $2, $3, "NO PASSWORD" }

$4 == "PS"      { Host = $1
                  Category = $2
                  UserID = $3
                  LastDate = $5
                  if ( length(LastDate) == 0 ) {
                        printf FMT2, Host, "CustApp", UserID
                        printf "NON-EXPIRING PASSWORD.\n"
                        next
                  }
                  DaysValid = $7

                  split(LastDate, MDY, "/")

                  MDY[1] += 0
                  MDY[2] += 0
                  if (MDY[3] < 70)
                        MDY[3] += 2000
                  else
                        MDY[3] += 1900
                  PasswordReset = daysSinceEpoc(MDY[1], MDY[2], MDY[3])
                  PasswordValid = PasswordReset + DaysValid

                  DaysToExpire = PasswordValid - Today

                  printf FMT2, Host, Category, UserID
                  Plural="s"
                  if (DaysToExpire == 1)
                        Plural=""
                  if (DaysToExpire > 0)
                        printf "Password expires in %d day%s.\n",
DaysToExpire,
Plural
                  else
                        printf "ALREADY EXPIRED.\n"
                }


function isLeap(Year) {
        return (((Year % 4) == 0) && ((Year % 100) != 0)) ||
                (((Year % 400) == 0) && ((Year % 4000) !=0))
}
function daysSinceEpoc(Month, Day, Year) {
        # Compute number of days since 1/1/1970.
        DSE = (Year - 1970) * 365 - 1           # DSE for 1/1/1970 is
0.
        numLeaps = 0
        for (i=1970; i<Year; i++)
                if (isLeap(i))
                        numLeaps++
        DSE += numLeaps
        DSE += dayOfYear(Month, Day, Year)
        return (DSE)
}
function dayOfYear(Month, Day, Year) {
        # Compute the day of the year for this date.
        TotalDays = 0
        DaysInMonth[1]  = 31
        DaysInMonth[2]  = 28
        DaysInMonth[3]  = 31
        DaysInMonth[4]  = 30
        DaysInMonth[5]  = 31
        DaysInMonth[6]  = 30
        DaysInMonth[7]  = 31
        DaysInMonth[8]  = 31
        DaysInMonth[9]  = 30
        DaysInMonth[10] = 31
        DaysInMonth[11] = 30
        DaysInMonth[12] = 31

        if (isLeap(Year))
                DaysInMonth[2] = 29

        for (i=1; i<Month; i++) {
                TotalDays += DaysInMonth[i]
        }
        TotalDays += Day
        return (TotalDays)
}
John
===============================================================
Attached are two scripts that will help you in what you want to do. You
will have to tweak them to suit your environment. Remember that
passwd_expiry.ksh script needs the second script epoch.pl to exist. 
It's
better if you keep them in the same directory. Also include your email
addresses in the ADMINS variable..

hth,

Kalyan Manchikanti

===============================================================
This isn't exactly what you asked for but it is something similar that 
I
did on an AIX box. It basically calculates time in seconds since the
last password change and if that time is greater than 9 (5443200) or 12
(7257600) weeks it tells you. This should be easily modifiable to place
in cron and change the execution of echo to mail. AIX doesn't use an
/etc/shadow file explicitly (/etc/security/passwd), but you should be
able to modify the for loop to look at the /etc/shadow file as opposed
to the /etc/passwd file. If I had time I'd port it for you, but I'm 
kind
of swamped and what fun would that be for you? ;)

Questions, let me know.


#!/usr/bin/ksh

if [[ `whoami` != root ]]
   then
   print "You must be root to run this script."
   exit
fi

USRCHG=`perl -e "use Time::Local; print time-5443200;"`
ADMCHG=`perl -e "use Time::Local; print time-7257600;"`
DATE=`perl -e "use Time::Local; print time;"`
USRDAT=`perl -e "use Time::Local; print scalar
localtime(time-5443200);"`
ADMDAT=`perl -e "use Time::Local; print scalar
localtime(time-7257600);"`

if [ "$1" = "" ]
then
   for user in `cat /etc/passwd | egrep -v
"^root:|^daemon:|^bin:|^sys:|^adm:|^uucp:|^nobo
dy:|^lpd:|^invscout:|^imnadm:|^nuucp:|^ipsec:|^kmem:" | awk -F: '{print
$1}'`
   do
      grep -p lastupdate /etc/security/passwd | grep -p ^$user: >
/dev/null
      if [ $? -eq 0 ]
      then
         LAST=`pwdadm -q $user | grep last | awk '{print $3}'`
         LSTDAT=`perl -e "use Time::Local; print scalar
localtime($LAST);"`
         if (( $LAST < $USRCHG ))
         then
            if (( $LAST < $ADMCHG ))
            then
               echo "$user:      \tRequires Admin To Change."
               echo "Last Change:\t$LSTDAT"
               echo "12 Weeks:   \t$ADMDAT\n"
            else
               echo "$user:      \tRequires User To Change."
               echo "Last Change:\t$LSTDAT"
               echo "9 Weeks:    \t$USRDAT\n"
            fi
         else
            echo "$user:      \tNo Change Required."
            echo "Last Change:\t$LSTDAT\n"
         fi
      else
        echo "$user:      \tDoes not have a \"lastupdate\" entry!\n"
      fi
   done
else
   user="$1"
   grep -p lastupdate /etc/security/passwd | grep -p ^$user: > 
/dev/null
   if [ $? -eq 0 ]
   then
      LAST=`pwdadm -q $user | grep last | awk '{print $3}'`
      LSTDAT=`perl -e "use Time::Local; print scalar 
localtime($LAST);"`
      if (( $LAST < $USRCHG ))
      then
         if (( $LAST < $ADMCHG ))
         then
            echo "$user:      \tRequires Admin To Change."
            echo "Last Change:\t$LSTDAT"
            echo "12 Weeks:   \t$ADMDAT\n"
         else
            echo "$user:      \tRequires User To Change."
            echo "Last Change:\t$LSTDAT"
            echo "9 Weeks:    \t$USRDAT\n"
         fi
      else
         echo "$user:      \tNo Change Required."
         echo "Last Change:\t$LSTDAT\n"
      fi
   else
     echo "$user:      \tDoes not have a \"lastupdate\" entry!\n"
   fi
fi


Aaron Lineberger

===============================================================
epoch to local should do it

for example, perl has a good way to do this

::::::::::::::
epoch2local.pl
::::::::::::::
#!/usr/bin/perl
#
# $1 = epoch time in format of shadowExpireA
$input = $ARGV[0];
$e = ($input*24*60*60);
print scalar localtime ($e) ;
print "\n\n ";

Google converting epoch to local time and you will get more help...

Sellers


===============================================================
You have the right idea, what you need is a tool that provides a
library for conversion to/from UNIX "epoch time". 

I don't think any of the shells will do it. Perl might, and it's
probably already on your system. You may need to get/install a date
conversion library. 

I'm surprised that there's no built-in mechanism to notify users. 
Brad Morrison - CONBRAM


===============================================================
It's probably easier to get the UNIX epoch time, seconds since January
1, 1970, which is what the computer counts internally anyway, and 
convert
that to days. An easy Perl script,

	open(SHADOW, '/etc/shadow') || die("failed to open /etc/shadow\n");

	$today = time() / 86400; # Today's date.
	while (<SHADOW>) {
		@pw = split(/:/);
		$lastchg = $pw[2]; # Date of last change.
		$max = $pw[4]; # Expiration timer.
		$warn = $pw[5]; # Warning period.
		# Calculate days until expiration.
		$expire = $max - ($today - $lastchg);
		# Check if we are in the warning period. If so, mail user.
		if ($expire < $warn) {
			# Insert code for message to user here.
		}
		# If less than three days, warn the administrator.
		if ($expire < 3) {
			# Insert code for message to admin here.
		}
	}
-- 
Crist J. Clark     


Below is my original question
===============================================================
I feel like this is probably an easy question, so I have been searching
the internet for an answer, but just can t figure this out myself. 

My question simply stated is, I want to be able to e-mail a person
outside of the unix server, when a unix id is about to expire.  Also if
the password will expire within 3 days I want to e-mail the system
administrator. Yes if the user is logged on the person will see the
warning message, but some IDs aren't logged on daily

In the /etc/shadow file the 3rd field is the number of days (since
January 1, 1970) since the password was last changed.  I am looking for
a way to take today date and display as the number of days since
January 1, 1970 and then compare to two numbers.  If the numbers are
within the password warning time frame then send the appropriate e-mail


Another thought was to use the date from passwd  s where the date is
displayed as mm/dd/yy, convert to a Julian date do the calculations
then convert back to gregorian 
corn: root: #passwd -s rnott 
rnott     PS    07/27/05     7    63     7

I am on Sun Solaris 9,



Kathy Ange
Virginia Department of Agriculture & Consumer Services
Information Systems
(804) 371-5793 Voice Mail
(804) 371-5282  FAX
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
#!/bin/ksh
#Author:Kalyan Manchikanti
#C:Date:02/08/2005
#Check the Shadow table for the epoch value and warn the users of password expiry
#This script needs the epoch.pl script to exist

ID=`/usr/bin/id | /usr/bin/cut -d" " -f1`
if [[ "${ID}" != "uid=0(root)" ]]
then
   echo "You should run as root"
   exit 1
fi

SHADOW=/etc/shadow
#Location of the epoch.pl script. Change it to wherever you are going to keep the epoch.pl script..
ESCPT=/home/kmanchi/bin/epoch.pl
HOSTNAME=`hostname`
#Email addresses of the admins / users needing the  notification
#ADMINS=""

for i in `cat $SHADOW`
do
LGN=`echo $i |awk -F: '{print \$1}'`
MAXDAYS=`echo $i | awk -F: '{print \$5}'`
echo "$MAXDAYS"
EPOCH=`echo $i |awk -F: '{print \$3}'`
EVAL=`$ESCPT $EPOCH | awk '{print \$2}'`
#echo "$EVAL"
		 if [[ $EVAL == `expr $MAXDAYS - 7` ]]
		 then
		 echo "Password for unix user $LGN on `hostname` is going to expire in a week. Please change it ASAP" | mailx -s 'password expiry' $ADMINS
		 elif [[ $EVAL == `expr $MAXDAYS - 6` ]]
		 then
		 echo "Password for unix user $LGN on `hostname` is going to expire in 6 days. Please change it ASAP" |  mailx -s 'password expiry' $ADMINS		 
		 elif [[ $EVAL == `expr $MAXDAYS - 5` ]]
		 then
		 echo "Password for unix user $LGN on `hostname` is going to expire in 5 days. Please change it ASAP" |  mailx -s 'password expiry' $ADMINS		 		 
		 elif [[ $EVAL == `expr $MAXDAYS - 4` ]]
		 then
		 echo "Password for unix user $LGN on `hostname` is going to expire in 4 days. Please change it ASAP" |  mailx -s 'password expiry' $ADMINS		 		 
		 elif [[ $EVAL == `expr $MAXDAYS - 3` ]]
		 then
		 echo "Password for unix user $LGN on `hostname` is going to expire in 3 days. Please change it ASAP" |  mailx -s 'password expiry' $ADMINS		 		 
		 elif [[ $EVAL == `expr $MAXDAYS - 2` ]]
		 then
		 echo "Password for unix user $LGN on `hostname` is going to expire in 2 days. Please change it ASAP" |  mailx -s 'password expiry' $ADMINS		 		 
		 elif [[ $EVAL == `expr $MAXDAYS - 1` ]]
		 then
		 echo "Password for unix user $LGN on `hostname` is going to expire in 1 day. Please change it ASAP" |  mailx -s 'password expiry' $ADMINS		 		 
		 elif [[ $EVAL == "$MAXDAYS" ]]
		 then
		 echo "PASSWORD FOR USER $LGN HAS EXPIRED.PLEASE CHANGE IT ASAP TO AVOID JOBS FAILING"
		 fi
done
#!/bin/perl -w

use integer;


if ($#ARGV != 0) {
    print "Usage: epoch.pl <number>\n";
    exit 1;
}

$input_day=$ARGV[0];
if ($input_day =~ /(\D+)/) {
    print "ERROR: Please enter a number!!!\n";
    exit 1;
}

$clktime=time;

$curr_day=$clktime/86400;

$diff=$curr_day - $input_day;

if ($diff < 0) {
    $diff=-1*$diff;
    print "$input_day: $diff days from current day\n";
}
else {
    print "$input_day: $diff days to current day\n";
}
_______________________________________________
sunmanagers mailing list
sunmanagers@sunmanagers.org
http://www.sunmanagers.org/mailman/listinfo/sunmanagers
Received on Thu Aug 4 15:40:27 2005

This archive was generated by hypermail 2.1.8 : Thu Mar 03 2016 - 06:43:50 EST