Skip to content

Instantly share code, notes, and snippets.

@ftoledo
Created August 2, 2024 20:43
Show Gist options
  • Save ftoledo/aa62ef4965c11023feb9cddcc2907cbf to your computer and use it in GitHub Desktop.
Save ftoledo/aa62ef4965c11023feb9cddcc2907cbf to your computer and use it in GitHub Desktop.
binkit.js outbound statics
#!/usr/bin/env python2
import glob
import os.path
import stat
import sys
from datetime import datetime
#--------------------------------------------------------------------------
def IsoTime(t):
return datetime.fromtimestamp(int(t)).strftime('%Y-%m-%d %H:%M:%S')
#--------------------------------------------------------------------------
class OBFile:
flavours = { 'f':"Normal", 'i':"Immediate", 'c':"Continuous", 'd':"Direct", 'h':"Hold", 'o':"Normal" }
def __init__(self, path, zone, net=-1, node=-1):
self.fullpath = os.path.abspath(path)
self.zone = zone
self.net = net
self.node = node
self.point = 0
self.txt = ""
self.type = "unk"
self.refs = []
try:
st = os.stat(path)
self.mtime = st.st_mtime
self.size = st.st_size
self.isDir = stat.S_ISDIR(st.st_mode)
self.fname = os.path.basename(path)
self.root, self.ext = os.path.splitext(self.fname)
self.ext = self.ext[1:].lower()
if len(self.root) == 8:
if self.net < 0:
self.net = int(self.root[:4], 16)
if self.node < 0:
self.node = int(self.root[4:], 16)
else:
self.point = int(self.root[4:], 16)
self.nn = str(self.zone) + ':' + str(self.net) + '/' + str(self.node)
if self.point > 0:
self.nn += '.' + str(self.point)
if self.ext == "try":
tfile = open(path)
tfile.seek(5)
self.txt = "Try result: " + tfile.readline().strip()
tfile.close()
self.type = "try"
elif self.ext == "bsy" or self.ext == "csy":
self.txt = ""
self.type = "bsy"
elif self.ext == "hld":
self.txt = "Holding until: " + IsoTime(open(path).readline())
self.type = "hld"
elif self.ext == "req":
self.txt = ""
self.type = "req"
elif self.ext[1:] == "ut" and self.ext[0] in "oicdh":
self.txt = "Flavour: " + self.flavours[self.ext[0]]
self.type = "out"
elif self.ext[1:] == "lo" and self.ext[0] in "ficdh":
self.txt = "Flavour: " + self.flavours[self.ext[0]]
self.type = "flo"
elif self.ext == "pnt" and self.isDir:
self.txt = "Point directory"
self.type = "pnt"
self.obdir = OutBoundDir(path, 5, self.zone, self.net, self.node)
except ValueError:
self.txt = ""
self.type = "err"
# The following directives are documented as a standard:
#
# "#" - Indicates that the files should be truncated to zero-
# length after successfully sending the file to the remote
# system. This is normally only employed when sending compressed
# mail (archived mail) to the remote.
#
# "^" - delete the file after successfully sending the file to
# the remote system.
#
# "~" - skip the line from treatment. It may be useful to mark
# an already processed line.
#
# <none> - indicates that the file should be sent and neither be
# truncated nor deleted after sending. Listing the file with the
# full path circumvents problems with files that have a name
# starting with a character that is a known directive.
#
#
# Software may optionally recognise the following directives:
#
# "-" As an alternate for "^"
#
# "!" As an alternate for "~"
#
# "@" Send file, do not truncate or delete.
def OrphansToRefs(self, orphans, fname, flochar):
for i, obfile in reversed(list(enumerate(orphans))):
if obfile.FileName() == fname:
obfile.flochar = flochar
self.refs.append(obfile)
del orphans[i]
break
def HandleLine(self, line, orphans):
if line[0] in "#^~-!@":
flochar = line[0]
fpath = line[1:].strip()
else:
flochar = ' '
fpath = line.strip()
fname = os.path.basename(fpath)
self.OrphansToRefs(orphans, fname, flochar)
def GetRefFiles(self, orphans):
if self.type == "flo":
tfile = open(self.fullpath)
for line in tfile:
self.HandleLine(line, orphans)
tfile.close()
def NodeNumber(self):
return self.nn if hasattr(self, 'nn') else ''
def FileName(self):
return self.fname if hasattr(self, 'fname') else ''
def KnownType(self):
return hasattr(self, 'type') and self.type != "unk" and self.type != "err"
def Size(self):
return " <dir>" if self.isDir else "%7d" % (self.size, )
def FileInfoStr(self):
return "%-12s - %s - %s" % (self.fname, IsoTime(self.mtime), self.Size())
def Print(self, indent):
print (' ' * indent), '+', self.FileInfoStr(), '-', self.txt
for obfile in self.refs:
obfile.PrintRef(indent)
if hasattr(self, 'obdir'):
self.obdir.PrintFiles()
def FloActionTxt(self):
if self.flochar == '#':
return "Truncate after send"
elif self.flochar == '^' or self.flochar == '-':
return "Delete after send"
elif self.flochar == '!' or self.flochar == '~':
return "Skip"
else:
return "Keep after send"
def PrintRef(self, indent):
print (' ' * indent), self.flochar, self.FileInfoStr(), "- Action:", self.FloActionTxt()
def PrintOrphan(self, indent):
print (' ' * (indent + 2)), self.FileInfoStr()
#--------------------------------------------------------------------------
class OutBoundDir:
def __init__(self, oDir, indent, zone, net=-1, node=-1):
self.oDir = oDir
self.zone = zone
self.net = net
self.node = node
self.indent = indent
self.nfiles = {}
self.orphans = []
self.AddFiles(glob.glob(os.path.join(oDir, "*")))
def AddFiles(self, files):
if files:
self.FilesToLists(files)
self.orphans.sort(key=OBFile.FileName)
self.AddOrphansToFloFiles()
def FilesToLists(self, files):
for oFile in files:
obf = OBFile(oFile, self.zone, self.net, self.node)
if obf.KnownType():
self.AddFile(obf)
else:
self.orphans += obf,
def AddFile(self, obfile):
if obfile.nn not in self.nfiles:
self.nfiles[obfile.nn] = []
self.nfiles[obfile.nn] += obfile,
def AddOrphansToFloFiles(self):
for key, obfiles in self.nfiles.iteritems():
for obfile in obfiles:
obfile.GetRefFiles(self.orphans)
def PrintNodes(self):
for key in sorted(self.nfiles):
print (' ' * self.indent) + key
for obfile in self.nfiles[key]:
obfile.Print(self.indent)
def PrintOrphans(self):
if self.orphans:
print (' ' * self.indent) + "Orphaned files:"
for orphan in self.orphans:
orphan.PrintOrphan(self.indent)
def PrintFiles(self):
self.PrintNodes()
self.PrintOrphans()
def NodeStrs(self):
if self.net >= 0:
return "Node", str(self.zone) + ':' + str(self.net) + '/' + str(self.node if self.node >= 0 else 0)
else:
return "Zone", str(self.zone)
def PrintHeader(self):
print self.oDir, "- %s %s" % self.NodeStrs()
print
def Print(self):
self.PrintHeader()
self.PrintFiles()
print
"""
Netmail: .?ut
Referemce: .?lo
"#" - truncate
"^" "-" - delete
"~" "!" - skip the line from treatment. It may be useful to mark an already processed line.
<none> "@" Send file, do not truncate or delete
file request: .req
flavours:
i - Immediate
c - Continuous
d - Direct
h - Hold
o/f - Normal (Netmail/Reference)
Immediate ("iut" or "ilo")
Continuous ("cut" or "clo")
Direct ("dut" or "dlo")
Normal ("out" or "flo")
Hold ("hut" or "hlo")
bsy (busy) control file
csy (call) control file
For information purposes a [bc]sy file may contain one line of
PID information (less than 70 characters).
hld (hold) control file
A hld file must contain a one line string with the expiration
of the hold period expressed in UNIX-time.
try control file
A try file must contain one line string with a diagnostic
message. It is for information purposes only.
For information purposes the second line of a try file may
contain one line of PID information. ( < 70 characters)
"""
#--------------------------------------------------------------------------
class OutBoundDirs:
def __init__(self, outbound, defzone):
self.outbound = outbound
self.defzone = defzone
def Handle(self):
if not os.path.isdir(self.outbound):
print "Error:", self.outbound, "is not a dir."
return 1
self.outboundDirs = [ (self.outbound, self.defzone), ]
self.GetOutboundDirs()
self.ProcessOutboundDirs()
return 0
def GetOutboundDirs(self):
dirs = glob.glob(self.outbound + ".*")
dirs.sort()
self.outboundStrLen = len(self.outbound) + 1
for dir in dirs:
self.GetOutboundDir(dir)
def GetOutboundDir(self, dir):
ext = dir[self.outboundStrLen:]
try:
zone = int(ext, 16)
self.outboundDirs += ((dir, zone),)
except ValueError:
pass
def ProcessOutboundDirs(self):
for od in self.outboundDirs:
obd = OutBoundDir(od[0], 2, od[1])
obd.Print()
#--------------------------------------------------------------------------
if __name__ == "__main__":
rv = 0
print "bsostatus 1.1.0 Copyright (C) 2022-01-17 by Wilfred van Velzen"
print
if len(sys.argv) < 3:
print "usage:", sys.argv[0], "<default outbound dir> <default zone>"
rv = 1
else:
rv = OutBoundDirs(sys.argv[1], int(sys.argv[2])).Handle()
sys.exit(rv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment