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