-- Grapevine: program to check database for export controls
-- DBExport.mesa
-- Andrew Birrell 11-Feb-82 9:41:35
DIRECTORY
Ascii USING[ CR ],
BodyDefs USING[ maxRNameLength, RName ],
IODefs USING[ WriteChar, WriteString ],
LaurelExecDefs USING[ MakeMenuCommandCallable ],
NameInfoDefs USING[ Close, Enumerate, Expand, ExpandInfo, GetMembers,
MemberInfo ],
Runtime USING[ IsBound ],
Storage USING[ Free, Node, String ],
String USING[ AppendChar, AppendString ];
DBExport: PROGRAM
IMPORTS IODefs, LaurelExecDefs, NameInfoDefs, Runtime, Storage, String =
BEGIN
OPEN IODefs, BodyDefs, NameInfoDefs;
LowerCase: PROC[c: CHARACTER] RETURNS[ CHARACTER ] = INLINE
{ RETURN[ IF c IN ['A..'Z] THEN 'a + (c-'A) ELSE c] };
EndsWith: PROC[a, b: STRING] RETURNS[ BOOLEAN ] = INLINE
BEGIN
j: CARDINAL ← a.length;
-- Assumes b is all lower case --
IF a.length < b.length THEN RETURN[FALSE];
FOR i: CARDINAL DECREASING IN [0..b.length)
DO j ← j-1;
IF LowerCase[a[j]] # LowerCase[b[i]] THEN RETURN[FALSE];
ENDLOOP;
RETURN[TRUE]
END;
targets: DESCRIPTOR FOR ARRAY OF STRING ← DESCRIPTOR[NIL,0];
GetTargets: PROC =
BEGIN
info: NameInfoDefs.MemberInfo =
NameInfoDefs.GetMembers["OtherRegistries↑.internet"L];
WITH info SELECT FROM
allDown =>
WriteString["Can't get OtherRegistries↑.internet - all down"L];
notFound, individual =>
WriteString["Can't get OtherRegistries↑.internet - not a group"L];
group =>
BEGIN
count: CARDINAL ← 0;
GetCount: PROC[entry: RName] RETURNS[done: BOOLEAN] =
{ count ← count+1; done ← FALSE };
GetReg: PROC[entry: RName] RETURNS[done: BOOLEAN] =
BEGIN
FOR i: CARDINAL DECREASING IN [0..entry.length)
DO IF entry[i] = '.
THEN BEGIN
targets[count] ← Storage.String[entry.length-i];
FOR j: CARDINAL IN [i..entry.length)
DO String.AppendChar[targets[count], entry[j]] ENDLOOP;
count ← count+1;
WriteString[SELECT count FROM
1 => """"L,
LENGTH[targets] => " and """L,
ENDCASE => ", """L];
WriteString[targets[count-1]];
WriteChar['"];
EXIT
END;
ENDLOOP;
done ← FALSE;
END;
WriteString["Looking for members and forwardees in: "L];
NameInfoDefs.Enumerate[members,GetCount];
targets ← DESCRIPTOR[Storage.Node[count*SIZE[STRING]],count];
count ← 0;
NameInfoDefs.Enumerate[members,GetReg];
NameInfoDefs.Close[members];
END;
ENDCASE => ERROR;
END;
FreeTargets: PROC =
BEGIN
tBase: POINTER ← BASE[targets];
FOR i: CARDINAL IN [0..LENGTH[targets])
DO Storage.Free[@targets[i]] ENDLOOP;
Storage.Free[@tBase];
END;
lookType: { group, individual };
Look: PROC[entry: RName] RETURNS[done: BOOLEAN] =
BEGIN
first: BOOLEAN ← TRUE;
Check: PROC[n: RName] RETURNS[done: BOOLEAN] =
BEGIN
FOR i: CARDINAL IN [0..LENGTH[targets])
DO IF EndsWith[n, targets[i]]
THEN BEGIN
IF first
THEN BEGIN
WriteChar[Ascii.CR]; WriteChar[Ascii.CR];
WriteString[entry];
WriteString[IF lookType = group
THEN " contains "
ELSE " is forwarded to "];
first ← FALSE;
END
ELSE WriteString[", "];
WriteString[n];
EXIT
END;
ENDLOOP;
done ← FALSE;
END;
memberInfo: NameInfoDefs.ExpandInfo = NameInfoDefs.Expand[entry];
WITH memberInfo SELECT FROM
group =>
BEGIN ENABLE UNWIND => NameInfoDefs.Close[members];
NameInfoDefs.Enumerate[members, Check];
NameInfoDefs.Close[members];
done ← FALSE
END;
allDown => { done ← TRUE; WriteString["all R-Servers down!"L] };
individual => { done ← FALSE; NameInfoDefs.Close[sites] };
notFound => done ← FALSE;
ENDCASE => ERROR;
END;
LookEnum: PROC[enumName: RName,
work: PROC[RName]RETURNS[done: BOOLEAN] ] =
-- argument is "groups.reg", "individuals.reg", or "dead.reg" --
BEGIN
memberInfo: NameInfoDefs.MemberInfo;
memberInfo ← NameInfoDefs.GetMembers[enumName];
WITH memberInfo SELECT FROM
group => BEGIN ENABLE UNWIND => NameInfoDefs.Close[members];
NameInfoDefs.Enumerate[members, work];
NameInfoDefs.Close[members];
END;
allDown =>
{ WriteString[enumName]; WriteString[": all R-Servers down!"L] };
notFound =>
{ WriteString[enumName]; WriteString[": not found!"L] };
ENDCASE => ERROR;
END;
LookAtRegistry: PROC[regGroup: RName] RETURNS[done: BOOLEAN] =
BEGIN
wanted: RName = [maxRNameLength];
FOR i: CARDINAL DECREASING IN [0..regGroup.length)
DO regGroup.length ← regGroup.length-1;
IF regGroup[i] = '. THEN EXIT;
ENDLOOP;
String.AppendString[wanted, "Groups."L];
String.AppendString[wanted, regGroup];
-- Don't look inside target registries --
FOR i: CARDINAL IN [0..LENGTH[targets])
DO IF EndsWith[wanted, targets[i]] THEN RETURN[FALSE]; ENDLOOP;
WriteChar[Ascii.CR]; WriteChar[Ascii.CR];
WriteString["Registry "L]; WriteString[regGroup];
lookType ← group; LookEnum[wanted, Look];
wanted.length ← 0;
String.AppendString[wanted, "Individuals."L];
String.AppendString[wanted, regGroup];
lookType ← individual; LookEnum[wanted, Look];
done ← FALSE;
END;
LookAtAll: PROC =
{ LookEnum["Groups.gv"L, LookAtRegistry] };
IF Runtime.IsBound[LaurelExecDefs.MakeMenuCommandCallable]
THEN BEGIN
LaurelExecDefs.MakeMenuCommandCallable[user];
LaurelExecDefs.MakeMenuCommandCallable[newMail];
LaurelExecDefs.MakeMenuCommandCallable[mailFile];
LaurelExecDefs.MakeMenuCommandCallable[display];
LaurelExecDefs.MakeMenuCommandCallable[delete];
LaurelExecDefs.MakeMenuCommandCallable[undelete];
LaurelExecDefs.MakeMenuCommandCallable[moveTo];
LaurelExecDefs.MakeMenuCommandCallable[copy];
END;
GetTargets[];
IF LENGTH[targets] # 0 THEN LookAtAll[];
IF BASE[targets] # NIL THEN FreeTargets[];
END.