initial import.
darcs-hash:20000522214025-92525-03a24257a5b15606c91a9135e08692e671d5a0fd.gz
This commit is contained in:
parent
53e27f3168
commit
7dfc99c69c
1 changed files with 215 additions and 0 deletions
215
wwho.py
Executable file
215
wwho.py
Executable file
|
@ -0,0 +1,215 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# when-who, Sam K (2000)
|
||||||
|
|
||||||
|
import os,string,getopt,time,sys,struct
|
||||||
|
""" usage : wwho [date] [-b secs (backwards)] [-p precision (sec/m/h/d)] [-l (last)]
|
||||||
|
[-a (all last msgs)] [-f wtmp_file] [-d (debug)]
|
||||||
|
DATE (2000 May 22 06:12:08)
|
||||||
|
"""
|
||||||
|
optlist, args = getopt.getopt(sys.argv[1:], "adlb:p:f:")
|
||||||
|
|
||||||
|
date=""
|
||||||
|
emul_last=0
|
||||||
|
all_last=0
|
||||||
|
debug=0
|
||||||
|
datesec=0
|
||||||
|
precision=2
|
||||||
|
utmpF="/var/log/wtmp"
|
||||||
|
if len(args)>0 :
|
||||||
|
date=args[0]
|
||||||
|
print "cmd_line_date : %s" %date
|
||||||
|
for i in optlist :
|
||||||
|
if i[0] =='-l' : emul_last=1
|
||||||
|
if i[0] =='-a' : all_last=1
|
||||||
|
if i[0] =='-d' : debug=1
|
||||||
|
if i[0] =='-b' : datesec=time.time()-float(i[1])
|
||||||
|
if i[0] =='-p' : precision=float(i[1])
|
||||||
|
if i[0] =='-f' : utmpF=i[1]
|
||||||
|
if debug : print "Option found : "+repr(i)
|
||||||
|
if not datesec :
|
||||||
|
if date :
|
||||||
|
t=time.strptime(date,"%Y %b %d %H:%M:%S")
|
||||||
|
#we still have to guess the DaylightSsavingTime flag -> -1
|
||||||
|
t2=[ t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],-1]
|
||||||
|
datesec = time.mktime(t2)
|
||||||
|
else : datesec =time.time()
|
||||||
|
|
||||||
|
def unpackstr(s, i=0):
|
||||||
|
for c in s:
|
||||||
|
if c == '\000': break
|
||||||
|
i = i + 1
|
||||||
|
return s[:i]
|
||||||
|
|
||||||
|
def msectime(secs,usecs) :
|
||||||
|
t=time.localtime(secs)
|
||||||
|
s=time.strftime("%d %b %Y %T",t)
|
||||||
|
s=s+ ( ".%06d"%usecs )[0:4]
|
||||||
|
#s=s+ time.strftime(" %z %Z",time.localtime(secs))
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
if debug : print " Date : %s // datesec : "% date + repr(datesec)
|
||||||
|
print "Finding who were here at %s, with precision %fs."\
|
||||||
|
% (msectime(datesec,0),precision)
|
||||||
|
|
||||||
|
# the C struct declaration (on AIX 4.2.1)
|
||||||
|
# char ut_user[8];
|
||||||
|
# char ut_id[14];
|
||||||
|
# char ut_line[12];
|
||||||
|
# short ut_type;
|
||||||
|
# pid_t ut_pid; (int)
|
||||||
|
# short ut_exit.e_termination;
|
||||||
|
# short ut_exit.e_exit;
|
||||||
|
# time_t ut_time; (long)
|
||||||
|
# char ut_host[16];
|
||||||
|
# the format string to represent that structure
|
||||||
|
|
||||||
|
""" cf utmp.h , ou man utmp :
|
||||||
|
#define UT_LINESIZE 32
|
||||||
|
#define UT_NAMESIZE 32
|
||||||
|
#define UT_HOSTSIZE 256
|
||||||
|
|
||||||
|
/* The structure describing the status of a terminated process. This
|
||||||
|
type is used in `struct utmp' below. */
|
||||||
|
struct exit_status
|
||||||
|
{
|
||||||
|
short int e_termination; /* Process termination status. */
|
||||||
|
short int e_exit; /* Process exit status. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The structure describing an entry in the user accounting database. */
|
||||||
|
struct utmp
|
||||||
|
{
|
||||||
|
short int ut_type; /* Type of login. */
|
||||||
|
pid_t ut_pid; /* Process ID of login process. */
|
||||||
|
char ut_line[UT_LINESIZE=32]; /* Devicename. */
|
||||||
|
char ut_id[4]; /* Inittab ID. */
|
||||||
|
char ut_user[UT_NAMESIZE=32]; /* Username. */
|
||||||
|
char ut_host[UT_HOSTSIZE=256]; /* Hostname for remote login. */
|
||||||
|
struct exit_status ut_exit; /* Exit status of a process marked
|
||||||
|
as DEAD_PROCESS. */
|
||||||
|
long int ut_session; /* Session ID, used for windowing. */
|
||||||
|
struct timeval ut_tv; /* Time entry was made. */
|
||||||
|
int32_t ut_addr_v6[4]; /* Internet address of remote host. */
|
||||||
|
char __unused[20]; /* Reserved for future use. */
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
fmt="hi32s4s32s256shhlii4i20s"
|
||||||
|
#fmt="2s4s32s4s32s256s4s8s8s16s20s"
|
||||||
|
|
||||||
|
""" constants (for ut_type):
|
||||||
|
"""
|
||||||
|
UT_EMPTY = 0
|
||||||
|
UT_RUN_LVL = 1
|
||||||
|
UT_BOOT_TIME = 2
|
||||||
|
UT_NEW_TIME = 3
|
||||||
|
UT_OLD_TIME = 4
|
||||||
|
UT_INIT_PROCESS = 5
|
||||||
|
UT_LOGIN_PROCESS = 6
|
||||||
|
UT_USER_PROCESS = 7
|
||||||
|
UT_DEAD_PROCESS = 8
|
||||||
|
UT_ACCOUNTING = 9
|
||||||
|
record_size = struct.calcsize(fmt)
|
||||||
|
# read who is logged on to a UNIX system
|
||||||
|
file = open(utmpF, 'rb')
|
||||||
|
|
||||||
|
sessions={}
|
||||||
|
suspects=[]
|
||||||
|
|
||||||
|
def evdisp(event,zt,rev) :
|
||||||
|
( ut_t,ut_ut,zt_t,zt_ut,u,l,h,p,id,typ) =event
|
||||||
|
if not zt :
|
||||||
|
if zt_t: zt=msectime(zt_t,zt_ut)
|
||||||
|
else : zt=" -stillNow-"
|
||||||
|
if rev :
|
||||||
|
t=zt;
|
||||||
|
zt=msectime(ut_t,ut_ut)
|
||||||
|
else :
|
||||||
|
t=msectime(ut_t,ut_ut)
|
||||||
|
return '%-8s %-8s %d/%-2d/%-6d %-4s [%-24s]=>[%-24s] (%s)' % \
|
||||||
|
(u, l, typ,1,p, id, t, zt, h)
|
||||||
|
|
||||||
|
def rewind(sessions,n,criter,event) :
|
||||||
|
i=n
|
||||||
|
( ut_time,ut_utime,zt_time,zt_utime,user,line,host,pid,sessid,type) =event
|
||||||
|
i0=1
|
||||||
|
while i>i0 :
|
||||||
|
i=i-1
|
||||||
|
closethis=0
|
||||||
|
if criter=='all' :
|
||||||
|
closethis=1
|
||||||
|
if criter =='line':
|
||||||
|
closethis=(sessions[i][5] == line)
|
||||||
|
if closethis : i0=i
|
||||||
|
|
||||||
|
if closethis :
|
||||||
|
( ut_t,ut_ut,zt_t,zt_ut,u,l,h,p,id,typ)=ev=sessions[i]
|
||||||
|
if zt_t !=0 :
|
||||||
|
if criter=='all' : continue
|
||||||
|
if all_last :
|
||||||
|
s="-ERR: "
|
||||||
|
s=s+evdisp(ev,"",1)
|
||||||
|
else :
|
||||||
|
ev=sessions[i]=( ut_t,ut_ut,ut_time,ut_utime,u,l,h,p,id,typ)
|
||||||
|
if all_last :
|
||||||
|
s="-CLOS "
|
||||||
|
s=s+evdisp(ev,"",1)
|
||||||
|
if all_last :
|
||||||
|
print s
|
||||||
|
|
||||||
|
block = file.read(record_size)
|
||||||
|
n=1
|
||||||
|
while block:
|
||||||
|
( type,pid,line,id,user,host,exit_1,exit_2,ut_session,ut_time,ut_utime,\
|
||||||
|
ip1,ip2,ip3,ip4,unused) = \
|
||||||
|
struct.unpack(fmt, block)
|
||||||
|
user = unpackstr(user) # remove the null characters
|
||||||
|
line = unpackstr(line)
|
||||||
|
host = unpackstr(host)
|
||||||
|
id = unpackstr(id)
|
||||||
|
|
||||||
|
event = ( ut_time,ut_utime,0,0,user,line,host,pid,id,type)
|
||||||
|
|
||||||
|
if type and all_last :
|
||||||
|
s='USER: '
|
||||||
|
s=s+evdisp(event," -n/a-",0)
|
||||||
|
print s
|
||||||
|
if user in ['LOGIN','reboot','shutdown'] :
|
||||||
|
"Crash & such : everybody logs off.."
|
||||||
|
rewind(sessions,n,'all',event)
|
||||||
|
|
||||||
|
if type == 7 and user :
|
||||||
|
sessions[n]=event
|
||||||
|
n=n+1
|
||||||
|
|
||||||
|
if type == 8 :
|
||||||
|
rewind(sessions,n,'line',event)
|
||||||
|
|
||||||
|
block=file.read(record_size)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
print "Number of entries : %d" %n
|
||||||
|
|
||||||
|
evs=sessions.values()
|
||||||
|
evs.sort(lambda x, y: cmp(y[0]+y[1]*1e-7,x[0]+x[1]*1e-7) )
|
||||||
|
i=0
|
||||||
|
for ev in evs:
|
||||||
|
i=i+1
|
||||||
|
(ut_t,ut_ut,zt_t,zt_ut,u,l,h,p,id,typ)=ev
|
||||||
|
if emul_last : print evdisp(ev,"",0)
|
||||||
|
if datesec <360000 :
|
||||||
|
# secret feature : giving a near-epoch date does that :
|
||||||
|
if precision >0 and zt_t-ut_t < precision : continue
|
||||||
|
if precision <0 and zt_t-ut_t > -precision : continue
|
||||||
|
else :
|
||||||
|
if datesec + precision < ut_t : continue
|
||||||
|
if zt_t !=0 and zt_t + precision <datesec : continue
|
||||||
|
if emul_last : print "----SUSPECT"
|
||||||
|
suspects.append(ev)
|
||||||
|
|
||||||
|
print "\nAnd Now the \"suspects\" :"
|
||||||
|
|
||||||
|
suspects.sort(lambda x, y: cmp(x[2]-x[0], y[2]-y[0]))
|
||||||
|
for ev in suspects :
|
||||||
|
(ut_t,ut_ut,zt_t,zt_ut,u,l,h,p,id,typ)=ev
|
||||||
|
print evdisp(ev,"",0)
|
Loading…
Add table
Add a link
Reference in a new issue