-- 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.