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[]; }; program: CARD32 _ 70; version: CARD16 _ 1; maxhops: CARD16 _ 6; 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[]; }. \FetchCommanderImpl.Mesa Copyright Σ 1987, 1988 by Xerox Corporation. All rights reserved. Bill Jackson (bj) July 25, 1988 5:59:29 pm PDT Bloomenthal, November 25, 1987 3:29:22 pm PST UserProfile stuff Magic contants (for Expanding Ring Broadcast) (for the commander) Types Error handling Monitor Worker Procs Commander Procs Initialization Κ ˜™Icode™BKšœ.™.K™-K™—šΟk ˜ Jšœœ ˜*Jš œœœœœœ˜ Jšœ œœ˜Jšœ œ˜Jšœ œ˜*Jšœœ1˜>Jšœœ ˜KšœœR˜]Jšœ œ/˜?Jšœœœ ˜&Jšœœ˜ Jšœœ%œ ˜>Jšœ œ ˜Jšœœ.˜CJšœ œ6˜GJšœœ ˜Jšœœ,˜5Jšœœ˜&Jšœ œ˜'J˜—šΟnœœ˜!KšœIœ=œ˜£Kšœžœ ˜Kšœœœ˜headšΟz™Kš ΠbkœœΟbœ‘œ‘œ˜HKš  œœ‘œ‘œ‘œœ˜CKš  œœ‘œ‘œ‘œœ˜MKš œœ‘œ‘œ‘ œœœ˜1K˜šžœœ˜ Kš‘ œ ΟcΠbc’ ˜:Kš‘œ œ˜7Kš‘œ œ˜AKš œœ˜ Kšœ˜K˜—šž œ$˜.Kšœ˜Kšœ˜K˜—šžœ+˜2Kšœ˜Kšœ˜——šŸ™šŸ™Kš‘œœ˜Kš‘œœ˜Kš‘œœ˜—šŸ™Kš‘ œœ‘ œ˜Kš‘ œœŒ˜žKš‘œœ‘ œ‘ œ˜FK˜Kš‘ œœ‘ œ˜Kš‘ œœ΄˜ΖKš‘œœ‘ œ‘ œ˜F——šŸ™šœœœ˜#Kšœ œ ˜Kšœœ˜Kšœ˜ K˜K˜—Kš œ œœœœ ˜%šœ œœ˜Kšœœ˜Kšœœ˜ Kšœ˜ K˜——šŸ™Kšœ œ˜!Kšžœœœœ˜3Kš œœœ˜—šŸ™Kšœ!˜!K˜šžœœœœœ œœœ˜iKšœ˜Kšœ!˜!Kšœ˜Kšœ˜K˜—š žœœœ œ œ˜DKš œœœ œœœ˜cKšœ˜Kšœ(˜(Kšœ˜Kšœ˜K˜—šžœœœ˜#Kšœ(˜(K˜——šŸ ™ šž œœ œœœœ œ+˜sšžœ˜%J˜J˜—Kšœ œ˜Kšœœ˜8šœœ˜Kšœ œœ˜*šœ)œ˜BKšœ˜Kšœœœ˜-Kš œ‘œ‘œ‘œ‘œ˜QKšœ œœœ"˜MKšœ˜—šœ˜ Kšœ"œœ˜=Kšœ1œœ˜JKšœ+˜+Kšœ˜Kšœœœ˜K˜——Kšœ˜Kšœ˜K˜—šžœœ œ œœ œœ œ˜bš ž œœ œ œœœ˜ZKšœœ˜!Kšœ œ˜š ž œœœœœœ˜>šœœ˜Kšœœœ˜Kšœœœ˜Kšœœœ˜Kšœœœ˜Kšœœ˜—Kšœ˜—š œ(œœœ6˜‡Kšœ˜—Kšœœ œ˜&Kšœ:˜:šœ'œœ˜JKšœœ%˜-šœœ˜Kšœœœœ˜7Kšœ-˜-Kšœ˜—Kšœ˜—K˜—Kšœ œ˜Kšœ0˜0Kšœ<˜