home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 2 BBS
/
02-BBS.zip
/
SHOWMSG.LZH
/
SHOWMSG.CMD
Wrap
OS/2 REXX Batch file
|
1991-10-06
|
15KB
|
489 lines
/*
SHOWMSG.CMD
This program shows the contents of a FIDO-message.
It was originally meant as a utility with which you could delete a
'thread' of messages. I want to keep my messageareas as 'clean' as
possible, especially the OS2 area. I have always 500-1000 messages
in this area and while I am reading, I kill all messages of no
interest to me using Alt-D in MsgEd.
When I see a long boring (political) discussion which I definitly
do not want to keep, I use this Rexx program to kill the whole
bunch at once.
You can also use this program to read your mail, although it is a
bit slow.
Jaap Geluk, 8 september 1991
*/
trace off
arg tCmdAreaName nCmdMsg
/* I use CMD.EXE SetLocal instead of
Rexx SetLocal because with OS/2
2.0 6.149 I can't get it to work
as I expect. */
address cmd '@setlocal' /* Save drive, directory en envir. */
/*
On my pointsystem I call SETENV.CMD first in all my Rexx files.
SetEnv.Cmd sets all required variables into the environment of CMD.EXE
interpret Call "'"Value('BINKLEY',,'OS2ENVIRONMENT')'\SetEnv'"'"
EchoDir = Value('Echo',,'OS2ENVIRONMENT')
NetMailDir = Value('BinkNetMail',,'OS2ENVIRONMENT')
*/
tEchoDir = 'C:\COMM\BINKLEY\ECHO'
tNetMailDir = 'C:\COMM\BINKLEY\NETMAIL'
nScreenLines = 50 /* Number of screenlines */
nScreenColumns = 80 /* Number of screencolumns */
bShowKludgeLines = 0 /* Show Kludge lines yes or no */
bShowSeenBys = 0 /* Show Seen-Bys yes or no */
Msg.tBuf = '' /* Buffer for actual message */
Msg.nMsg = nCmdMsg /* Current messagenumber (physical) */
Msg.bReadForward = 1 /* Direction of reading */
Msg.tArea = tCmdAreaName /* Current tAreaName */
Msg.tSavArea = '' /* 'Static' variable used in ChechArea() */
Msg.tDir = '' /* Full directoryname of current area */
Msg.tFile = '' /* Full filename with dir of current msg */
Msg.nNext = 0 /* Next message in thread */
Msg.nPrev = 0 /* Previous message in thread */
tGlobals = 'nScreenLines nScreenColumns',
'tEchoDir tNetMailDir',
'bShowKludgeLines bShowSeenBys',
'Msg.tBuf Msg.nMsg',
'Msg.bReadForward Msg.tArea',
'Msg.tSavArea Msg.tDir Msg.tFile',
'Msg.nNext Msg.nPrev tGlobals'
address cmd '@mode co' || nScreenColumns || ',' || nScreenLines
if datatype(Msg.tArea) \= 'CHAR' then Msg.tArea = 'NETMAIL'
if datatype(Msg.nMsg) \= 'NUM' then Msg.nMsg = 1
/*
Beginning of main loop...
*/
do forever
if ReadMsgFile() \= 0 then leave
call ShowMsg
say Msg.tArea'#'Msg.nMsg||,
'--------------------------------------------------------------'
say '<=Previous >=Next ,=Previous- .=Next-threadmessage (Q)uit'
say '(L)istthread (K)illthread (A)rea (D)elete-message Kl(u)dge (S)een-Bys'
pull tCmdChar
select
when tCmdChar = '<' then do
Msg.nMsg = max(1, Msg.nMsg - 1)
Msg.bReadForward = 0
end
when tCmdChar = '>' then do
Msg.nMsg = Msg.nMsg + 1
Msg.bReadForward = 1
end
when tCmdChar = ',' then do
if Msg.nPrev > 0 then Msg.nMsg = Msg.nPrev
else say 'First message in thread!'
Msg.bReadForward = 0
end
when tCmdChar = '.' then do
if Msg.nNext > 0 then Msg.nMsg = Msg.nNext
else say 'Last message in thread!'
Msg.bReadForward = 1
end
when tCmdChar = 'Q' then leave
when tCmdChar = 'L' then do
call ListThread
address cmd '@pause'
end
when tCmdChar = 'K' then call KillThread
when tCmdChar = 'D' then call DeleteMsg
when word(tCmdChar,1) = 'A' then do
if words(tCmdChar) = 2 then Msg.tArea = word(tCmdChar, 2)
else pull Msg.tArea
Msg.nMsg = 1
call CheckArea
end
when tCmdChar = 'U' then bShowKludgeLines = \ bShowKludgeLines
when tCmdChar = 'S' then bShowSeenBys = \ bShowSeenBys
when datatype(tCmdChar) = 'NUM' then Msg.nMsg = tCmdChar
otherwise
say tCmdChar' is an unsupported tCmdChar...'
end
end
exit 0 /* End of ShowMsg.CMD */
/* =============================== FUNCTIONS =================================*/
/* ==========================================================================
NextPos
This function is used by ShowMsg()
*/
NextPos: procedure
parse arg pos3 pos4
if pos3 < 1 then return pos4
if pos4 < 1 then return pos3
return min(pos3, pos4)
/* ==========================================================================
Word2Dec
Converts a word (a 2-byte CHAR variable) into a decimal value
*/
Word2Dec: procedure
return C2D(translate('21', arg(1), '12'))
/* ==========================================================================
Long2Dec
Converts a long (a 4-byte CHAR variable) into a decimal value
*/
Long2Dec: procedure
return C2D(translate('2143', arg(1), '1234'))
/* ==========================================================================
Long2Date
Converts a long (a 4-byte CHAR variable) into a date-string.
Use by ShowMsg() to show the dates...
*/
Long2Date: procedure
parse arg long
/*
This is not working, yet...
Can't find what the problem is. Nor do I have the time.
Could not exactly find out what all the bits EXACTLY mean...
*/
BinDate = X2B(C2X(translate('1234', long, '1234')))
day = X2D(B2X(substr(BinDate, 1, 5)))
mon = X2D(B2X(substr(BinDate, 6, 4))) - 1
yea = X2D(B2X(substr(BinDate, 10, 7))) + 80
sec = X2D(B2X(substr(BinDate, 17, 5))) * 2
min = X2D(B2X(substr(BinDate, 22, 6)))
hou = X2D(B2X(substr(BinDate, 28, 5)))
/* Below you see the Dutch way of saying what the time is... :-) */
return day'-'mon'-'yea' 'hou':'min':'sec
/* ==========================================================================
bool = CheckArea()
bool = true on return if Msg.tAreaName was valid.
Checks if Msg.tAreaName is valid. If not, on return Msg.tAreaName will
be equal to 'NETMAIL'.
If Msg.tAreaName is not different from the value used when CheckArea
was called before, CheckArea will return immediatly.
*/
CheckArea: procedure expose (tGlobals)
tLocAreaName = Msg.tArea
if tLocAreaName = Msg.tSavArea then return 0
Msg.tSavArea = tLocAreaName
if tLocAreaName = '' then tLocAreaName = 'NETMAIL'
if tLocAreaName \= 'NETMAIL' then do
/* Prefix tAreaName with full directory name */
tLocAreaDir = tEchoDir'\'tLocAreaName
/* Test for the existence of the area-dir */
if \ Exist(tLocAreaDir'\*.*') then do
say tLocAreaName' does not exist!'
Msg.tArea = 'NETMAIL'
Msg.tDir = tNetMailDir
end
else do
Msg.tArea = tLocAreaName
Msg.tDir = tLocAreaDir
end
end
else do
Msg.tDir = tNetMailDir
end
return 0
/* ==========================================================================
MakeFIleName
'Composes' a complete filename (with directory) for the current
messagefile.
*/
MakeFileName: procedure expose (tGlobals)
Msg.tFile = Msg.tDir'\'Msg.nMsg'.MSG'
return
/* ==========================================================================
bool = ReadMsgFile()
bool = true when all went ok
This routine opens the specified .MSG file in read-only mode, reads
everything into the Msg structure and closes the file.
*/
ReadMsgFile: procedure expose (tGlobals)
if CheckArea() \= 0 then return 1
do i = 1 to 10
call MakeFileName
if stream(Msg.tFile, 'c', 'query exists') = Msg.tFile then leave
if Msg.bReadForward then
Msg.nMsg = Msg.nMsg + 1
else
Msg.nMsg = Msg.nMsg - 1
if Msg.nMsg < 1 then leave
end
if i > 10 | Msg.nMsg < 1 then return 1
if stream(Msg.tFile, 'c', 'open read') \= 'READY' then do
say Msg.tFile' could not be opened for reading...'
return 1
end
Msg.tBuf = charin(Msg.tFile, 1, stream(Msg.tFile, 'c', 'query size'))
if stream(Msg.tFile, 'c', 'close') \= 'READY' then do
say Msg.tFile' could not be closed...'
return 1
end
Msg.nPrev = Word2Dec(substr(Msg.tBuf, X2D('B9'), 02))
Msg.nNext = Word2Dec(substr(Msg.tBuf, X2D('BD'), 02))
return 0 /* End of ReadMsgFile() */
/* ==========================================================================
ShowMsg (Msg)
This routine shows the contents of a message on screen.
Before doing that, the screen is cleared.
*/
ShowMsg: procedure expose (tGlobals)
address cmd '@cls'
say 'From :' strip(substr(Msg.tBuf, X2D('01'), 36), 'T', '00'X)
say 'To :' strip(substr(Msg.tBuf, X2D('25'), 36), 'T', '00'x)
say 'Subject :' strip(substr(Msg.tBuf, X2D('49'), 72), 'T', '00'x)
say 'Date :' strip(substr(Msg.tBuf, X2D('91'), 20), 'T', '00'x)
say 'Times read :' Word2Dec(substr(Msg.tBuf, X2D('A5'), 02))
say 'Dest. node :' Word2Dec(substr(Msg.tBuf, X2D('A7'), 02))
say 'Org. node :' Word2Dec(substr(Msg.tBuf, X2D('A9'), 02))
say 'Cost :' Word2Dec(substr(Msg.tBuf, X2D('AB'), 02))
say 'Org. net :' Word2Dec(substr(Msg.tBuf, X2D('AD'), 02))
say 'Dest. net :' Word2Dec(substr(Msg.tBuf, X2D('AF'), 02))
/* say 'Date written:' Long2Date(substr(Msg.tBuf, X2D('B1'), 04)) */
/* say 'Date arrived:' Long2Date(substr(Msg.tBuf, X2D('B5'), 04)) */
/*
If you put the above lines back on screen, remember to change the value
of nCurLine from 16 to 18
*/
say 'Reply :' Msg.nNext
say 'Unreply :' Msg.nPrev
Attr = X2B(D2X(Word2Dec(substr(Msg.tBuf, X2D('BB'), 02))))
Tmp = ''
if substr(Attr, 01, 1) = '1' then Tmp = Tmp'Private '
if substr(Attr, 02, 1) = '1' then Tmp = Tmp'Crash '
if substr(Attr, 03, 1) = '1' then Tmp = Tmp'Read '
if substr(Attr, 04, 1) = '1' then Tmp = Tmp'Sent '
if substr(Attr, 05, 1) = '1' then Tmp = Tmp'Attach '
if substr(Attr, 06, 1) = '1' then Tmp = Tmp'Forwarded '
if substr(Attr, 07, 1) = '1' then Tmp = Tmp'Orphan '
if substr(Attr, 08, 1) = '1' then Tmp = Tmp'Kill/sent '
if substr(Attr, 09, 1) = '1' then Tmp = Tmp'Local '
if substr(Attr, 10, 1) = '1' then Tmp = Tmp'Hold '
if substr(Attr, 11, 1) = '1' then Tmp = Tmp'Direct '
if substr(Attr, 12, 1) = '1' then Tmp = Tmp'Request '
if substr(Attr, 13, 1) = '1' then Tmp = Tmp'Return-receipt requested '
if substr(Attr, 14, 1) = '1' then Tmp = Tmp'Return-receipt '
if substr(Attr, 15, 1) = '1' then Tmp = Tmp'Audit-trail requested '
if substr(Attr, 16, 1) = '1' then Tmp = Tmp'Update-request '
say 'Attributes :' Tmp
say '---------------------------------------------------------------------'
SOFTCR = D2C(141)
CTRLCOD = D2C(1)
CR = D2C(13)
LF = D2C(10)
CRLF = CR||LF
tTableO = CR
tTableI = SOFTCR
if bShowKludgeLines then do
tTableO = tTableO||'^'
tTableI = tTableI||CTRLCOD
end
Msg.tBuf = translate(substr(Msg.tBuf, X2D('BF')), tTableO, tTableI)
nCurLine = 16
nMaxLineLen = nScreenColumns - 1
pos1 = 1
pos2 = NextPos(pos(CR, Msg.tBuf, pos1), pos(CRLF, Msg.tBuf, pos1))
do while pos2 > 0
if nCurLine > nScreenLines then do
address cmd '@pause'
address cmd '@cls'
nCurLine = 0
end
if substr(Msg.tBuf, pos1, 1) \= CTRLCOD then do
nBeg = pos1 /* First position of current sentence */
nLen = pos2 - pos1 /* (Remaining) Lenght of current sentence */
do while nLen > 0
nLineLen = min(nMaxLineLen, nLen)
tLine = substr(Msg.tBuf, nBeg, nLineLen)
if nLineLen = nMaxLineLen then do
nTmp = words(tLine)
if nTmp > 1 then do
tLine = delword(tLine, nTmp)
nLineLen = length(tLine)
end
end
say tLine
nCurLine = nCurLine + 1
nLen = nLen - nLineLen
nBeg = nBeg + nLineLen
end
end
if \ bShowSeenBys then do
/* Check if line begins with ' * Origin:'. If so, leave loop */
if substr(Msg.tBuf, pos1, 9) = ' * Origin' then leave
end
pos1 = pos2 + 1
if substr(Msg.tBuf, pos1, 1) = LF then pos1 = pos1 + 1
pos2 = NextPos(pos(CR, Msg.tBuf, pos1), pos(CRLF, Msg.tBuf, pos1))
end
return 1 /* End of ShowMsg */
/* ==========================================================================
num = SearchForFirstThreadMessage()
This function searches for the first message in a message-thread.
If it does not succeed finding it, it will return 0.
*/
SearchForFirstThreadMessage: procedure expose (tGlobals)
do while Msg.nMsg > 0
if ReadMsgFile() \= 0 then return 0
if Msg.nPrev < 1 then return Msg.nMsg
Msg.nMsg = Msg.nPrev
end
return 0
/* ==========================================================================
bool = ListThread(Msg)
bool = true if everything went ok.
Shows all messages in a thread.
*/
ListThread: procedure expose (tGlobals)
nSaveCurMsg = Msg.nMsg /* Save current message */
nRet = 0 /* Default returnvalue */
Msg.nMsg = SearchForFirstThreadMessage()
do while Msg.nMsg > 0
if ReadMsgFile() \= 0 then do
nRet = 1
leave
end
say '#'Msg.nMsg':' strip(substr(Msg.tBuf, X2D('49'), 72), 'T', '00'x)
Msg.nMsg = Msg.nNext
end
Msg.nMsg = nSaveCurMsg
return nRet
/* ==========================================================================
KillThread
First calls ListThread, asks you for a confirmation and then kills all
messages in a thread.
*/
KillThread: procedure expose (tGlobals)
address cmd '@cls'
call ListThread
say 'Are you sure to kill this thread?'
pull answer
if answer \= 'Y' then return 1
nKilled = 0 /* Number of deleted messages */
Msg.nMsg = SearchForFirstThreadMessage()
do while Msg.nMsg > 0
if ReadMsgFile() \= 0 then return 1
say '#'Msg.nMsg':' strip(substr(Msg.tBuf, X2D('49'), 72), 'T', '00'x)
address cmd '@del' Msg.tFile
nKilled = nKilled + 1
Msg.nMsg = Msg.nNext
end
say nKilled' messages killed...'
pull key
return 0
/* ==========================================================================
DeleteMsg
Deletes the 'current' msg described in the stemvariable Msg.
*/
DeleteMsg: procedure expose (tGlobals)
if CheckArea() \= 0 then return 1
call MakeFileName
address cmd '@del' Msg.tFile
return 0
/* ==========================================================================
bool = Exist(tDirName)
Used to test if a directory exists.
*/
Exist: procedure
address cmd '@if exist' arg(1) 'dir nul 1>nul 2>nul'
return rc