<> <> <> <> <<>> DIRECTORY Args USING [ Arg, ArgsGet, Error, NArgs ], Ascii USING [ SP, TAB, CR, LF ], BasicTime USING [ GMT, Now ], CHNameP2V0 USING [ ], Commander USING [ CommandProc, Register ], Convert USING [ NetFormat, RopeFromXNSAddress, TimeFromRope ], CourierBinding USING [ Bind ], CrRPC USING [ CreateClientHandle, DestroyClientHandle, Error, Handle, PutArgsProc, PutRope ], FetchP70V1 USING [ BadRelease, FileNotFound, Find, Predicate ], IO USING [ PutF, rope, STREAM, time ], Process USING [ CheckForAbort ], Rope USING [ Cat, Concat, InlineFetch, Length, ROPE, Substr ], TiogaMenuOps USING [ Open ], UserCredentials USING [ CredentialsChangeProc, RegisterForChange ], UserProfile USING [ CallWhenProfileChanges, Line, ProfileChangedProc ], ViewerClasses USING [ Viewer ], XNS USING [ Address, unknownAddress, unknownSocket ], XNSCH USING [ LookupAddressFromRope ], XNSCHName USING [ Name, RopeFromName ]; FetchCommanderImpl: CEDAR MONITOR IMPORTS Args, BasicTime, Commander, Convert, CourierBinding, CrRPC, FetchP70V1, IO, Process, Rope, TiogaMenuOps, UserCredentials, UserProfile, XNSCH, XNSCHName ~ { OPEN Fetch1: FetchP70V1; ROPE: TYPE ~ Rope.ROPE; <> FORMAT: ROPE ~ "Fetch.Format"; defaultFormat: Convert.NetFormat _ octal; RELEASE: ROPE ~ "Fetch.Release"; defaultRelease: ROPE _ "Mesa14.0"; SERVICE: ROPE ~ "Fetch.Service"; defaultService: ROPE _ "Anonymous Server::"; SOCKET: ROPE ~ "Fetch.Socket"; HACK: BOOL _ TRUE; GetDefaultsFromProfile: PROC ~ { defaultFormat _ octal; -- UserProfile.Line[FORMAT, octal]; defaultRelease _ UserProfile.Line[RELEASE, "Mesa14.0"]; defaultService _ UserProfile.Line[SERVICE, "Anonymous Server::"]; HACK _ TRUE; }; NewProfile: UserProfile.ProfileChangedProc ~ { GetDefaultsFromProfile[]; }; NewUser: UserCredentials.CredentialsChangeProc ~ { GetDefaultsFromProfile[]; }; <> <<(for Expanding Ring Broadcast)>> program: CARD32 _ 70; version: CARD16 _ 1; maxhops: CARD16 _ 6; <<(for the commander)>> fetchinfo: ROPE ~ "FetchInfo"; fetchinfodoc: ROPE ~ " [-h -r -d -v] Query Fetch service for release information. Switches: -h query a particular service -r specify which 'VersionMap' to use -d list enclosing df -v list server used"; fetchinfousage: ROPE ~ Rope.Concat["Usage: FetchInfo ", fetchinfodoc]; fetchopen: ROPE ~ "FetchOpen"; fetchopendoc: ROPE ~ " [-h -r -d -v] Query Fetch service for release information, then open viewer on relevant files. Switches: -h query a particular service -r specify which 'VersionMap' to use -d retrieve enclosing df -v list server used"; fetchopenusage: ROPE ~ Rope.Concat["Usage: FetchOpen ", fetchopendoc]; <> CachedServerObject: TYPE ~ RECORD [ address: XNS.Address, lastCall: BasicTime.GMT, name: ROPE ]; InfoList: TYPE ~ LIST OF REF InfoRec; InfoRec: TYPE ~ RECORD [ date: BasicTime.GMT, df: ROPE, name: ROPE ]; <> ErrorType: TYPE ~ { name, bind }; Error: ERROR [ type: ErrorType, msg: ROPE ] ~ CODE; FIREWALL: SIGNAL ~ CODE; <> cachedServer: CachedServerObject; GetCachedServer: ENTRY PROC [ ] RETURNS [ address: XNS.Address, lastCall: BasicTime.GMT, name: ROPE ] ~ { address _ cachedServer.address; lastCall _ cachedServer.lastCall; name _ cachedServer.name; }; SetCachedServer: ENTRY PROC [ name: ROPE, address: XNS.Address ] ~ { IF ( ( address.socket # XNS.unknownSocket ) AND ( HACK ) ) THEN address.socket _ XNS.unknownSocket; cachedServer.address _ address; cachedServer.lastCall _ BasicTime.Now[]; cachedServer.name _ name; }; UpdateTimestamp: ENTRY PROC [ ] ~ { cachedServer.lastCall _ BasicTime.Now[]; }; <> FindServer: PROC [ release: ROPE, host: ROPE _ NIL ] RETURNS [ addr: XNS.Address, distingName: XNSCHName.Name ] ~ { PutArgsClosure: CrRPC.PutArgsProc ~ { CrRPC.PutRope[s, release]; }; validServer: BOOL; [distingName, addr] _ XNSCH.LookupAddressFromRope[host]; SELECT TRUE FROM ( addr # XNS.unknownAddress ) => { NULL }; ( ( addr _ GetCachedServer[].address ) = XNS.unknownAddress ) => { host _ "Anonymous Server::"; distingName _ [NIL, NIL, "Anonymous Server"]; addr _ CourierBinding.Bind[program, [version, version], maxhops, PutArgsClosure]; IF ( addr = XNS.unknownAddress ) THEN ERROR Error[bind, "No Server located"]; }; ENDCASE => { ENABLE { CrRPC.Error => { validServer _ FALSE; CONTINUE }; }; h: CrRPC.Handle _ CrRPC.CreateClientHandle[$SPP, NEW[XNS.Address _ addr]]; validServer _ Fetch1.Predicate[h, release]; CrRPC.DestroyClientHandle[h]; IF ( validServer ) THEN RETURN; }; SetCachedServer[host, addr]; }; GetToken: PROC [ source: ROPE, offset: CARD16 ] RETURNS [ token: ROPE _ NIL, nextpos: CARD16 ] ~ { FindToken: PROC [ source: ROPE, offset: CARD16 ] RETURNS [ firstpos, nextpos: CARD16 ] ~ { slen: CARD ~ Rope.Length[source]; hostPending: BOOL; WhiteSpace: PROC [ ch: CHAR ] RETURNS [ yes: BOOL ] ~ INLINE { yes _ SELECT ch FROM ( Ascii.SP ) => TRUE, ( Ascii.TAB ) => TRUE, ( Ascii.CR) => TRUE, ( Ascii.LF) => TRUE, ENDCASE => FALSE; }; FOR firstpos _ offset, firstpos _ firstpos.SUCC WHILE ( ( firstpos < slen ) AND ( WhiteSpace[Rope.InlineFetch[source, firstpos]] ) ) DO ENDLOOP; IF ( firstpos >= slen ) THEN FIREWALL; hostPending _ ( Rope.InlineFetch[source, firstpos] = '[ ); FOR nextpos _ firstpos, nextpos _ nextpos.SUCC WHILE ( nextpos < slen ) DO ch: CHAR _ Rope.InlineFetch[source, nextpos]; SELECT TRUE FROM ( ( NOT hostPending ) AND ( WhiteSpace[ch] ) ) => EXIT; ( hostPending ) => hostPending _ ( ch # '] ); ENDCASE; ENDLOOP; }; firstpos: CARD16; [firstpos, nextpos] _ FindToken[source, offset]; token _ Rope.Substr[source, firstpos, (nextpos - firstpos)]; }; BustUpResults: PROC [ dfList, pathList, dateList: ROPE, nMatches: CARD16 ] RETURNS [ list: InfoList _ NIL ] ~ { n1, n2, n3: CARD16 _ 0; fileName: ROPE; dfName: ROPE; date1, date2, date3: ROPE; date: BasicTime.GMT; FOR i: CARD16 IN [0..nMatches) DO [fileName, n1] _ GetToken[pathList, n1]; [dfName, n2] _ GetToken[dfList, n2]; [date1, n3] _ GetToken[dateList, n3]; [date2, n3] _ GetToken[dateList, n3]; [date3, n3] _ GetToken[dateList, n3]; date _ Convert.TimeFromRope[Rope.Cat[date1, " ", date2, " ", date3]]; list _ CONS [NEW [InfoRec _ [date, dfName, fileName]], list]; ENDLOOP; }; InfoInternal: PROC [ pattern: ROPE, host: ROPE, release: ROPE ] RETURNS [ list: InfoList _ NIL, service: ROPE _ NIL, place: ROPE _ NIL ] ~ { dfName: ROPE; filePath: ROPE; createDate: ROPE; nMatches: CARD16; addr: XNS.Address; distingName: XNSCHName.Name; h: CrRPC.Handle; CleanUp: PROC ~ { CrRPC.DestroyClientHandle[h]; service _ XNSCHName.RopeFromName[distingName]; place _ Convert.RopeFromXNSAddress[addr, defaultFormat]; }; [addr, distingName] _ FindServer[release, host]; IF ( addr = XNS.unknownAddress ) THEN ERROR Error[name, "Server not found"]; IF ( ( addr.socket # XNS.unknownSocket ) AND ( HACK ) ) THEN addr.socket _ XNS.unknownSocket; h _ CrRPC.CreateClientHandle[$SPP, NEW[XNS.Address _ addr]]; [dfName, filePath, createDate, nMatches] _ Fetch1.Find[h, pattern, release, TRUE, TRUE, TRUE ! Fetch1.FileNotFound => { CleanUp[]; GOTO Finish }; Fetch1.BadRelease => { CleanUp[]; GOTO Finish } ]; list _ BustUpResults[dfName, filePath, createDate, nMatches]; CleanUp[]; EXITS Finish => { NULL }; }; FillViewer: PROC [ name: ROPE ] RETURNS [ viewer: ViewerClasses.Viewer ] ~ { viewer _ TiogaMenuOps.Open[name]; }; <> FetchOpenProc: Commander.CommandProc ~ { ENABLE { UNWIND => NULL }; out: IO.STREAM ~ cmd.out; host, pattern, release, getDF, verbose: Args.Arg; list: InfoList; service: ROPE; place: ROPE; IF ( Args.NArgs[cmd] = 0 ) THEN { msg _ fetchopenusage; GOTO Failed }; [pattern, host, release, getDF, verbose] _ Args.ArgsGet[cmd, "%s-h%s-r%s-d%b-v%b" ! Args.Error => { msg _ reason; CONTINUE }]; IF ( msg # NIL ) THEN RETURN[$Failure, "Command syntax error."]; IF ( NOT host.ok ) THEN host.rope _ defaultService; IF ( NOT release.ok ) THEN release.rope _ defaultRelease; Process.CheckForAbort[]; [list, service, place] _ InfoInternal[pattern.rope, host.rope, release.rope]; SELECT TRUE FROM ( list = NIL ) => { msg _ Rope.Cat["Sorry, '", pattern.rope, ".*' is not in the ", release.rope, " release."]; GOTO Failed; }; ENDCASE => { NULL }; IF ( verbose.bool ) THEN IO.PutF[out, "[%g] at %g\n", IO.rope[service], IO.rope[place] ]; IF ( list.rest = NIL ) THEN IO.PutF[out, "%s =>\n", IO.rope[pattern.rope] ] ELSE IO.PutF[out, "%s.* =>\n", IO.rope[pattern.rope] ]; FOR tail: InfoList _ list, tail.rest WHILE ( tail # NIL ) DO IO.PutF[out, " %g\n %g\n", IO.rope[tail.first.name], IO.time[tail.first.date] ]; [] _ FillViewer[tail.first.name]; IF ( getDF.bool ) THEN { IO.PutF[out, " From: %g\n", IO.rope[tail.first.df] ]; [] _ FillViewer[tail.first.df]; }; ENDLOOP; EXITS Failed => { result _ $Failure }; }; FetchInfoProc: Commander.CommandProc ~ { ENABLE { UNWIND => NULL }; out: IO.STREAM ~ cmd.out; host, pattern, release, listDF, verbose: Args.Arg; list: InfoList; service: ROPE; place: ROPE; IF ( Args.NArgs[cmd] = 0 ) THEN { msg _ fetchinfousage; GOTO Failed }; [pattern, host, release, listDF, verbose] _ Args.ArgsGet[cmd, "%s-h%s-r%s-d%b-v%b" ! Args.Error => { msg _ reason; CONTINUE }]; IF ( msg # NIL ) THEN RETURN[$Failure, "Command syntax error."]; IF ( NOT host.ok ) THEN host.rope _ defaultService; IF ( NOT release.ok ) THEN release.rope _ defaultRelease; Process.CheckForAbort[]; [list, service, place] _ InfoInternal[pattern.rope, host.rope, release.rope]; SELECT TRUE FROM ( list = NIL ) => { msg _ Rope.Cat["Sorry, '", pattern.rope, ".*' is not in the ", release.rope, " release."]; GOTO Failed; }; ENDCASE => { NULL }; IF ( verbose.bool ) THEN IO.PutF[out, "[%g] at %g\n", IO.rope[service], IO.rope[place] ]; IF ( list.rest = NIL ) THEN IO.PutF[out, "%s =>\n", IO.rope[pattern.rope] ] ELSE IO.PutF[out, "%s.* =>\n", IO.rope[pattern.rope] ]; FOR tail: InfoList _ list, tail.rest WHILE ( tail # NIL ) DO IO.PutF[out, " %g\n %g\n", IO.rope[tail.first.name], IO.time[tail.first.date] ]; IF ( listDF.bool ) THEN IO.PutF[out, " From: %g\n", IO.rope[tail.first.df] ]; ENDLOOP; EXITS Failed => { result _ $Failure }; }; <> Init: PROC ~ { GetDefaultsFromProfile[]; UserProfile.CallWhenProfileChanges[NewProfile]; UserCredentials.RegisterForChange[NewUser]; SetCachedServer[defaultService, XNS.unknownAddress]; Commander.Register[fetchinfo, FetchInfoProc, fetchinfodoc]; Commander.Register[fetchopen, FetchOpenProc, fetchopendoc]; }; Init[]; }.