2009-11-10 18:57:59 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
2011-02-04 13:21:23 +00:00
|
|
|
# Copyright (C) 2003-2011 Upi Tamminen <desaster@dragonlight.fi>
|
2009-11-10 18:57:59 +00:00
|
|
|
#
|
|
|
|
|
2018-08-11 22:31:45 +00:00
|
|
|
import getopt
|
|
|
|
import os
|
|
|
|
import struct
|
|
|
|
import sys
|
|
|
|
import time
|
2009-11-10 18:57:59 +00:00
|
|
|
|
|
|
|
OP_OPEN, OP_CLOSE, OP_WRITE, OP_EXEC = 1, 2, 3, 4
|
2011-10-21 18:35:41 +00:00
|
|
|
TYPE_INPUT, TYPE_OUTPUT, TYPE_INTERACT = 1, 2, 3
|
2009-11-10 18:57:59 +00:00
|
|
|
|
2011-02-04 13:21:23 +00:00
|
|
|
def playlog(fd, settings):
|
2010-08-16 16:15:18 +00:00
|
|
|
ssize = struct.calcsize('<iLiiLL')
|
2009-11-10 18:57:59 +00:00
|
|
|
currtty, prevtime, prefdir = 0, 0, 0
|
|
|
|
|
2011-10-21 18:35:41 +00:00
|
|
|
color = None
|
|
|
|
|
2018-05-02 10:40:02 +00:00
|
|
|
if sys.version_info >= (3,):
|
|
|
|
stdout = sys.stdout.buffer
|
|
|
|
else:
|
|
|
|
stdout = sys.stdout
|
|
|
|
|
2009-11-10 18:57:59 +00:00
|
|
|
while 1:
|
|
|
|
try:
|
|
|
|
(op, tty, length, dir, sec, usec) = \
|
2010-08-16 16:15:18 +00:00
|
|
|
struct.unpack('<iLiiLL', fd.read(ssize))
|
2009-11-10 18:57:59 +00:00
|
|
|
data = fd.read(length)
|
|
|
|
except struct.error:
|
2011-02-04 13:21:23 +00:00
|
|
|
if settings['tail']:
|
|
|
|
prevtime = 0
|
|
|
|
time.sleep(0.1)
|
|
|
|
settings['maxdelay'] = 0
|
|
|
|
continue
|
|
|
|
break
|
2014-05-28 04:13:55 +00:00
|
|
|
|
2009-11-10 18:57:59 +00:00
|
|
|
if currtty == 0: currtty = tty
|
|
|
|
|
|
|
|
if str(tty) == str(currtty) and op == OP_WRITE:
|
|
|
|
# the first stream seen is considered 'output'
|
|
|
|
if prefdir == 0:
|
|
|
|
prefdir = dir
|
|
|
|
# use the other direction
|
|
|
|
if settings['input_only']:
|
2011-10-21 18:35:41 +00:00
|
|
|
prefdir = TYPE_INPUT
|
|
|
|
if dir == TYPE_INPUT: prefdir = TYPE_OUTPUT
|
|
|
|
if dir == TYPE_INTERACT:
|
|
|
|
color = '\033[36m'
|
|
|
|
elif dir == TYPE_INPUT:
|
|
|
|
color = '\033[33m'
|
2009-11-10 18:57:59 +00:00
|
|
|
if dir == prefdir or settings['both_dirs']:
|
|
|
|
curtime = float(sec) + float(usec) / 1000000
|
|
|
|
if prevtime != 0:
|
|
|
|
sleeptime = curtime - prevtime
|
|
|
|
if sleeptime > settings['maxdelay']:
|
|
|
|
sleeptime = settings['maxdelay']
|
|
|
|
if settings['maxdelay'] > 0:
|
|
|
|
time.sleep(sleeptime)
|
|
|
|
prevtime = curtime
|
2011-10-21 18:35:41 +00:00
|
|
|
if settings['colorify'] and color:
|
2018-05-02 10:40:02 +00:00
|
|
|
stdout.write(color)
|
|
|
|
stdout.write(data)
|
2011-10-21 18:35:41 +00:00
|
|
|
if settings['colorify'] and color:
|
2018-05-02 10:40:02 +00:00
|
|
|
stdout.write('\033[0m')
|
2011-10-21 18:35:41 +00:00
|
|
|
color = None
|
2009-11-10 18:57:59 +00:00
|
|
|
sys.stdout.flush()
|
|
|
|
elif str(tty) == str(currtty) and op == OP_CLOSE:
|
|
|
|
break
|
|
|
|
|
|
|
|
def help(brief = 0):
|
2016-09-18 21:25:50 +00:00
|
|
|
print('Usage: %s [-bfhi] [-m secs] [-w file] <tty-log-file> <tty-log-file>...\n' % \
|
|
|
|
os.path.basename(sys.argv[0]))
|
2009-11-10 18:57:59 +00:00
|
|
|
|
|
|
|
if not brief:
|
2016-09-18 21:25:50 +00:00
|
|
|
print(' -f keep trying to read the log until it\'s closed')
|
|
|
|
print(' -m <seconds> maximum delay in seconds, to avoid' + \
|
2009-11-10 18:57:59 +00:00
|
|
|
' boredom or fast-forward\n' + \
|
2016-09-18 21:25:50 +00:00
|
|
|
' to the end. (default is 3.0)')
|
|
|
|
print(' -i show the input stream instead of output')
|
|
|
|
print(' -b show both input and output streams')
|
|
|
|
print(' -c colorify the output stream based on what streams are being received')
|
|
|
|
print(' -h display this help\n')
|
2009-11-10 18:57:59 +00:00
|
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
|
|
settings = {
|
|
|
|
'tail': 0,
|
|
|
|
'maxdelay': 3.0,
|
|
|
|
'input_only': 0,
|
|
|
|
'both_dirs': 0,
|
2011-10-21 18:35:41 +00:00
|
|
|
'colorify': 0,
|
2009-11-10 18:57:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try:
|
2011-10-21 18:35:41 +00:00
|
|
|
optlist, args = getopt.getopt(sys.argv[1:], 'fhibcm:w:', ['help'])
|
2016-09-18 21:25:50 +00:00
|
|
|
except getopt.GetoptError as error:
|
|
|
|
print('Error: %s\n' % error)
|
2009-11-10 18:57:59 +00:00
|
|
|
help()
|
|
|
|
|
|
|
|
for o, a in optlist:
|
|
|
|
if o == '-f': settings['tail'] = 1
|
|
|
|
elif o == '-m': settings['maxdelay'] = float(a) # takes decimals
|
|
|
|
elif o == '-i': settings['input_only'] = 1
|
|
|
|
elif o == '-b': settings['both_dirs'] = 1
|
|
|
|
elif o in ['-h', '--help']: help()
|
2011-10-21 18:35:41 +00:00
|
|
|
elif o == '-c': settings['colorify'] = 1
|
2009-11-10 18:57:59 +00:00
|
|
|
|
2011-02-04 13:21:23 +00:00
|
|
|
if len(args) < 1:
|
|
|
|
help()
|
2009-11-10 18:57:59 +00:00
|
|
|
|
|
|
|
try:
|
2016-01-21 23:40:50 +00:00
|
|
|
for logfile in args:
|
|
|
|
logfd = open(logfile, 'rb')
|
|
|
|
playlog(logfd, settings)
|
2009-11-10 18:57:59 +00:00
|
|
|
except IOError:
|
2016-09-18 21:25:50 +00:00
|
|
|
print("\n\n[!] Couldn't open log file (%s)!" % logfile)
|
2009-11-10 18:57:59 +00:00
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
# vim: set sw=4:
|