XNSCHImpl.mesa
Copyright Ó 1988, 1989, 1991 by Xerox Corporation. All rights reserved.
Demers, January 27, 1988 11:28:23 am PST
Willie-Sue, February 13, 1989 3:37:56 pm PST
Willie-s, December 10, 1991 1:26 pm PST
DIRECTORY
Basics USING [Card16FromH, HFromCard16, HWORD, Word16],
CHACLOpsP127V1 USING [AddMemberToDomainACL, AddMemberToOrganizationACL, AddMemberToPropertyACL, DeleteMemberFromDomainACL, DeleteMemberFromOrganizationACL, DeleteMemberFromPropertyACL, DomainName, IsInDomainACL, IsInOrganizationACL, IsInPropertyACL, OrganizationName, RetrieveDomainACL, RetrieveOrganizationACL, RetrievePropertyACL],
CHEntriesP0V0 USING [addressList, associatedWorkstation, members],
CHOpsP2V3 USING [AddGroupProperty, AddItemProperty, AddMember, AddSelf, Authenticator, ChangeItem, CreateAlias, CreateObject, DeleteAlias, DeleteMember, DeleteSelf, DeleteObject, DeleteProperty, IsMember, ItemObject, ListAliases, ListAliasesOf, ListDomains, ListDomainsServed, ListObjects, ListOrganizations, ListProperties, LookupObject, NetworkAddressList, RetrieveAddresses, RetrieveItem, RetrieveMembers],
Convert USING [Error, RopeFromXNSAddress, XNSAddressFromRope],
CrRPC USING [BulkDataCheckAbortProc, BulkDataValueProc, BulkDataXferProc, GetRope, Handle, MarshalledRopeHWords, PutRope, ReadBulkDataStream, WriteBulkDataSegment],
IO USING [STREAM],
RefText USING [AppendChar, ObtainScratch, ReleaseScratch],
Rope USING [Cat, Concat, FromRefText, Fetch, IsEmpty, Length, ROPE],
ThisMachineRegistry USING [RegisterThisMachineProcs, ThisMachineProcsRec, ThisMachineRef],
XNS USING [Address, GetThisHost, Host, unknownAddress],
XNSAuth USING [GetIdentityDetails, Identity],
XNSCH USING [Conversation, Element, ElementStreamProc, EnumeratorProc, ErrorCode, InitiateConversation, Item, Name, NameStreamProc, notUsable, Pattern, Properties, PropertyID, TerminateConversation, unspecified, Which],
XNSCHACL USING [AccessList],
XNSCHName USING [FieldTooLong, Name, NameFromRope, RopeFromName],
XNSCHPrivate USING [CallRemote, GetAuthenticator, IsGeneric, NACacheInsert, NACacheLookup, RemoteProc],
XNSCredentials USING [GetIdentity],
XNSRouter USING [GetHops]
;
XNSCHImpl: CEDAR MONITOR
IMPORTS Basics, CHACLOpsP127V1, CHOpsP2V3, Convert, CrRPC, RefText, Rope, ThisMachineRegistry, XNS, XNSAuth, XNSCH, XNSCHName, XNSCHPrivate, XNSCredentials, XNSRouter
EXPORTS XNSCH, XNSCHACL, XNSCHPrivate
This is a monitor only because of the nCache stuff in "Common Lookups".
~ {
OPEN CHEntries: CHEntriesP0V0, CHOps: CHOpsP2V3, CHACLOps: CHACLOpsP127V1;
ROPE: TYPE ~ Rope.ROPE;
Name: TYPE ~ XNSCH.Name;
Pattern: TYPE ~ XNSCH.Pattern;
Element: TYPE ~ XNSCH.Element;
PropertyID: TYPE ~ XNSCH.PropertyID;
Properties: TYPE ~ XNSCH.Properties;
Item: TYPE ~ XNSCH.Item;
Conversation: TYPE ~ XNSCH.Conversation;
AccessList: TYPE ~ XNSCHACL.AccessList;
DomainName: TYPE ~ CHACLOps.DomainName;
OrganizationName: TYPE ~ CHACLOps.OrganizationName;
HWORD: TYPE ~ Basics.HWORD;
RemoteProc: TYPE ~ XNSCHPrivate.RemoteProc;
BulkDataXferProc: TYPE ~ CrRPC.BulkDataXferProc;
BulkDataValueProc: TYPE ~ CrRPC.BulkDataValueProc;
shiftInName: ROPE ~ "CHServers";
chServiceName: Name ~
[organization~shiftInName, domain~shiftInName, object~"Clearinghouse Service"];
Error: PUBLIC ERROR [code: XNSCH.ErrorCode, which: XNSCH.Which] ~ CODE;
Operations on Objects
Add: PUBLIC PROC [c: Conversation, name: Name] ~ {
DoAdd: RemoteProc -- [handle, host] -- ~ {
CHOps.CreateObject[handle, name, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAdd, DomainFromElement[name]];
};
Delete: PUBLIC PROC [c: Conversation, name: Name] ~ {
DoDelete: RemoteProc -- [handle, host] -- ~ {
CHOps.DeleteObject[handle, name, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDelete, DomainFromElement[name]];
};
Lookup: PUBLIC PROC [c: Conversation, pattern: Pattern]
RETURNS [distingName: Name] ~ {
DoLookup: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.LookupObject[handle, pattern,
XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoLookup, DomainFromElement[pattern]];
};
AddAlias: PUBLIC PROC [c: Conversation, name, alias: Name]
RETURNS [distingName: Name] ~ {
DoAddAlias: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.CreateAlias[handle, alias, name,
XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddAlias, DomainFromElement[alias--????--]];
};
DeleteAlias: PUBLIC PROC [c: Conversation, alias: Name]
RETURNS [distingName: Name] ~ {
DoDeleteAlias: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.DeleteAlias[handle, alias,
XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteAlias, DomainFromElement[alias]];
};
ListAliases: PUBLIC PROC [c: Conversation, pattern: Pattern, eachAlias: XNSCH.NameStreamProc] RETURNS [distingName: Name] ~ {
ReadStreamOfNames: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachNameInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachAlias[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachNameInStream]];
};
DoListAliases: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.ListAliasesOf[handle, pattern, ReadStreamOfNames, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoListAliases, DomainFromElement[pattern], FALSE];
};
Operations on Properties
GetProperties: PUBLIC PROC [c: Conversation, pattern: Pattern]
RETURNS [distingName: Name, properties: Properties] ~ {
DoGetProperties: RemoteProc -- [handle, host] -- ~ {
[distinguishedObject~distingName, properties~properties] ¬
CHOps.ListProperties[handle, pattern,
XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoGetProperties, DomainFromElement[pattern]];
};
DeleteProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID]
RETURNS [distingName: Name] ~ {
DoDeleteProperty: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.DeleteProperty[handle, name, pID, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteProperty, DomainFromElement[name]];
};
AddItemProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, item: Item]
RETURNS [distingName: Name] ~ {
DoAddItemProperty: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.AddItemProperty[handle, name, pID, item, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddItemProperty, DomainFromElement[name]];
};
ChangeItemProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, item: Item]
RETURNS [distingName: Name] ~ {
DoChangeItemProperty: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.ChangeItem[handle, name, pID, item, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoChangeItemProperty, DomainFromElement[name]];
};
LookupItemProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID]
RETURNS [distingName: Name, item: Item] ~ {
DoLookupItemProperty: RemoteProc -- [handle, host] -- ~ {
[distinguishedObject~distingName, value~item] ¬
CHOps.RetrieveItem[handle, pattern, pID,
XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoLookupItemProperty, DomainFromElement[pattern]];
};
LookupAddress: PUBLIC PROC [c: Conversation, pattern: Pattern]
RETURNS [distingName: Name, address: XNS.Address] ~ {
DoLookupAddress: RemoteProc -- [handle, host] -- ~ {
item: Item;
addresses: LIST OF XNS.Address;
[distinguishedObject~distingName, value~item] ¬
CHOps.RetrieveItem[handle, pattern, CHEntries.addressList, XNSCHPrivate.GetAuthenticator[c, host]];
addresses ¬ AddressesFromItem[item];
IF addresses # NIL
THEN address ¬ BestAddressInList[addresses]
ELSE address ¬ XNS.unknownAddress;
};
XNSCHPrivate.CallRemote[c, DoLookupAddress, DomainFromElement[pattern]];
};
LookupRopeProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID]
RETURNS [distingName: Name, ropeProperty: ROPE] ~ {
DoLookupRopeProperty: RemoteProc -- [handle, host] -- ~ {
item: Item;
[distinguishedObject~distingName, value~item] ¬
CHOps.RetrieveItem[handle, pattern, pID,
XNSCHPrivate.GetAuthenticator[c, host]];
ropeProperty ¬ RopeFromItem[item];
};
XNSCHPrivate.CallRemote[c, DoLookupRopeProperty, DomainFromElement[pattern]];
};
LookupNameProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID]
RETURNS [distingName: Name, nameProperty: Name] ~ {
DoLookupNameProperty: RemoteProc -- [handle, host] -- ~ {
item: Item;
[distinguishedObject~distingName, value~item] ¬
CHOps.RetrieveItem[handle, pattern, pID,
XNSCHPrivate.GetAuthenticator[c, host]];
nameProperty ¬ ElementFromItem[item];
};
XNSCHPrivate.CallRemote[c, DoLookupNameProperty, DomainFromElement[pattern]];
};
HeAborted: ERROR ~ CODE;
AddGroupProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID,
enumerator: XNSCH.EnumeratorProc]
RETURNS [distingName: Name] ~ {
WriteStreamOfElements: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
heAborted: BOOL ¬ FALSE;
EachElement: PROC [element: Element] ~ {
WriteTheElement: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOL]
~ { PutElement[s, element]; RETURN [FALSE] };
[heAborted~heAborted] ¬ CrRPC.WriteBulkDataSegment[h, s, checkAbort, WriteTheElement, 1];
IF heAborted THEN ERROR HeAborted[];
};
enumerator[EachElement ! HeAborted => CONTINUE ];
IF NOT heAborted THEN [] ¬ CrRPC.WriteBulkDataSegment[h, s, NIL, NIL, 0];
RETURN [FALSE] };
DoAddGroupProperty: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.AddGroupProperty[handle, name, pID, WriteStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddGroupProperty, DomainFromElement[name]];
};
AddMember: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, member: Element]
RETURNS [distingName: Name] ~ {
DoAddMember: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.AddMember[handle, name, pID, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddMember, DomainFromElement[name]];
};
AddSelf: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID]
RETURNS [distingName: Name] ~ {
DoAddSelf: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.AddSelf[handle, name, pID,
XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddSelf, DomainFromElement[name]];
};
DeleteMember: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, member: Element]
RETURNS [distingName: Name] ~ {
DoDeleteMember: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.DeleteMember[handle, name, pID, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteMember, DomainFromElement[name]];
};
DeleteSelf: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID]
RETURNS [distingName: Name] ~ {
DoDeleteSelf: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.DeleteSelf[handle, name, pID,
XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteSelf, DomainFromElement[name]];
};
ListMembers: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID,
eachMember: XNSCH.ElementStreamProc]
RETURNS [distingName: Name] ~ {
ReadStreamOfElements: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachElementInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachMember[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachElementInStream]];
};
DoListMembers: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHOps.RetrieveMembers[handle, pattern, pID, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoListMembers, DomainFromElement[pattern], FALSE];
};
IsMember: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, member: Element]
RETURNS [distingName: Name, isMember: BOOL] ~ {
DoIsMember: RemoteProc -- [handle, host] -- ~ {
[isMember~isMember, distinguishedObject~distingName] ¬
CHOps.IsMember[handle, pattern, pID, XNSCH.notUsable, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoIsMember, DomainFromElement[pattern]];
};
IsMemberClosure: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, member: Element, pID2: PropertyID]
RETURNS [distingName: Name, isMember: BOOL] ~ {
DoIsMemberClosure: RemoteProc -- [handle, host] -- ~ {
[isMember~isMember, distinguishedObject~distingName] ¬
CHOps.IsMember[handle, pattern, pID, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
IF pID2 = XNSCH.unspecified THEN pID2 ¬ pID;
XNSCHPrivate.CallRemote[c, DoIsMemberClosure, DomainFromElement[pattern]];
};
Enumeration operations
Enumerate: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID,
eachObject: XNSCH.NameStreamProc] ~ {
ReadStreamOfStrings: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachStringInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachObject[[organization~pattern.organization, domain~pattern.domain, object~CrRPC.GetRope[s]]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachStringInStream]];
};
DoEnumerate: RemoteProc -- [handle, host] -- ~ {
CHOps.ListObjects[handle, pattern, pID, ReadStreamOfStrings, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoEnumerate, DomainFromElement[pattern], FALSE];
};
EnumerateAliases: PUBLIC PROC [c: Conversation, pattern: Pattern,
eachName: XNSCH.NameStreamProc] ~ {
ReadStreamOfStrings: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachStringInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachName[[organization~pattern.organization, domain~pattern.domain, object~CrRPC.GetRope[s]]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachStringInStream]];
};
DoEnumerateAliases: RemoteProc -- [handle, host] -- ~ {
CHOps.ListAliases[handle, pattern, ReadStreamOfStrings, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoEnumerateAliases, DomainFromElement[pattern], FALSE];
};
EnumerateOrganizations: PUBLIC PROC [c: Conversation, pattern: Pattern,
eachOrganization: XNSCH.ElementStreamProc] ~ {
ReadStreamOfStrings: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachStringInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachOrganization[[organization~CrRPC.GetRope[s], domain~NIL, object~NIL]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachStringInStream]];
};
DoEnumerateOrganizations: RemoteProc -- [handle, host] -- ~ {
CHOps.ListOrganizations[handle, pattern.organization, ReadStreamOfStrings, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoEnumerateOrganizations, NIL, FALSE];
};
EnumerateDomains: PUBLIC PROC [c: Conversation, pattern: Pattern,
eachDomain: XNSCH.ElementStreamProc] ~ {
ReadStreamOfStrings: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachStringInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachDomain[[organization~pattern.organization, domain~CrRPC.GetRope[s], object~NIL]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachStringInStream]];
};
DoEnumerateDomains: RemoteProc -- [handle, host] -- ~ {
CHOps.ListDomains[handle, [organization~pattern.organization, domain~pattern.domain], ReadStreamOfStrings, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoEnumerateDomains, DomainFromOrgElement[pattern], FALSE];
};
Operations on Property ACLs
ListMembersOfPropertyACL: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, acl: AccessList, eachMember: XNSCH.ElementStreamProc]
RETURNS [distingName: Name] ~ {
ReadStreamOfElements: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachElementInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachMember[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachElementInStream]];
};
DoListMembersOfPropertyACL: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHACLOps.RetrievePropertyACL[handle, pattern, pID, acl, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoListMembersOfPropertyACL, DomainFromElement[pattern], FALSE];
};
IsMemberOfPropertyACLClosure: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, acl: AccessList, member: Element, pID2: PropertyID]
RETURNS [distingName: Name, isMember: BOOL] ~ {
DoIsMemberOfPropertyACLClosure: RemoteProc -- [handle, host] -- ~ {
[inACL~isMember, distinguishedObject~distingName] ¬
CHACLOps.IsInPropertyACL[handle, pattern, pID, acl, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
IF pID2 = XNSCH.unspecified THEN pID2 ¬ pID;
XNSCHPrivate.CallRemote[c, DoIsMemberOfPropertyACLClosure, DomainFromElement[pattern]];
};
AddMemberToPropertyACL: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, acl: AccessList, member: Element]
RETURNS [distingName: Name] ~ {
DoAddMemberToPropertyACL: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHACLOps.AddMemberToPropertyACL[handle, name, pID, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddMemberToPropertyACL, DomainFromElement[name]];
};
DeleteMemberFromPropertyACL: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, acl: AccessList, member: Element]
RETURNS [distingName: Name] ~ {
DoDeleteMemberFromPropertyACL: RemoteProc -- [handle, host] -- ~ {
distingName ¬ CHACLOps.DeleteMemberFromPropertyACL[handle, name, pID, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteMemberFromPropertyACL, DomainFromElement[name]];
};
Operations on Domain ACLs
ListMembersOfDomainACL: PUBLIC PROC [c: Conversation, domain: Name, acl: AccessList, eachMember: XNSCH.ElementStreamProc] ~ {
domainName: DomainName ~ [domain~domain.domain, organization~domain.organization];
ReadStreamOfElements: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachElementInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachMember[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachElementInStream]];
};
DoListMembersOfDomainACL: RemoteProc -- [handle, host] -- ~ {
[] ¬ CHACLOps.RetrieveDomainACL[handle, domainName, acl, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]]; -- RETURNS SOMETHING ????
};
XNSCHPrivate.CallRemote[c, DoListMembersOfDomainACL, DomainFromElement[domain], FALSE];
};
IsMemberOfDomainACLClosure: PUBLIC PROC [c: Conversation, domain: Name, acl: AccessList, member: Element, pID2: PropertyID]
RETURNS [isMember: BOOL] ~ {
domainName: DomainName ~ [domain~domain.domain, organization~domain.organization];
DoIsMemberOfDomainACLClosure: RemoteProc -- [handle, host] -- ~ {
isMember ¬ CHACLOps.IsInDomainACL[handle, domainName, acl, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
IF pID2 = XNSCH.unspecified THEN pID2 ¬ CHEntries.members;
XNSCHPrivate.CallRemote[c, DoIsMemberOfDomainACLClosure, DomainFromElement[domain]];
};
AddMemberToDomainACL: PUBLIC PROC [c: Conversation, domain: Name, acl: AccessList, member: Element] ~ {
domainName: DomainName ~ [domain~domain.domain, organization~domain.organization];
DoAddMemberToDomainACL: RemoteProc -- [handle, host] -- ~ {
CHACLOps.AddMemberToDomainACL[handle, domainName, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddMemberToDomainACL, DomainFromElement[domain]];
};
DeleteMemberFromDomainACL: PUBLIC PROC [c: Conversation, domain: Name, acl: AccessList, member: Element] ~ {
domainName: DomainName ~ [domain~domain.domain, organization~domain.organization];
DoDeleteMemberFromDomainACL: RemoteProc -- [handle, host] -- ~ {
CHACLOps.DeleteMemberFromDomainACL[handle, domainName, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteMemberFromDomainACL, DomainFromElement[domain]];
};
Operations on Organization ACLs
ListMembersOfOrganizationACL: PUBLIC PROC [c: Conversation, organization: Name, acl: AccessList, eachMember: XNSCH.ElementStreamProc] ~ {
organizationName: OrganizationName ~ organization.organization;
ReadStreamOfElements: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachElementInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachMember[GetElement[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachElementInStream]];
};
DoListMembersOfOrganizationACL: RemoteProc -- [handle, host] -- ~ {
CHACLOps.RetrieveOrganizationACL[handle, organizationName, acl, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoListMembersOfOrganizationACL, DomainFromOrgElement[organization], FALSE];
};
IsMemberOfOrganizationACLClosure: PUBLIC PROC [c: Conversation, organization: Name, acl: AccessList, member: Element, pID2: PropertyID]
RETURNS [isMember: BOOL] ~ {
organizationName: OrganizationName ~ organization.organization;
DoIsMemberOfOrganizationACLClosure: RemoteProc -- [handle, host] -- ~ {
isMember ¬ CHACLOps.IsInOrganizationACL[handle, organizationName, acl, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
IF pID2 = XNSCH.unspecified THEN pID2 ¬ CHEntries.members;
XNSCHPrivate.CallRemote[c, DoIsMemberOfOrganizationACLClosure, DomainFromOrgElement[organization]];
};
AddMemberToOrganizationACL: PUBLIC PROC [c: Conversation, organization: Name, acl: AccessList, member: Element] ~ {
organizationName: OrganizationName ~ organization.organization;
DoAddMemberToOrganizationACL: RemoteProc -- [handle, host] -- ~ {
CHACLOps.AddMemberToOrganizationACL[handle, organizationName, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoAddMemberToOrganizationACL, DomainFromOrgElement[organization]];
};
DeleteMemberFromOrganizationACL: PUBLIC PROC [c: Conversation, organization: Name, acl: AccessList, member: Element] ~ {
organizationName: OrganizationName ~ organization.organization;
DoDeleteMemberFromOrganizationACL: RemoteProc -- [handle, host] -- ~ {
CHACLOps.DeleteMemberFromOrganizationACL[handle, organizationName, acl, member, XNSCHPrivate.GetAuthenticator[c, host]];
};
XNSCHPrivate.CallRemote[c, DoDeleteMemberFromOrganizationACL, DomainFromOrgElement[organization]];
};
Common Lookups
LookupAddressFromRopeInner: PROC [rope: ROPE, doClosure: BOOL ¬ FALSE]
RETURNS [distingName: Name ¬ [NIL,NIL,NIL], address: XNS.Address ¬ XNS.unknownAddress, didClosure: BOOL ¬ FALSE]
~ {
c: Conversation ¬ XNSCH.InitiateConversation[];
name: Name;
{
{ ENABLE Convert.Error => CONTINUE;
address ¬ Convert.XNSAddressFromRope[rope];
GOTO Good };
{ ENABLE XNSCHName.FieldTooLong => GOTO Bad;
name ¬ XNSCHName.NameFromRope[rope];
};
DO
{ found: BOOL;
[found, distingName, address] ¬ XNSCHPrivate.NACacheLookup[name];
IF found THEN GOTO Good;
};
{ ENABLE Error => CONTINUE;
[distingName, address] ¬ LookupAddress[c, name];
XNSCHPrivate.NACacheInsert[name, distingName, address]; -- Note we cache direct mappings only, not closure mappings.
GOTO Good };
IF doClosure THEN {
ENABLE Error => CONTINUE;
item: Item;
[item~item] ¬ LookupItemProperty[c~c, pattern~name, pID~CHEntries.associatedWorkstation];
name ¬ ElementFromItem[item];
didClosure ¬ TRUE;
LOOP;
};
GOTO Bad;
ENDLOOP;
EXITS
Good, Bad => NULL;
};
XNSCH.TerminateConversation[c];
};
LookupAddressFromRope: PUBLIC PROC [rope: ROPE]
RETURNS [distingName: Name, address: XNS.Address]
~ {
[distingName~distingName, address~address] ¬
LookupAddressFromRopeInner[rope, FALSE];
};
LookupAddressFromRopeClosure: PUBLIC PROC [rope: ROPE]
RETURNS [distingName: Name, address: XNS.Address, didClosure: BOOL]
~ {
[distingName, address, didClosure] ¬
LookupAddressFromRopeInner[rope, TRUE];
};
Server-Specific Queries
GetServerAddresses: PUBLIC PROC [c: Conversation]
RETURNS [addresses: LIST OF XNS.Address] ~ {
list: CHOps.NetworkAddressList;
DoGetServerAddresses: RemoteProc -- [handle, host] -- ~ {
i: CARDINAL;
list ¬ CHOps.RetrieveAddresses[handle];
i ¬ list.length;
addresses ¬ NIL;
WHILE i > 0 DO
i ¬ i - 1;
addresses ¬ CONS [LOOPHOLE[list.body[i]], addresses];
ENDLOOP;
};
IF XNSCHPrivate.IsGeneric[c] THEN ERROR Error[inappropriateConversation, first];
XNSCHPrivate.CallRemote[c, DoGetServerAddresses, NIL];
};
EnumerateDomainsServed: PUBLIC PROC [c: Conversation,
eachDomain: XNSCH.ElementStreamProc] ~ {
ReadStreamOfDomains: BulkDataXferProc
[h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL];
~ {
EachDomainInStream: BulkDataValueProc
[s: IO.STREAM] RETURNS [abort: BOOLFALSE]
~ { eachDomain[GetDomain[s]] };
RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachDomainInStream]];
};
DoEnumerateDomainsServed: RemoteProc -- [handle, host] -- ~ {
CHOps.ListDomainsServed[handle, ReadStreamOfDomains, XNSCHPrivate.GetAuthenticator[c, host]];
};
IF XNSCHPrivate.IsGeneric[c] THEN ERROR Error[inappropriateConversation, first];
XNSCHPrivate.CallRemote[c, DoEnumerateDomainsServed, NIL];
};
Utilities
(Un)marshalling
These are strange because the Items have already been byte-swapped to internal representation, which can mess up objects like XNS.Addresses that are stored inside them.
adrHWords: CARDINAL ~ BITS[XNS.Address]/BITS[HWORD];
AddressesFromItem: PUBLIC PROC [item: Item]
RETURNS [addresses: LIST OF XNS.Address] ~ {
buf: PACKED ARRAY [0..adrHWords) OF HWORD;
cnt: CARD16;
index: CARDINAL ¬ 1;
IF item.length < 1 THEN RETURN[NIL];
cnt ¬ item.body[0];
IF item.length < 1+cnt*adrHWords THEN RETURN[NIL];
THROUGH [1..cnt] DO
FOR i: CARDINAL IN [0..adrHWords) DO
buf[i] ¬ Basics.HFromCard16[item.body[index]];
index ¬ index + 1;
ENDLOOP;
addresses ¬ CONS[LOOPHOLE[buf], addresses];
ENDLOOP;
};
ItemFromAddresses: PUBLIC PROC [addresses: LIST OF XNS.Address]
RETURNS [item: Item] ~ {
buf: PACKED ARRAY [0..adrHWords) OF HWORD;
index: CARDINAL;
cnt: CARD16 ¬ 0;
FOR temp: LIST OF XNS.Address ¬ addresses, temp.rest WHILE temp # NIL DO
cnt ¬ cnt + 1;
ENDLOOP;
item ¬ NEW[CHOps.ItemObject[1+cnt*adrHWords]];
item.body[0] ¬ cnt;
index ¬ 1;
FOR temp: LIST OF XNS.Address ¬ addresses, temp.rest WHILE temp # NIL DO
buf ¬ LOOPHOLE[temp.first];
FOR i: CARDINAL IN [0..adrHWords) DO
item.body[index] ¬ Basics.Card16FromH[buf[i]];
index ¬ index + 1;
ENDLOOP;
ENDLOOP;
};
RopeFromItem: PUBLIC PROC [item: Item]
RETURNS [rope: ROPE] ~ {
[rope~rope] ¬ RopeFromItemInner[item,0] };
ElementFromItem: PUBLIC PROC [item: Item]
RETURNS [element: Element] ~ {
pos: CARD32;
[rope~element.organization, newPos~pos] ¬ RopeFromItemInner[item, 0];
[rope~element.domain, newPos~pos] ¬ RopeFromItemInner[item, pos];
[rope~element.object] ¬ RopeFromItemInner[item, pos]; };
RopeFromItemInner: PROC [item: Item, pos: CARD32]
RETURNS [rope: ROPE, newPos: CARD32] ~ {
buf: Basics.Word16;
text: REF TEXT;
cnt: CARD32;
IF item.length <= pos THEN RETURN [NIL, pos];
cnt ¬ item.body[pos];
IF (CARD[item.length-pos-1]*BYTES[HWORD]) < cnt THEN RETURN [NIL, pos]; -- ERROR
text ¬ RefText.ObtainScratch[cnt];
newPos ¬ pos+1;
DO
IF cnt = 0 THEN EXIT;
buf.card ¬ item.body[newPos]; newPos ¬ newPos+1;
text ¬ RefText.AppendChar[to~text, from~LOOPHOLE[buf.hi]];
cnt ¬ cnt-1;
IF cnt = 0 THEN EXIT;
text ¬ RefText.AppendChar[to~text, from~LOOPHOLE[buf.lo]];
cnt ¬ cnt-1;
ENDLOOP;
rope ¬ Rope.FromRefText[text];
RefText.ReleaseScratch[text];
};
ItemFromRope: PUBLIC PROC [rope: ROPE] RETURNS [item: Item] ~ {
itemLen: CARD32 ~ CrRPC.MarshalledRopeHWords[rope];
item ¬ NEW[CHOps.ItemObject[itemLen]];
ItemFromRopeInner[rope, item, 0];
};
ItemFromElement: PUBLIC PROC [element: Element] RETURNS [item: Item] ~ {
orgLen: CARD32 ~ CrRPC.MarshalledRopeHWords[element.organization];
domLen: CARD32 ~ CrRPC.MarshalledRopeHWords[element.domain];
objLen: CARD32 ~ CrRPC.MarshalledRopeHWords[element.object];
itemLen: CARD32 ~ orgLen + domLen + objLen;
item ¬ NEW[CHOps.ItemObject[itemLen]];
ItemFromRopeInner[element.organization, item, 0];
ItemFromRopeInner[element.domain, item, orgLen];
ItemFromRopeInner[element.object, item, orgLen + domLen] };
ItemFromRopeInner: PROC [rope: ROPE, item: Item, pos: CARD32] ~ {
buf: Basics.Word16;
ropeLen, iFrom: INT;
IF CrRPC.MarshalledRopeHWords[rope] > (item.length - pos) THEN ERROR;
item.body[pos] ¬ ropeLen ¬ Rope.Length[rope]; pos ¬ pos + 1;
iFrom ¬ 0;
DO
IF iFrom >= ropeLen THEN EXIT;
buf.hi ¬ ORD[Rope.Fetch[rope, iFrom]];
iFrom ¬ iFrom+1;
buf.lo ¬ IF iFrom < ropeLen THEN ORD[Rope.Fetch[rope, iFrom]] ELSE 0;
iFrom ¬ iFrom+1;
item.body[pos] ¬ buf.card; pos ¬ pos + 1;
ENDLOOP;
};
Domain Name Ropes
DomainFromElement: PROC [element: Element] RETURNS [rope: ROPE] ~ INLINE {
e.g. ["Xerox", "PARC", "*"] -> "PARC:Xerox"
rope ¬ Rope.Cat[element.domain, ":", element.organization] };
DomainFromOrgElement: PROC [element: Element] RETURNS [rope: ROPE] ~ INLINE {
e.g. ["Xerox", "foo", "bar"] -> "Xerox:CHServers"
rope ¬ Rope.Cat[element.organization, ":", shiftInName] };
Address List Manipulation
BestAddressInList: PUBLIC PROC [list: LIST OF XNS.Address]
RETURNS [bestAddress: XNS.Address] ~ {
bestHops: CARDINAL ¬ LAST[CARDINAL];
WHILE list # NIL DO
tempHops: CARDINAL ~ XNSRouter.GetHops[list.first.net];
IF tempHops < bestHops THEN {
bestAddress ¬ list.first;
bestHops ¬ tempHops };
list ¬ list.rest;
ENDLOOP;
};
Bulk Data Stream / Marshalling Procs
GetElement: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ {
element.organization ¬ CrRPC.GetRope[stream];
element.domain ¬ CrRPC.GetRope[stream];
element.object ¬ CrRPC.GetRope[stream] };
GetOrganization: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ {
element.organization ¬ CrRPC.GetRope[stream];
element.domain ¬ NIL;
element.object ¬ NIL };
GetDomain: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ {
element.organization ¬ CrRPC.GetRope[stream];
element.domain ¬ CrRPC.GetRope[stream];
element.object ¬ NIL };
PutElement: PUBLIC PROC [stream: IO.STREAM, element: Element] ~ {
CrRPC.PutRope[stream, element.organization];
CrRPC.PutRope[stream, element.domain];
CrRPC.PutRope[stream, element.object] };
taken from ThisMachineImpl; registered with ThisMachineRegistry
cachedXNSName: ROPE ¬ NIL;
cachedXNSNameOK: BOOL ¬ FALSE;
TMName: PROC RETURNS[rope: ROPE ¬ NIL] = {
Someday the XNS world will have to get its act together and allow address-to-name mapping. For now, we try to construct an XNS name either as <username>-WS or by getting the Pup name and using the default domain and organization. We try this at most once, since it takes awhile if there isn't a Pup name service on the network.
GuessXNSName: PROC [guess: ROPE] ~ {
address: XNS.Address;
distingName: XNSCHName.Name;
IF Rope.IsEmpty[guess] THEN RETURN;
guess ¬ XNSCHName.RopeFromName[XNSCHName.NameFromRope[guess]];
[distingName, address] ¬ LookupAddressFromRope[guess];
IF address.host = XNS.GetThisHost[] THEN {
cachedXNSName ¬ XNSCHName.RopeFromName[distingName];
cachedXNSNameOK ¬ TRUE };
};
IF NOT cachedXNSNameOK THEN {
item: XNSCH.Item;
c: XNSCH.Conversation;
tempIdentity: XNSAuth.Identity ¬ XNSCredentials.GetIdentity[];
IF tempIdentity = NIL THEN GOTO Out;
c ¬ XNSCH.InitiateConversation[];
[item~item] ¬ LookupItemProperty[c~c, pattern~XNSAuth.GetIdentityDetails[tempIdentity].name, pID~CHEntries.associatedWorkstation
! Error => { XNSCH.TerminateConversation[c]; GOTO Out } ];
XNSCH.TerminateConversation[c];
GuessXNSName[XNSCHName.RopeFromName[ElementFromItem[item]]];
EXITS
Out => NULL;
};
IF NOT cachedXNSNameOK THEN {
Guess <userName>-WS ...
tempIdentity: XNSAuth.Identity ¬ XNSCredentials.GetIdentity[];
IF tempIdentity # NIL THEN
GuessXNSName[Rope.Concat[XNSAuth.GetIdentityDetails[tempIdentity].name.object, "-ws"]];
};
IF NOT cachedXNSNameOK THEN {
Give up ...
cachedXNSName ¬ NIL;
cachedXNSNameOK ¬ TRUE;
};
rope ¬ cachedXNSName;
};
TMAddress: PROC RETURNS[rope: ROPE ¬ NIL] = {
rope ¬ Convert.RopeFromXNSAddress[Convert.XNSAddressFromRope["ME"]];
};
InitProcs: PROC = {
thisMachineProcs: ThisMachineRegistry.ThisMachineRef ¬
NEW[ThisMachineRegistry.ThisMachineProcsRec ¬ [
which: $xns,
Name: TMName,
Address: TMAddress,
ProcessorID: NIL
]];
ThisMachineRegistry.RegisterThisMachineProcs[thisMachineProcs];
Booting.RegisterProcs[r~Rollback];
};
Rollback: Booting.RollbackProc ~ {
cachedXNSNameOK ← FALSE;
cachedXNSName ← NIL;
};
InitProcs[];
}.