scripts/wwho.py
Vincent Le Gallic c039058708 Enregistrement des droits d'exécution. Aucune vraie modif.
Darcs n'enregistrait pas les permissions des fichiers.
2013-01-31 05:36:25 +01:00

231 lines
6.8 KiB
Python
Executable file

#! /usr/bin/env python
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)
wfile : idem, except : [-a (access)] FILE
ça marche. mais la recherche ds le wtmp pour construire _sessions_ est
pas du tout optimale -> lent pour un gros wtmp.
Améliorations à prévoir..
"""
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 debug : print " argv[0] : %s" % sys.argv[0]
if not datesec :
if date :
if string.lower(os.path.basename(sys.argv[0]))=="wfile.py" :
datesec=os.path.getmtime(date) #modif time
if all_last : #access time
datesec=os.stat(date)[7]
# datesec=os.path.getatime(date) #BUG ! donne mtime !
all_last=0
print " Chosen file Time : %s" \
%time.ctime(datesec)
else :
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)