<> <> <> <> <> <> DIRECTORY Arpa, Convert USING [IntFromRope, Error], IO USING [int, PutFR], RefText USING [AppendChar, AppendRope, ObtainScratch, ReleaseScratch, TrustTextAsRope], Rope USING [Cat, Concat, Flatten, FromRefText, IsEmpty, MapType, MoveType, ROPE], SunYPAgent USING [Error, First, Handle, Match, Next, ObtainHandle, ReleaseHandle, TextSeq, TokenizeUsingSeparator], SystemNames USING [Release, ReleaseOption, Server], SystemVersion USING [release], ThisMachine USING [Name], UnixSysCalls USING [GetUID], UnixTypes USING [UID]; SystemNamesFromYPImpl: CEDAR MONITOR IMPORTS Convert, IO, RefText, Rope, SystemVersion, SunYPAgent, ThisMachine, UnixSysCalls EXPORTS SystemNames ~ { ROPE: TYPE ~ Rope.ROPE; Release: TYPE ~ SystemNames.Release; ReleaseOption: TYPE ~ SystemNames.ReleaseOption; Server: TYPE ~ SystemNames.Server; ReleaseArray: TYPE ~ ARRAY Release OF ROPE; releaseNames: REF ReleaseArray ~ NEW[ReleaseArray ¬ ALL[NIL]]; ServerInfo: TYPE ~ RECORD [name, defaultHost: ROPE]; ServerArray: TYPE ~ ARRAY Server OF ServerInfo; serverInfo: REF ServerArray ~ NEW[ServerArray ¬ ALL[[NIL, NIL]]]; Initialize: PROC ~ { Version: TYPE ~ RECORD [major, minor: INT]; current: Version ~ [major: SystemVersion.release.major, minor: SystemVersion.release.minor]; previous: Version ~ IF current.minor>0 THEN [major: current.major, minor: current.minor-1] ELSE [major: 0, minor: 0]; -- must edit this by hand each major release versions: ARRAY Release OF Version ¬ [current: current, previous: previous]; FOR r: Release IN Release DO v: Version ~ versions[r]; releaseNames[r] ¬ Rope.Flatten[IO.PutFR["%g.%g", IO.int[v.major], IO.int[v.minor]]]; ENDLOOP; serverInfo­ ¬ [ Cedar: [name: "Cedar", defaultHost: "Cyan-STP"], PCedar: [name: "PCedar", defaultHost: "Pixel-STP"], User: [name: "User", defaultHost: "Ivy-STP"], Fonts: [name: "Fonts", defaultHost: "Cyan-STP"] ]; }; ReleaseName: PUBLIC PROC [release: Release ¬ current] RETURNS [ROPE] ~ { RETURN [releaseNames[release]]; }; <<>> ServerName: PUBLIC PROC [server: Server] RETURNS [ROPE] ~ { RETURN [serverInfo[server].name]; }; <<>> DefaultHostName: PUBLIC PROC [server: Server] RETURNS [ROPE] ~ { RETURN [serverInfo[server].defaultHost]; }; <<>> passwordMapName: ROPE ¬ "passwd.byname"; namePos: CARDINAL ~ 0; uidPos: CARDINAL ~ 2; homeDirPos: CARDINAL ~ 5; UserName: PUBLIC ENTRY PROC RETURNS [name: ROPE] ~ { ENABLE UNWIND => NULL; name ¬ UserNameInternal[]; }; userName: ROPE ¬ NIL; UserNameInternal: INTERNAL PROC RETURNS [name: ROPE] ~ { IF userName#NIL THEN RETURN[userName]; { ENABLE SunYPAgent.Error, Convert.Error => GOTO GiveUp; h: SunYPAgent.Handle ¬ SunYPAgent.ObtainHandle[]; uid: UnixTypes.UID ¬ UnixSysCalls.GetUID[]; keyBefore: ROPE; val: REF TEXT; [keyBefore, val] ¬ SunYPAgent.First[h, passwordMapName]; DO seq: SunYPAgent.TextSeq; tuid: UnixTypes.UID; seq ¬ SunYPAgent.TokenizeUsingSeparator[val, ':]; IF seq.length <= uidPos THEN { SunYPAgent.ReleaseHandle[h]; GOTO GiveUp; }; tuid ¬ Convert.IntFromRope[RefText.TrustTextAsRope[seq.refText[uidPos]]]; IF tuid = uid THEN { SunYPAgent.ReleaseHandle[h]; RETURN[userName ¬ RefText.TrustTextAsRope[seq.refText[namePos]]]; }; [keyBefore, val] ¬ SunYPAgent.Next[h, passwordMapName, keyBefore]; ENDLOOP; EXITS GiveUp => RETURN[NIL]; }; }; homeDirectory: ROPE ¬ NIL; GetHomeDirectory: ENTRY PROC RETURNS [wdir: Rope.ROPE] ~ { IF homeDirectory#NIL THEN RETURN[homeDirectory]; { ENABLE { SunYPAgent.Error, Convert.Error => GOTO GiveUp; UNWIND => NULL; }; name: ROPE ¬ UserNameInternal[]; h: SunYPAgent.Handle ¬ SunYPAgent.ObtainHandle[]; val: REF TEXT; seq: SunYPAgent.TextSeq; IF name = NIL THEN ERROR; -- couldn't find entry in passwd file val ¬ SunYPAgent.Match[h, passwordMapName, name]; seq ¬ SunYPAgent.TokenizeUsingSeparator[val, ':]; IF seq.length <= homeDirPos THEN GOTO GiveUp; homeDirectory ¬ RefText.TrustTextAsRope[seq.refText[homeDirPos]]; SunYPAgent.ReleaseHandle[h]; RETURN[homeDirectory]; EXITS GiveUp => NULL; } }; MachineName: PUBLIC PROC RETURNS [machine: ROPE ¬ NIL] ~ { machine ¬ ThisMachine.Name[]; IF machine=NIL THEN machine ¬ "AnonymousMachine"; }; ReleaseDir: PUBLIC PROC [dir: ROPE, release: Release] RETURNS [ROPE] ~ { releaseName: ROPE ~ releaseNames[release]; RETURN[Rope.Flatten[Rope.Concat[dir, releaseName]]]; }; ReleaseSubDir: PUBLIC PROC [subDirs: ROPE, release: Release] RETURNS [ROPE] ~ { releaseName: ROPE ~ releaseNames[release]; IF Rope.IsEmpty[subDirs] THEN RETURN[releaseName] ELSE RETURN[Rope.Flatten[Rope.Cat[releaseName, "/", subDirs]]]; }; ConstructDir: PUBLIC PROC [server, dir, subDirs: ROPE, option: ReleaseOption, release: Release] RETURNS [ROPE] ~ { SELECT option FROM releaseDir => dir ¬ ReleaseDir[dir, release]; releaseSubDir => subDirs ¬ ReleaseSubDir[subDirs, release]; releaseOmitted => NULL; ENDCASE => ERROR; RETURN[ConstructFName[server: server, dir: dir, subDirs: subDirs]]; }; <<>> ConstructFName: PROC [server, dir, subDirs: ROPE ¬ NIL] RETURNS [fName: ROPE] = { GetTildeRope: PROC RETURNS [r: Rope.ROPE] = { <> <<>> r ¬ GetHomeDirectory[]; IF r = NIL THEN ERROR -- can't happen. presumably the user logged on. ELSE RETURN[Rope.Cat[r, "/Cedar"]]; }; scratch: REF TEXT ~ RefText.ObtainScratch[120]; text: REF TEXT ¬ scratch; tilde: Rope.ROPE ¬ GetTildeRope[]; -- eg "/palain/wyatt/Cedar" text ¬ RefText.AppendRope[text, tilde]; text ¬ RefText.AppendChar[text, '/ ]; IF NOT Rope.IsEmpty[server] THEN { text ¬ RefText.AppendRope[text, server]; text ¬ RefText.AppendChar[text, '/ ]; }; IF NOT Rope.IsEmpty[dir] THEN { text ¬ RefText.AppendRope[text, dir]; text ¬ RefText.AppendChar[text, '/ ]; }; IF NOT Rope.IsEmpty[subDirs] THEN { text ¬ RefText.AppendRope[text, subDirs]; text ¬ RefText.AppendChar[text, '/ ]; }; fName ¬ Rope.FromRefText[text]; RefText.ReleaseScratch[scratch]; }; LocalDir: PUBLIC PROC [subDirs: ROPE, option: ReleaseOption, release: Release ¬ current, volumeName: ROPE ¬ NIL] RETURNS [ROPE] ~ { RETURN[ConstructDir[NIL, volumeName, subDirs, option, release]]; }; <<>> CedarDir: PUBLIC PROC [subDirs: ROPE, release: Release, dir: ROPE] RETURNS [ROPE] ~ { server: ROPE ~ serverInfo[Cedar].name; IF dir=NIL THEN dir ¬ server; RETURN[ConstructDir[server, dir, subDirs, $releaseDir, release]]; }; <<>> UserDir: PUBLIC PROC [subDirs: ROPE, option: ReleaseOption, release: Release, userName: ROPE] RETURNS [ROPE] ~ { server: ROPE ~ serverInfo[User].name; IF userName=NIL THEN userName ¬ UserName[]; RETURN[ConstructDir[server, userName, subDirs, option, release]]; }; <<>> Initialize[]; }.