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 INT ← ALL[ALL[ALL[0]]];
totalUsers, totalIfs, totalNsForwarding: INT ← 0;
primary: ARRAY ServerNum OF LIST OF ROPE ← ALL[NIL];
secondary: ARRAY ServerNum OF LIST OF ROPE ← ALL[NIL];
noMailboxes, nsMailboxes, finks: LIST OF ROPE ← NIL;
NSForwarding:
PROC [registry: Registry, user:
ROPE, mailbox:
ROPE]
RETURNS [yes:
BOOL ←
FALSE] = {
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: BOOLEAN ← FALSE;
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;
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[]]; };
}.