-- Transport Mechanism Mail Server - managing records of other servers --
-- [Indigo]<Grapevine>MS>ServerAlloc.mesa
-- Randy Gobbel 19-May-81 12:36:43 --
-- Andrew Birrell 29-Dec-81 15:34:31 --
DIRECTORY
Ascii USING[ CR ],
BodyDefs USING[ RName, RNameSize ],
EnquiryDefs USING[ ],
GlassDefs USING[ Handle ],
Inline USING[ COPY ],
Process USING[ InitializeMonitor ],
ServerDefs USING[ ServerHandle, ServerData, ServerName, ServerType ],
Storage USING[ Node, String ],
String USING[ EquivalentStrings ];
ServerAlloc: MONITOR
IMPORTS BodyDefs, Inline, Process, Storage, String
EXPORTS EnquiryDefs, ServerDefs
SHARES ServerDefs =
BEGIN
OPEN ServerDefs;
noServer: ServerHandle = NIL;
freeChain: ServerHandle ← noServer;
mailChain: ServerHandle ← noServer;
CreateServer: INTERNAL PROCEDURE[ name: ServerName, type: ServerType ]
RETURNS[ res: ServerHandle ] =
BEGIN
chain: POINTER TO ServerHandle = @mailChain;
IF freeChain = noServer
THEN res ← Storage.Node[SIZE[ServerData]]
ELSE BEGIN res ← freeChain; freeChain ← freeChain.next; END;
res.next ← chain↑; chain↑ ← res;
Process.InitializeMonitor[@res.LOCK];
res.type ← type;
WITH name SELECT FROM
rName =>
BEGIN --copy RName into permanent storage--
size: CARDINAL = BodyDefs.RNameSize[value];
place: BodyDefs.RName = Storage.Node[size];
Inline.COPY[value, size, place];
res.name ← [rName[place]];
--MTP-- FOR index: CARDINAL IN [0..place.length)
--MTP-- DO IF place[index] = '. THEN EXIT;
--MTP-- REPEAT --if no dot, asssume foreign--
--MTP-- FINISHED => { res.type ← foreign; res.name ← [connect[place]] }
--MTP-- ENDLOOP;
res.addrKnown ← FALSE;
END;
connect =>
BEGIN --copy connect site into permanent storage --
place: STRING = Storage.String[value.length];
Inline.COPY[@(value.text), (1+value.length)/2, @(place.text)];
place.length ← value.length;
res.name ← [connect[place]];
res.addrKnown ← FALSE;
END;
netAddr =>
BEGIN
res.name ← [netAddr[value]];
res.addr ← value;
res.addrKnown ← TRUE;
END;
ENDCASE => ERROR;
res.up ← TRUE;
res.SL ← NIL;
END;
GetServer: PUBLIC ENTRY PROCEDURE[ name: ServerName, type: ServerType ]
RETURNS[ res: ServerHandle ] =
BEGIN
FOR res ← mailChain, res.next
UNTIL res = noServer
DO IF (WITH wanted: name SELECT FROM
rName =>
(WITH found: res.name SELECT FROM
rName =>
String.EquivalentStrings[found.value, wanted.value],
--MTP-- connect =>
--MTP-- String.EquivalentStrings[found.value, wanted.value],
ENDCASE => FALSE),
connect =>
(WITH found: res.name SELECT FROM
connect =>
String.EquivalentStrings[found.value, wanted.value],
ENDCASE => FALSE),
netAddr =>
(WITH found: res.name SELECT FROM
netAddr =>
found.value = wanted.value,
ENDCASE => FALSE),
ENDCASE => ERROR)
THEN EXIT;
ENDLOOP;
IF res = noServer THEN res ← CreateServer[name,type];
END;
EnumerateAll: PUBLIC ENTRY PROCEDURE[ work: PROCEDURE[ServerHandle]] =
BEGIN
ENABLE UNWIND => NULL;
FOR ptr: ServerHandle ← mailChain, ptr.next UNTIL ptr = noServer
DO work[ptr] ENDLOOP;
END;
RemoteServers: PUBLIC PROC[ str: GlassDefs.Handle ] =
BEGIN
OPEN str;
FOR ptr: ServerHandle ← mailChain, ptr.next UNTIL ptr = noServer
DO WriteChar[Ascii.CR];
WriteString[ WITH this: ptr.name SELECT FROM
rName => this.value,
connect => this.value,
netAddr => "[net address]"L,
ENDCASE => "[bad name]"L ];
WriteString[": "L];
WriteString[IF ptr.up THEN "up"L ELSE "down"L];
WriteString[", handle="L];
WriteDecimal[LOOPHOLE[ptr]];
ENDLOOP;
END;
END.