-- GrapevineUser (Cedar) - Client access to the R-Server database -- GVNamesImpl.mesa -- Andrew Birrell July 8, 1982 8:33 am DIRECTORY BodyDefs USING[ maxRNameLength, Password, RName, RNameSize ], ConvertUnsafe USING[ AppendRope, ToRope ], GVBasics USING[ Connect, GVString, Password, Remark, RName, oldestTime, Timestamp ], GVNames USING[ AuthenticateInfo, ConnectInfo, ExpandInfo, GetEntryInfo, GetEntryList, ListType, MemberInfo, Membership, MembershipGrade, MembershipLevel, NameType, Outcome, RemarkInfo, ReporterProc, RListHandle, SetServerInfo, StampInfo], NameInfoDefs USING[ AuthenticateKey, GetConnect, GetRemark, IsInList ], NameInfoPrivate USING[ GetCompound, SetServer ], NameUpdateDefs USING[ Update ], ProtocolDefs USING[ Handle, MakeKey, ReceiveByte, ReceiveCount, ReceivePassword, ReceiveRName, ReceiveTimestamp, RNameType, RSOperation ], PupDefs USING[ GetPupAddress, PupAddress, PupNameTrouble ], Rope USING[ Find, Length, ROPE, Substr ]; GVNamesImpl: CEDAR PROGRAM IMPORTS BodyDefs, ConvertUnsafe, NameInfoPrivate, NameInfoDefs, NameUpdateDefs, ProtocolDefs, PupDefs, Rope EXPORTS GVBasics, GVNames SHARES NameUpdateDefs = BEGIN --GVBasics.--MakeKey: PUBLIC PROC[r: Rope.ROPE] RETURNS[GVBasics.Password] = TRUSTED BEGIN p: STRING = [64]; ConvertUnsafe.AppendRope[p,r]; RETURN[ProtocolDefs.MakeKey[p]] END; ReceiveRList: PROC[str: ProtocolDefs.Handle] RETURNS[gvList: GVNames.RListHandle, count: CARDINAL] = TRUSTED BEGIN s: BodyDefs.RName = [BodyDefs.maxRNameLength]; words: CARDINAL _ ProtocolDefs.ReceiveCount[str]; tail: GVNames.RListHandle _ NIL; gvList _ NIL; count _ 0; WHILE words > 0 DO count _ count+1; ProtocolDefs.ReceiveRName[str, s]; words _ words - BodyDefs.RNameSize[s]; IF tail = NIL THEN { gvList _ CONS[ConvertUnsafe.ToRope[s],NIL]; tail _ gvList } ELSE { tail.rest _ CONS[ConvertUnsafe.ToRope[s],NIL]; tail _ tail.rest }; ENDLOOP; END; ReceiveStampList: PROC[str: ProtocolDefs.Handle] RETURNS[list: LIST OF GVBasics.Timestamp] = TRUSTED BEGIN words: CARDINAL _ ProtocolDefs.ReceiveCount[str]; tail: LIST OF GVBasics.Timestamp _ NIL; list _ NIL; WHILE words > 0 DO stamp: GVBasics.Timestamp = ProtocolDefs.ReceiveTimestamp[str]; words _ words - SIZE[GVBasics.Timestamp]; IF tail = NIL THEN { list _ CONS[stamp,NIL]; tail _ list } ELSE { tail.rest _ CONS[stamp,NIL]; tail _ tail.rest }; ENDLOOP; END; Expand: PUBLIC PROC[name: GVBasics.RName, oldStamp: GVBasics.Timestamp _ GVBasics.oldestTime] RETURNS[ GVNames.ExpandInfo ] = TRUSTED BEGIN s: BodyDefs.RName = [BodyDefs.maxRNameLength]; info: GVNames.NameType; gvList: GVNames.RListHandle _ NIL; count: CARDINAL; Receive: UNSAFE PROC[str: ProtocolDefs.Handle] = { [gvList,count] _ ReceiveRList[str] }; stamp: GVBasics.Timestamp; IF Rope.Length[name] > BodyDefs.maxRNameLength THEN RETURN[[notFound[]]]; ConvertUnsafe.AppendRope[s, name]; [info, stamp] _ NameInfoPrivate.GetCompound[s, oldStamp, Expand, Receive]; SELECT info FROM noChange => RETURN[[noChange[]]]; group => RETURN[[group[gvList, stamp, count]]]; individual => RETURN[[individual[gvList, stamp, count]]]; notFound => RETURN[[notFound[]]]; allDown => RETURN[[allDown[]]]; ENDCASE => ERROR; END; GetList: PUBLIC PROC[name: GVBasics.RName, oldStamp: GVBasics.Timestamp, list: GVNames.ListType] RETURNS[GVNames.MemberInfo] = TRUSTED BEGIN s: BodyDefs.RName = [BodyDefs.maxRNameLength]; info: GVNames.NameType; gvList: GVNames.RListHandle _ NIL; count: CARDINAL; Receive: UNSAFE PROC[str: ProtocolDefs.Handle] = { [gvList,count] _ ReceiveRList[str] }; stamp: GVBasics.Timestamp; IF Rope.Length[name] > BodyDefs.maxRNameLength THEN RETURN[[notFound[]]]; ConvertUnsafe.AppendRope[s, name]; [info, stamp] _ NameInfoPrivate.GetCompound[s, oldStamp, SELECT list FROM members => ReadMembers, owners => ReadOwners, friends => ReadFriends, ENDCASE => ERROR, Receive]; SELECT info FROM noChange => RETURN[[noChange[]]]; group => RETURN[[group[gvList, stamp, count]]]; individual => RETURN[[individual[]]]; notFound => RETURN[[notFound[]]]; allDown => RETURN[[allDown[]]]; ENDCASE => ERROR; END; GetEntry: PUBLIC PROC[name: GVBasics.RName, reporter: GVNames.ReporterProc _ NIL] RETURNS[ rc: GVNames.NameType[group..allDown], info: REF GVNames.GetEntryInfo] = TRUSTED BEGIN MyReporter: PROC[report: STRING] = TRUSTED { reporter[ConvertUnsafe.ToRope[report]] }; s: BodyDefs.RName = [BodyDefs.maxRNameLength]; Receive: PROC[str: ProtocolDefs.Handle] = TRUSTED BEGIN ENABLE UNWIND => info _ NEW[GVNames.GetEntryInfo _ [,,notFound[]]]; ReceiveRope: PROC RETURNS[ GVBasics.GVString ] = TRUSTED { ProtocolDefs.ReceiveRName[str, s]; RETURN[ ConvertUnsafe.ToRope[s] ] }; ReceiveFunnyString: PROC RETURNS[ GVBasics.GVString ] = TRUSTED BEGIN s.length _ ProtocolDefs.ReceiveCount[str]; FOR i: CARDINAL IN [0..s.length) DO s[i] _ LOOPHOLE[ProtocolDefs.ReceiveByte[str]] ENDLOOP; IF s.length MOD 2 # 0 THEN [] _ ProtocolDefs.ReceiveByte[str]; RETURN[ ConvertUnsafe.ToRope[s] ]; END; ReceiveList: PROC RETURNS[ list: GVNames.GetEntryList ] = TRUSTED BEGIN list.current _ ReceiveRList[str].gvList; list.currentStamps _ ReceiveStampList[str]; list.deleted _ ReceiveRList[str].gvList; list.deletedStamps _ ReceiveStampList[str]; END; type: ProtocolDefs.RNameType; stamp: GVBasics.Timestamp; [] _ ProtocolDefs.ReceiveCount[str]; -- number of components -- [] _ ProtocolDefs.ReceiveCount[str]; -- component length -- stamp _ ProtocolDefs.ReceiveTimestamp[str]; type _ LOOPHOLE[ProtocolDefs.ReceiveCount[str]]; info _ NEW[GVNames.GetEntryInfo _ SELECT type FROM group => [,,group[,,,]], individual => [,,individual[,,,,,]], notFound => [,,notFound[]], dead => [,,dead[]], ENDCASE => ERROR]; info.name _ ReceiveRope[]; info.stamp _ stamp; WITH i: info SELECT FROM group => BEGIN [] _ ProtocolDefs.ReceiveCount[str]; -- component length -- i.remarkStamp _ ProtocolDefs.ReceiveTimestamp[str]; i.remark _ ReceiveFunnyString[]; i.members _ ReceiveList[]; i.owners _ ReceiveList[]; i.friends _ ReceiveList[]; END; individual => BEGIN [] _ ProtocolDefs.ReceiveCount[str]; -- component length -- i.passwordStamp _ ProtocolDefs.ReceiveTimestamp[str]; i.password _ ProtocolDefs.ReceivePassword[str,]; [] _ ProtocolDefs.ReceiveCount[str]; -- component length -- i.connectStamp _ ProtocolDefs.ReceiveTimestamp[str]; i.connect _ ReceiveFunnyString[]; i.forward _ ReceiveList[]; i.sites _ ReceiveList[]; END; ENDCASE => NULL; END; info _ NEW[GVNames.GetEntryInfo _ [,,notFound[]]]; IF Rope.Length[name] > BodyDefs.maxRNameLength THEN rc _ notFound ELSE BEGIN ConvertUnsafe.AppendRope[s, name]; rc _ NameInfoPrivate.GetCompound[s, GVBasics.oldestTime, ReadEntry, Receive, IF reporter = NIL THEN NIL ELSE MyReporter].info; END; END; CheckStamp: PUBLIC PROC[name: GVBasics.RName, oldStamp: GVBasics.Timestamp _ GVBasics.oldestTime, reporter: GVNames.ReporterProc _ NIL] RETURNS[ info: GVNames.StampInfo ] = TRUSTED BEGIN MyReporter: PROC[report: STRING] = TRUSTED { reporter[ConvertUnsafe.ToRope[report]] }; Receive: PROC[ProtocolDefs.Handle] = TRUSTED {}; s: BodyDefs.RName = [BodyDefs.maxRNameLength]; IF Rope.Length[name] > BodyDefs.maxRNameLength THEN RETURN[notFound]; ConvertUnsafe.AppendRope[s, name]; info _ NameInfoPrivate.GetCompound[s, oldStamp, CheckStamp, Receive, IF reporter = NIL THEN NIL ELSE MyReporter].info; END; GetConnect: PUBLIC PROC[name: GVBasics.RName] RETURNS[info: GVNames.ConnectInfo, connect: GVBasics.Connect] = TRUSTED BEGIN s: BodyDefs.RName = [BodyDefs.maxRNameLength]; IF Rope.Length[name] > BodyDefs.maxRNameLength THEN RETURN[notFound,NIL]; ConvertUnsafe.AppendRope[s, name]; info _ NameInfoDefs.GetConnect[s,s]; IF info = individual THEN connect _ ConvertUnsafe.ToRope[s] ELSE connect _ NIL; END; GetRemark: PUBLIC PROC[name: GVBasics.RName] RETURNS[info: GVNames.RemarkInfo, remark: GVBasics.Remark] = TRUSTED BEGIN s: BodyDefs.RName = [BodyDefs.maxRNameLength]; IF Rope.Length[name] > BodyDefs.maxRNameLength THEN RETURN[notFound,NIL]; ConvertUnsafe.AppendRope[s, name]; info _ NameInfoDefs.GetRemark[s,s]; IF info = group THEN remark _ ConvertUnsafe.ToRope[s] ELSE remark _ NIL; END; AuthenticateKey: PUBLIC PROC[name: GVBasics.RName, key: GVBasics.Password] RETURNS[ info: GVNames.AuthenticateInfo ] = TRUSTED BEGIN s: BodyDefs.RName = [BodyDefs.maxRNameLength]; IF Rope.Length[name] > BodyDefs.maxRNameLength THEN RETURN[notFound]; ConvertUnsafe.AppendRope[s, name]; info _ NameInfoDefs.AuthenticateKey[s, key]; END; IsInList: PUBLIC PROC[name: GVBasics.RName, member: GVBasics.RName, level: GVNames.MembershipLevel, grade: GVNames.MembershipGrade, acl: GVNames.ListType] RETURNS[GVNames.Membership] = TRUSTED BEGIN s: BodyDefs.RName = [BodyDefs.maxRNameLength]; m: BodyDefs.RName = [BodyDefs.maxRNameLength]; IF Rope.Length[name] > BodyDefs.maxRNameLength THEN RETURN[notGroup]; IF Rope.Length[member] > BodyDefs.maxRNameLength THEN RETURN[no]; ConvertUnsafe.AppendRope[s, name]; ConvertUnsafe.AppendRope[m, member]; RETURN[NameInfoDefs.IsInList[s, m, level, grade, acl]] END; Update: PUBLIC PROC[user: GVBasics.RName, password: GVBasics.Password, op: ProtocolDefs.RSOperation, target: GVBasics.RName, value: GVBasics.GVString _ NIL, newPwd: GVBasics.Password _ NULL, reporter: GVNames.ReporterProc _ NIL] RETURNS[GVNames.Outcome] = TRUSTED BEGIN MyReporter: PROC[report: STRING] = TRUSTED { reporter[ConvertUnsafe.ToRope[report]] }; u: BodyDefs.RName = [BodyDefs.maxRNameLength]; t: BodyDefs.RName = [BodyDefs.maxRNameLength]; v: BodyDefs.RName = [BodyDefs.maxRNameLength]; IF Rope.Length[user] > BodyDefs.maxRNameLength THEN RETURN[badPwd]; IF Rope.Length[target] > BodyDefs.maxRNameLength THEN RETURN[notFound]; IF Rope.Length[value] > BodyDefs.maxRNameLength THEN value _ Rope.Substr[value, 0, BodyDefs.maxRNameLength]; ConvertUnsafe.AppendRope[u, user]; ConvertUnsafe.AppendRope[t, target]; ConvertUnsafe.AppendRope[v, value]; RETURN[ NameUpdateDefs.Update[u, password, op, t, v, newPwd, IF reporter = NIL THEN NIL ELSE MyReporter] ] END; SetServer: PUBLIC PROC[name: Rope.ROPE] RETURNS[ info: GVNames.SetServerInfo ] = TRUSTED BEGIN s: STRING = [64]; addr: PupDefs.PupAddress; IF Rope.Find[name, "."] >= 0 THEN BEGIN connectInfo: GVNames.ConnectInfo; [connectInfo, name] _ GetConnect[name]; SELECT connectInfo FROM allDown => RETURN[allDown]; individual => NULL; group, notFound => RETURN[badName]; ENDCASE => ERROR; END; IF Rope.Length[name] > s.maxlength THEN RETURN[badName]; ConvertUnsafe.AppendRope[s, name]; info _ ok; PupDefs.GetPupAddress[@addr, s ! PupDefs.PupNameTrouble => BEGIN info _ SELECT code FROM noRoute => noRoute, noResponse => allDown, errorFromServer => badName, ENDCASE => ERROR; CONTINUE END ]; IF info = ok THEN NameInfoPrivate.SetServer[addr]; END; END.