InboxCount.mesa (derived from GVWatcher.mesa), produce inbox counts for each server/registry
M. D. Schroeder, December 31, 1982 4:55 pm
Hal Murray, April 7, 1986 1:01:41 am PST
John Larson, February 16, 1987 2:58:14 pm PST
DIRECTORY
BasicTime USING [Now],
GVNames USING [GetEntry, GetEntryInfo, GetMembers, MemberInfo, NameType, RListHandle],
IO USING [int, PutF, PutRope, STREAM, rope, time],
Process USING [Detach],
Rope USING [Cat, Equal, Fetch, Find, Length, ROPE, Substr],
ViewerIO USING [CreateViewerStreams];


Beware; manual editing is required before running this tool

InboxCount: CEDAR PROGRAM
IMPORTS BasicTime, IO, GVNames, Process, Rope, ViewerIO
SHARES GVNames = {
ROPE: TYPE = Rope.ROPE;
AppendRopeToList: PROC [list: LIST OF ROPE, rope: ROPE] RETURNS [LIST OF ROPE] =
BEGIN
IF list = NIL THEN RETURN[CONS[rope, NIL]];
FOR temp: LIST OF ROPE ← list, temp.rest DO
IF temp.rest = NIL THEN {
temp.rest ← CONS[rope, NIL];
RETURN[list]; };
ENDLOOP;
END;
FindRegistry: PROC [name: ROPE] RETURNS [registry: ROPE] =
BEGIN
length: INT ← Rope.Length[name];
FOR i: INT DECREASING IN [0 .. length) DO
IF Rope.Fetch[name, i] = '. THEN RETURN[Rope.Substr[name, i+1, length - i-1]];
REPEAT FINISHED => RETURN[NIL];
ENDLOOP;
END;
Registry: TYPE = {pa, fx, pasa, es, henr, wbst, dlos, rx, xrcc, eosa, guest, osda, chi};
BoxNum: TYPE = [0..2);
registry: ARRAY Registry OF ROPE = [
pa: "PA",
fx: "FX", pasa: "Pasa",
es: "ES",
henr: "Henr",
wbst: "Wbst",
dlos: "Dlos", rx: "RX", xrcc: "XRCC",
eosa: "EOSA", guest: "Guest", osda: "OSDA", chi: "CHI"];
expected: ARRAY Registry OF LIST OF ROPE = [
pa: LIST["OSBUNorth", "OSBUBayshore", "Sunnyvale", "PARC", "rdes", "sbderx", "esxc16", "ns", "SCB1Versatec", "ESCP8", "DlosLV", "SanDiegoXCSS"],
fx: LIST["IWAFX", "ShinjukuMizunoFX", "pavisitors"],
pasa: LIST["XSIS", "XSISHQ", "XOSMAR", "ns"],
es: LIST["OSBUSouth", "ElSegundo", "osdassociates", "ESCP8", "ESM8", "ESXC15", "ESXC16", "esxcost", "ESGSDWCO", "SanDiegoXCSS", "osbunorth", "ns"],
henr: LIST["WBST139", "ns"],
wbst: LIST["Roch", "Wbst102A", "Wbst128", "Wbst129","Roch805","Wbst311", "WBST139", "ns"],
dlos: LIST["dloslv", "dloslc", "dlosce", "DlosNSC", "Dloslv-Comm", "OSService", "dloscss", "dlosEtron"],
rx: LIST["OSBURX", "RXHRX", "SBDERX", "WGCERX", "BUSRX", "SBDRXN", "AYLTSDRX", "SOLNAMORXS", "IHAIL", "CB19RXF", "EspooRXSF", "HKRXS", "ZurichRXCH", "osbuNorth"],
xrcc: LIST["XRCC-NS", "Wbst147"],
eosa: NIL,
guest: NIL,
osda: LIST["pavisitors"],
chi: NIL];

TotalRec: TYPE = RECORD [i, ifs, ns: INT ← 0];

totals: ARRAY Registry OF TotalRec ← [];

ServerNum: TYPE = [0..21);
server: ARRAY ServerNum OF ROPE = [
"Cabernet.ms", "Chardonnay.ms", "Salvador.ms", "Semillon.ms",
"Burger.ms", "Riesling.ms", "Koshu.ms", "PinotNoir.ms",
"Concord.ms", "Mission.ms", "Gamay.ms",
"CheninBlanc.ms", "Flora.ms", "Muscat.ms", "Catawba.ms",
"Aurora.ms", "BacoNoir.ms",
"Barbera.ms", "deChaunac.ms",
"NoMailboxes.ms", "Other.ms"];
columnsPerPage: NAT = 7;
pages: NAT = (Registry.LAST.ORD+columnsPerPage)/columnsPerPage;
data: ARRAY ServerNum OF ARRAY Registry OF ARRAY BoxNum OF INTALL[ALL[ALL[0]]];
totalUsers, totalIfs, totalNsForwarding: INT ← 0;
primary: ARRAY ServerNum OF LIST OF ROPEALL[NIL];
secondary: ARRAY ServerNum OF LIST OF ROPEALL[NIL];
noMailboxes, nsMailboxes, finks: LIST OF ROPENIL;
NSForwarding: PROC [registry: Registry, user: ROPE, mailbox: ROPE] RETURNS [yes: BOOLFALSE] = {
target: ROPE ← FindRegistry[mailbox];
FOR ok: LIST OF ROPE ← expected[registry], ok.rest UNTIL ok = NIL DO
IF Rope.Equal[target, ok.first, FALSE] THEN RETURN[TRUE];
REPEAT FINISHED => RETURN[FALSE];
ENDLOOP;
};
DoRegistry: PROC [r: Registry, g: group GVNames.MemberInfo] = {
individuals, ifs, forwarding, nsForwarding, empty: INT ← 0;
FOR mbrs: GVNames.RListHandle ← g.members, mbrs.rest UNTIL mbrs=NIL DO
rc: GVNames.NameType;
info: REF GVNames.GetEntryInfo;
userName: ROPE ← mbrs.first;
[rc, info] ← GVNames.GetEntry[userName];
IF rc # individual THEN ERROR;
WITH info SELECT FROM
i: REF GVNames.GetEntryInfo[individual] =>
BEGIN
b: BoxNum ← 0;
expectNone: BOOLEANFALSE;
forward: LIST OF ROPE ← i.forward.current;
boxes: LIST OF ROPE ← i.sites.current;
individuals ← individuals + 1;
IF forward # NIL THEN {
boxes ← NIL;
SELECT TRUE FROM
forward.rest # NIL => forwarding ← forwarding + 1;
Rope.Equal[forward.first, "NoMailboxes.ms", FALSE] => {
noMailboxes ← AppendRopeToList[noMailboxes, userName];
forward ← NIL;
ifs ← ifs + 1;
expectNone ← TRUE; };
NSForwarding[r, userName, forward.first] => {
nsMailboxes ← AppendRopeToList[nsMailboxes, userName];
nsForwarding ← nsForwarding + 1;
forward ← NIL;
expectNone ← TRUE; };
ENDCASE => forwarding ← forwarding + 1; };
FOR sites: GVNames.RListHandle ← forward, sites.rest UNTIL sites=NIL DO
site: ROPE = sites.first;
IF site.Find["@"] # -1 THEN
out.PutF[" %g has Arpanet forwarding to %g. ***\n", IO.rope[userName], IO.rope[site]]
ELSE out.PutF[" %g has forwarding to %g.\n", IO.rope[userName], IO.rope[site]];
ENDLOOP; --i.sites--
IF boxes = NIL AND forward = NIL AND ~expectNone THEN {
empty ← empty + 1;
finks ← AppendRopeToList[finks, userName]; };
FOR sites: GVNames.RListHandle ← boxes, sites.rest UNTIL sites=NIL DO
site: ROPE = sites.first;
FOR s: ServerNum IN ServerNum DO
IF Rope.Equal[site, server[s], FALSE] THEN {
data[s][r][b] ← data[s][r][b] + 1;
IF b = 0 THEN primary[s] ← AppendRopeToList[primary[s], userName]
ELSE secondary[s] ← AppendRopeToList[secondary[s], userName];
EXIT};
REPEAT FINISHED => {
data[LAST[ServerNum]][r][b] ← data[LAST[ServerNum]][r][b] + 1;
out.PutF[" %g has a funny mailbox: %g. ****\n", IO.rope[userName], IO.rope[site]]; };
ENDLOOP; --s--
IF b # LAST[BoxNum] THEN b ← b + 1;
ENDLOOP; --i.sites--
END; --individual--
ENDCASE => ERROR;
ENDLOOP; --g.members--
out.PutF[" There are %g individuals in the %g registry.\n", IO.int[individuals], IO.rope[registry[r]]];
IF forwarding # 0 THEN out.PutF[" %g have forwarding.\n", IO.int[forwarding]];
IF nsForwarding # 0 THEN out.PutF[" %g have forwarding to NS mail addresses.\n", IO.int[nsForwarding]];
IF empty # 0 THEN out.PutF[" %g have no mailboxes.\n", IO.int[empty]];
IF noMailboxes # NIL THEN {
out.PutRope[" The following individuals have forwarding to NoMailboxes.ms: "];
FOR none: LIST OF ROPE ← noMailboxes, none.rest UNTIL none = NIL DO
IF none # noMailboxes THEN out.PutF[", "];
out.PutF["%g", IO.rope[none.first]];
ENDLOOP;
out.PutF[".\n"];
noMailboxes ← NIL; };
IF nsMailboxes # NIL THEN {
out.PutRope[" The following individuals have forwarding to NS Mailboxes: "];
FOR none: LIST OF ROPE ← nsMailboxes, none.rest UNTIL none = NIL DO
IF none # nsMailboxes THEN out.PutF[", "];
out.PutF["%g", IO.rope[none.first]];
ENDLOOP;
out.PutF[".\n"];
nsMailboxes ← NIL; };
IF finks # NIL THEN {
out.PutRope[" ****** The following individuals have no mailboxes: "];
FOR fink: LIST OF ROPE ← finks, fink.rest UNTIL fink = NIL DO
IF fink # finks THEN out.PutF[", "];
out.PutF["%g", IO.rope[fink.first]];
ENDLOOP;
out.PutF[".\n"];
finks ← NIL; };
out.PutF["\n"];
totals[r].i ← individuals - forwarding - empty - ifs;
totals[r].ifs ← ifs;
totals[r].ns ← nsForwarding;
totalUsers ← totalUsers + individuals - forwarding - empty - ifs;
totalIfs ← totalIfs + ifs;
totalNsForwarding ← totalNsForwarding + nsForwarding;
};
out: IO.STREAM = ViewerIO.CreateViewerStreams["Inbox Count"].out;
DoIt: PROC = {
out.PutF["\n%t Inbox counter started.\n\n", IO.time[] ];
FOR r: Registry IN Registry DO
out.PutF["%t Working on %g.\n", IO.time[], [rope[registry[r]]] ];
WITH GVNames.GetMembers[Rope.Cat["individuals.", registry[r]]] SELECT FROM
g: GVNames.MemberInfo[group] => DoRegistry[r, g];
ENDCASE => ERROR;
ENDLOOP; --r--
out.PutF["%t Scan Finished.\n", IO.time[]];
out.PutF["\014\n"]; -- This gets everything on one sheet if you use Cedar's Print command
BEGIN 
first: Registry ← Registry.FIRST;
last: Registry ← first;
FOR page: INT IN [0..pages) DO
There must be a better way, but I don't want to get hit with a Bounds Fault
THROUGH [0..columnsPerPage) DO
IF last = Registry.LAST THEN EXIT;
last ← last.SUCC;
ENDLOOP;
out.PutF["\014%15g", [rope[" "]]]; -- blanks --
FOR r: Registry IN [first..last] DO
out.PutF["%-9g", [rope[registry[r]]]];
ENDLOOP;
out.PutRope["\n\n"];
FOR s: ServerNum IN ServerNum DO
serverName: ROPE ← Rope.Substr[server[s], 0, Rope.Length[server[s]]-3];
out.PutF["%-12g", [rope[serverName]]];
FOR r: Registry IN [first..last] DO
out.PutF["%4d%4d ", IO.int[data[s][r][0]], IO.int[data[s][r][1]]];
ENDLOOP;
out.PutRope["\n\n"];
ENDLOOP;
IF last # Registry.LAST THEN first ← last.SUCC;
ENDLOOP;
END;
FOR s: INT IN ServerNum DO
serverName: ROPE ← Rope.Substr[server[s], 0, Rope.Length[server[s]]-3];
out.PutRope["\014\n"];
out.PutF["%g has the following primary mailboxes: ", [rope[serverName]]];
FOR list: LIST OF ROPE ← primary[s], list.rest UNTIL list = NIL DO
IF list # primary[s] THEN out.PutF[", "];
out.PutF["%g", IO.rope[list.first]];
ENDLOOP;
out.PutRope[".\n"];
ENDLOOP;
FOR s: INT IN ServerNum DO
serverName: ROPE ← Rope.Substr[server[s], 0, Rope.Length[server[s]]-3];
out.PutRope["\014\n"];
out.PutF["%g has the following secondary mailboxes: ", [rope[serverName]]];
FOR list: LIST OF ROPE ← secondary[s], list.rest UNTIL list = NIL DO
IF list # secondary[s] THEN out.PutF[", "];
out.PutF["%g", IO.rope[list.first]];
ENDLOOP;
out.PutRope[".\n"];
ENDLOOP;
out.PutRope["\n\nTotals:\n\n"];
out.PutF["There are %g unique users in the system.\n", IO.int[totalUsers]];
out.PutF["%g of these have no mailboxes.\n", IO.int[totalIfs]];
out.PutF["%g are forwarded to NS mail addresses.\n\n\n", IO.int[totalNsForwarding]];
FOR r: Registry IN Registry DO
out.PutF[" %g unique users in %g.\n", IO.int[totals[r].i], [rope[registry[r]]] ];
out.PutF[" %g of these have no mailboxes.\n", IO.int[totals[r].ifs]];
out.PutF[" %g are forwarded to NS mail addresses.\n\n", IO.int[totals[r].ns]];
ENDLOOP;
primary ← ALL[NIL];
secondary ← ALL[NIL]; -- ka wahammy
};
TRUSTED { Process.Detach[FORK DoIt[]]; };
}.