-- InboxToFiles.mesa

-- M. D. Schroeder May 5, 1983 9:08 am

DIRECTORY
Ascii   USING [ NUL ],
FileIO  USING [ Open ],
GVBasics USING [ ItemHeader ],
GVRetrieve,
IO   USING [ card, Close, Error, Flush, GetInt, GetIndex, PutBlock,
       PutChar, PutF, PutFR, PutRope, rope, STREAM ],
IOExtras  USING [ GetLine ],
Rope   USING [ Cat, ROPE, FromRefText ],
UserExec  USING [ CommandProc, RegisterCommand ],
ViewerIO USING [ CreateViewerStreams ];

InboxToFiles: PROGRAM
IMPORTS FileIO, GVRetrieve, IO, IOExtras, Rope, UserExec, ViewerIO =

BEGIN


Unpick: PROC [n1, n2, n3, n4: INTEGER] RETURNS [Rope.ROPE] =
BEGIN
text: REF TEXT = NEW[TEXT[8]];
[text[0], text[1]] ← Chars[n1];
[text[2], text[3]] ← Chars[n2];
[text[4], text[5]] ← Chars[n3];
[text[6], text[7]] ← Chars[n4];
FOR i: INT IN [0..7] DO
IF text[i] = Ascii.NUL THEN {text.length ← i; EXIT};
ENDLOOP;
RETURN [Rope.FromRefText[text]];
END; --Unpick--


Chars: PROC [n: INTEGER] RETURNS [left, right: CHAR] =
BEGIN
MagicNumber: TYPE = MACHINE DEPENDENT RECORD
[char1: [0..127], skip1: [0..1], char2: [0..127], skip2: [0..1]];
m: MagicNumber = LOOPHOLE[n, MagicNumber];
left ← LOOPHOLE[m.char1, CHAR];
right ← LOOPHOLE[m.char2, CHAR];
END; --Chars--


DoIt: PROC= TRUSTED
BEGIN
buffer: REF TEXT = NEW[TEXT[512]];
fileNum: CARDINAL ← 0;
fH: IO.STREAMNIL;
in, out: IO.STREAM;
name, password: Rope.ROPE;
m1, m2, m3, m4: INTEGER;
handle: GVRetrieve.Handle = GVRetrieve.Create[300];
[in, out] ← ViewerIO.CreateViewerStreams["InboxToFile"];

DO

DO
out.PutRope["\nType RName: "];
name ← IOExtras.GetLine[in];
out.PutRope["Type magic numbers: "];
BEGIN ENABLE IO.Error => IF ec=SyntaxError THEN LOOP;
m1 ← in.GetInt[]; m2 ← in.GetInt[]; m3 ← in.GetInt[]; m4 ← in.GetInt[];
END;
password ← Unpick[m1, m2, m3, m4];
handle.NewUser[name, password];
SELECT handle.MailboxState[] FROM
badName, badPwd => out.PutRope["\nBad name or password."];
cantAuth, allDown => out.PutRope["\nServers down."];
someEmpty, allEmpty => out.PutRope["\nNo mail."];
notEmpty => EXIT;
ENDCASE => ERROR;
LOOP;
ENDLOOP;

DO
failed: BOOLEANFALSE;
noMore: BOOL;
state: GVRetrieve.ServerState;
type: GVRetrieve.ServerType;
[noMore, state, type] ← GVRetrieve.NextServer[handle];
IF noMore THEN EXIT;
out.PutF["\nServer \"%g\"\n", IO.rope[GVRetrieve.ServerName[handle]] ];
IF state # notEmpty THEN LOOP;
DO ENABLE GVRetrieve.Failed => { failed ← TRUE; EXIT };
msgExists, archived, deleted: BOOL;
[msgExists, archived, deleted] ← GVRetrieve.NextMessage[handle];
IF NOT msgExists THEN EXIT;
IF deleted THEN LOOP;
DO
header: GVBasics.ItemHeader = GVRetrieve.NextItem[handle];
IF header.type = LastItem THEN EXIT;
IF header.type # Text THEN LOOP;
IF fH = NIL OR fH.GetIndex > 100000
THEN BEGIN
file: Rope.ROPE;
IF fH # NIL THEN fH.Close[];
fileNum ← fileNum + 1;
file ← Rope.Cat[name, ".", IO.PutFR["%g", IO.card[fileNum]], ".mail"];
out.PutF["\nNew file: \"%g\"\n", IO.rope[file] ];
fH ← FileIO.Open[
fileName: file,
accessOptions: overwrite,
streamBufferParms: [bufferSize: 16, bufferSwapUnitSize: 16] ];
END
ELSE fH.PutRope["\n\n++++++++++\n\n"];
UNTIL handle.EndOf[] DO
buffer.length ← handle.GetBlock[buffer, 0, buffer.maxLength];
fH.PutBlock[buffer, 0, buffer.length];
ENDLOOP;
ENDLOOP;
out.PutChar['.];
ENDLOOP;
IF fH # NIL THEN fH.Flush[];
IF NOT failed
THEN BEGIN
out.PutRope["\nFlushing inbox ... "];
handle.Accept[];
out.PutRope["done.\n"];
END
ELSE out.PutRope["\n****** Failed\n"];
ENDLOOP;
IF fH # NIL THEN fH.Close[];
out.PutRope["\nEnd of messages\n"];
handle.Close[];

ENDLOOP;

END;

DoItWithCatch: UserExec.CommandProc = TRUSTED { DoIt [ ! IO.Error => CONTINUE ] };

UserExec.RegisterCommand["InboxToFiles", DoItWithCatch ];

END.