<<>> <> <> <> <> <> <<>> 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 <> ~ { 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; <> 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: BOOL _ FALSE]>> ~ { 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]; }; <> 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: BOOL _ FALSE]>> ~ { 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]]; }; <> 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: BOOL _ FALSE]>> ~ { 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: BOOL _ FALSE]>> ~ { 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: BOOL _ FALSE]>> ~ { 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: BOOL _ FALSE]>> ~ { 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]; }; <> 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: BOOL _ FALSE]>> ~ { 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]]; }; <> 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: BOOL _ FALSE]>> ~ { 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]]; }; <> 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: BOOL _ FALSE]>> ~ { 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]]; }; <> 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]; }; <> 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: BOOL _ FALSE]>> ~ { 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]; }; <> <<(Un)marshalling>> <> 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; }; <> DomainFromElement: PROC [element: Element] RETURNS [rope: ROPE] ~ INLINE { < "PARC:Xerox">> rope ¬ Rope.Cat[element.domain, ":", element.organization] }; DomainFromOrgElement: PROC [element: Element] RETURNS [rope: ROPE] ~ INLINE { < "Xerox:CHServers">> rope ¬ Rope.Cat[element.organization, ":", shiftInName] }; <
> 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; }; <> 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] }; <> <<>> cachedXNSName: ROPE ¬ NIL; cachedXNSNameOK: BOOL ¬ FALSE; TMName: PROC RETURNS[rope: ROPE ¬ NIL] = { <-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 { <-WS ...>> tempIdentity: XNSAuth.Identity ¬ XNSCredentials.GetIdentity[]; IF tempIdentity # NIL THEN GuessXNSName[Rope.Concat[XNSAuth.GetIdentityDetails[tempIdentity].name.object, "-ws"]]; }; IF NOT cachedXNSNameOK THEN { <> 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]; <> }; <> <> <> <<};>> <<>> InitProcs[]; <<>> }.