-- Copyright (C) 1982, 1984, 1985 by Xerox Corporation. All rights reserved. -- InitParms.mesa, HGM, 10-Mar-85 5:54:04 -- From OthelloFTP.mesa of 11-Dec-82 16:01:37 DIRECTORY Boot USING [EthernetBootFileNumber, Location], Device USING [Type], DeviceTypes USING [ethernet, ethernetOne], Environment USING [bytesPerPage, bytesPerWord], Format USING [HostNumber, StringProc], Heap USING [systemZone], HostNumbers USING [HostNumber], NSConstants USING [bootServerSocket], OthelloDefs USING [ AbortingCommand, CheckUserAbort, CommandProcessor, GetName, IndexTooLarge, MyNameIs, Question, ReadShortNumber, RegisterCommandProc, WriteChar, WriteLine, WriteLongNumber, WriteOctal, WriteString, Yes], Process USING [Pause, SecondsToTicks], Space USING [ScratchMap, Unmap], STP USING [ Close, Create, CreateRemoteStream, Enumerate, Error, ErrorCode, FileInfo, GetFileInfo, Handle, IsOpen, Login, NextFileName, NoteFileProcType, Open, SetDirectory, SetHost], Stream USING [EndOfStream, Handle], String USING [AppendCharAndGrow, AppendString, CopyToNewString, Length], System USING [ broadcastHostNumber, GreenwichMeanTime, NetworkAddress, nullNetworkNumber], Time USING [Append, Unpack], Unformat USING [Error, HostNumber], Indirect USING [GetParmFileName], OthelloForgot USING [], Parms USING [Error, GetBootLocation, GetMaxChars, GetParms, WriteBootLocation, WriteParms], PhoneFace USING [phoneLine]; InitParms: PROGRAM IMPORTS Format, Heap, OthelloDefs, Process, Space, STP, Stream, String, Time, Unformat, Indirect, Parms EXPORTS System, OthelloForgot = BEGIN HostNumber: PUBLIC TYPE = HostNumbers.HostNumber; host, userName, userPassword: LONG STRING ¬ NIL; directory, file: LONG STRING ¬ NIL; bootFileNumber: LONG STRING; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- String/Credentials Commands --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Directory: PROC = { OthelloDefs.MyNameIs[ myNameIs: "Directory"L, myHelpIs: "Set Default FTP directory"L]; OthelloDefs.GetName["Directory: "L, @directory]}; GetUserNamePassword: PROC = { OthelloDefs.MyNameIs[ myNameIs: "Login"L, myHelpIs: "Set user name-password"L]; OthelloDefs.GetName["User: "L, @userName]; OthelloDefs.GetName["Password: "L, @userPassword, stars]}; SmashPassword: PUBLIC PROCEDURE = BEGIN Heap.systemZone.FREE[@userName]; Heap.systemZone.FREE[@userPassword] END; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Set BootLocation Command --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SetBootLocation: PROC = BEGIN where: Boot.Location; OthelloDefs.MyNameIs[ myNameIs: "Set Boot Location", myHelpIs: "Set Boot Location in EERom"L]; SELECT TRUE FROM OthelloDefs.Yes["NS/10MB? "L] => BEGIN bfn: HostNumber; board: CARDINAL ¬ 0; OthelloDefs.GetName["NS Boot File Number: "L, @bootFileNumber]; GetAddress[@bfn, bootFileNumber ! Unformat.Error => OthelloDefs.AbortingCommand["Can't parse that one (No CH)"L]]; board ¬ OthelloDefs.ReadShortNumber[ "Board: "L, 0, 3, board]; where ¬ [ deviceType: DeviceTypes.ethernet, deviceOrdinal: board, vp: ethernet [ [ bfn: [bfn], address: [ net: System.nullNetworkNumber, host: System.broadcastHostNumber, socket: NSConstants.bootServerSocket] ]]]; END; OthelloDefs.Yes["NS/Phone? "L] => BEGIN bfn: HostNumber; line: CARDINAL ¬ 0; OthelloDefs.GetName["NS Boot File Number: "L, @bootFileNumber]; GetAddress[@bfn, bootFileNumber ! Unformat.Error => OthelloDefs.AbortingCommand["Can't parse that one (No CH)"L]]; line ¬ OthelloDefs.ReadShortNumber[ "Line: "L, 0, 3, line]; where ¬ [ deviceType: PhoneFace.phoneLine, deviceOrdinal: line, vp: ethernet [ [ bfn: [bfn], address: [ net: System.nullNetworkNumber, host: System.broadcastHostNumber, socket: NSConstants.bootServerSocket] ]]]; END; OthelloDefs.Yes["Pup/3MB? "L] => BEGIN bfn: CARDINAL ¬ OthelloDefs.ReadShortNumber[ "Pup Boot File Number: "L, 0, 177777B, 140000B]; board: CARDINAL ¬ 0; board ¬ OthelloDefs.ReadShortNumber[ "Board: "L, 0, 3, board]; where ¬ [ deviceType: DeviceTypes.ethernetOne, deviceOrdinal: board, vp: ethernetOne [ bootFileNumber: bfn, net: 0, host: 0 ] ]; END; ENDCASE => OthelloDefs.AbortingCommand["No other options implemented."L]; Parms.WriteBootLocation[where ! Parms.Error => BEGIN OthelloDefs.WriteString["Trouble Writing BootLocation: "L]; OthelloDefs.WriteLine[reason]; CONTINUE; END;]; OthelloDefs.WriteLine["done"L]; END; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Fetch Parm File Command --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FetchParmFile: PROC = BEGIN GetString: PROC [s: LONG STRING] = BEGIN OthelloDefs.WriteString["storing..."L]; Parms.WriteParms[s ! Parms.Error => BEGIN OthelloDefs.WriteString["Trouble Writing Parms: "L]; OthelloDefs.WriteLine[reason]; CONTINUE; END;]; END; OthelloDefs.MyNameIs[ myNameIs: "Fetch Parm File", myHelpIs: "Fetch Parameter File from FileServer and store it in EERom"L]; OthelloDefs.GetName["Parameter file: "L, @file ! OthelloDefs.Question => { OthelloDefs.WriteLine["Filename"L]; RESUME}]; IF ~ConnectionOpen[] AND ~ReOpen[] THEN BEGIN IF host # NIL THEN Open[]; IF ~ConnectionOpen[] THEN OthelloDefs.AbortingCommand["Please open a connection"L]; END; Retrieve[destination: [string[GetString]]]; OthelloDefs.WriteLine["done"L]; END; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Type Parm File Command --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TypeParmFile: PROC = BEGIN s: LONG STRING ¬ NIL; BEGIN ENABLE UNWIND => Heap.systemZone.FREE[@s]; boot: Boot.Location; write: System.GreenwichMeanTime; goodBoot, goodParms: BOOLEAN ¬ TRUE; OthelloDefs.MyNameIs[ myNameIs: "Type Parm File", myHelpIs: "Type Parameter File from EERom"L]; s ¬ Heap.systemZone.NEW[StringBody[Parms.GetMaxChars[]]]; [boot, write] ¬ Parms.GetBootLocation[ ! Parms.Error => BEGIN OthelloDefs.WriteString["Can't read BootLocation: "L]; OthelloDefs.WriteString[reason]; OthelloDefs.WriteLine["."L]; goodBoot ¬ FALSE; CONTINUE; END]; IF goodBoot THEN BEGIN OthelloDefs.WriteString["Boot Location Written: "L]; WriteTime[write]; OthelloDefs.WriteLine["."L]; OthelloDefs.WriteString["Boot Info: "L]; SELECT boot.deviceType FROM DeviceTypes.ethernet => BEGIN OthelloDefs.WriteString["NS/10MB Boot File #"L]; WriteBFN[boot.ethernetRequest.bfn]; OthelloDefs.WriteString[", Board: "L]; OthelloDefs.WriteLongNumber[boot.deviceOrdinal]; END; PhoneFace.phoneLine => BEGIN OthelloDefs.WriteString["NS/Phone Boot File #"L]; WriteBFN[boot.ethernetRequest.bfn]; OthelloDefs.WriteString[", Line: "L]; OthelloDefs.WriteLongNumber[boot.deviceOrdinal]; END; DeviceTypes.ethernetOne => BEGIN OthelloDefs.WriteString["Pup/3MB Boot File #"L]; OthelloDefs.WriteOctal[boot.bootFileNumber]; OthelloDefs.WriteString[", Board: "L]; OthelloDefs.WriteLongNumber[boot.deviceOrdinal]; END; ENDCASE => BEGIN p: POINTER TO ARRAY [0..0) OF WORD = LOOPHOLE[@boot]; FOR i: CARDINAL IN [0..SIZE[Boot.Location]) DO IF i # 0 THEN OthelloDefs.WriteString[", "L]; OthelloDefs.WriteOctal[p[i]]; ENDLOOP; END; OthelloDefs.WriteLine["."L]; END; OthelloDefs.WriteLine[""L]; [write] ¬ Parms.GetParms[s ! Parms.Error => BEGIN OthelloDefs.WriteString["Can't read Parms: "L]; OthelloDefs.WriteString[reason]; OthelloDefs.WriteLine["."L]; goodParms ¬ FALSE; CONTINUE; END]; IF goodParms THEN BEGIN OthelloDefs.WriteString["Parms Written: "L]; WriteTime[write]; OthelloDefs.WriteLine["."L]; OthelloDefs.WriteString["Text length: "L]; OthelloDefs.WriteLongNumber[s.length]; OthelloDefs.WriteString[". (Max is "L]; OthelloDefs.WriteLongNumber[Parms.GetMaxChars[]]; OthelloDefs.WriteLine[".)"L]; OthelloDefs.WriteLine[s]; END; OthelloDefs.WriteLine[""L]; Heap.systemZone.FREE[@s]; END; END; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- IO Routines --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ WriteTime: PROCEDURE [t: System.GreenwichMeanTime] = BEGIN temp: STRING = [40]; Time.Append[temp, Time.Unpack[t], TRUE]; OthelloDefs.WriteString[temp]; END; WriteBFN: PROCEDURE [bfn: Boot.EthernetBootFileNumber] = BEGIN Append: Format.StringProc = BEGIN String.AppendString[temp, s]; END; temp: STRING = [40]; Format.HostNumber[Append, bfn, octal]; OthelloDefs.WriteString[temp]; END; GetAddress: PROCEDURE [host: POINTER TO HostNumber, s: LONG STRING] = BEGIN host­ ¬ Unformat.HostNumber[s, octal]; END; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- MISC Stuff/Commands --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ userOpened: BOOLEAN ¬ FALSE; OpenCmd: PROC = { OthelloDefs.MyNameIs[myNameIs: "Open"L, myHelpIs: "STP Open"L]; CloseCmd[]; OthelloDefs.GetName["Open connection to "L, @host]; Open[]; userOpened ¬ TRUE}; ReOpen: PROC RETURNS [BOOLEAN] = { IF userOpened=FALSE THEN RETURN[FALSE]; Open[]; RETURN[TRUE]}; CloseCmd: PROC = { OthelloDefs.MyNameIs[myNameIs: "Close"L, myHelpIs: "STP Close"L]; userOpened ¬ FALSE; Close[]}; RemoteList: PROC = { OthelloDefs.MyNameIs[ myNameIs: "List Remote Files"L, myHelpIs: "List Remote Files"L]; IF ~ConnectionOpen[] AND ~ReOpen[] THEN OthelloDefs.AbortingCommand["Please open a connection"L]; OthelloDefs.GetName["Pattern: "L, @file]; IF String.Length[file] = 0 THEN String.AppendCharAndGrow[@file, '*, Heap.systemZone]; ListFiles[]}; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Central commands --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ commandProcessor: OthelloDefs.CommandProcessor ¬ [FtpCommands]; FtpCommands: PROC [index: CARDINAL] = { SELECT index FROM 0 => TypeParmFile[]; 1 => SetBootLocation[]; 2 => FetchParmFile[]; 3 => Directory[]; 4 => GetUserNamePassword[]; 5 => OpenCmd[]; 6 => CloseCmd[]; 7 => RemoteList[]; ENDCASE => OthelloDefs.IndexTooLarge}; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- STP Stuff/Commands --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ stp: STP.Handle ¬ NIL; ConnectionOpen: PROC RETURNS [BOOLEAN] = { RETURN[stp # NIL AND STP.IsOpen[stp]]}; -- all callers close the connection first Open: PROC = { herald: LONG STRING ¬ NIL; IF stp = NIL THEN stp ¬ STP.Create[]; DO herald ¬ STP.Open[stp, host ! STP.Error => SELECT code FROM connectionTimedOut, connectionClosed, noRouteToNetwork, noNameLookupResponse, connectionRejected => { OthelloDefs.WriteLine[error]; CONTINUE}; ENDCASE => OthelloDefs.AbortingCommand[error]]; IF herald # NIL THEN EXIT; Process.Pause[Process.SecondsToTicks[10]]; OthelloDefs.CheckUserAbort[]; ENDLOOP; OthelloDefs.WriteLine[herald]; Heap.systemZone.FREE[@herald]; STP.SetHost[stp, host]}; Close: PROC = { IF ~ConnectionOpen[] THEN RETURN; STP.Close[stp ! STP.Error => OthelloDefs.AbortingCommand[error]]; OthelloDefs.WriteLine["Connection closed"L]}; -- could mess with directories. -- who cares ListFiles: PROC = { ListOne: STP.NoteFileProcType = { info: STP.FileInfo = STP.GetFileInfo[stp]; OthelloDefs.WriteString[file]; THROUGH [file.length..80-info.create.length) DO OthelloDefs.WriteChar[' ] ENDLOOP; OthelloDefs.WriteLine[info.create]; --OthelloDefs.WriteChar[' ]; --OthelloDefs.WriteLine[info.author]; --OthelloDefs.WriteChar[' ]; --OthelloDefs.WriteLongNumber[info.size]; --OthelloDefs.WriteLine[" bytes]"L]; OthelloDefs.CheckUserAbort[]; RETURN[yes]}; STP.Login[stp, userName, userPassword]; STP.SetDirectory[stp, directory]; STP.Enumerate[stp, file, ListOne ! STP.Error => OthelloDefs.AbortingCommand[error]]}; Destination: TYPE = RECORD [ SELECT type: * FROM string => [stringProc: PROC [LONG STRING]], ENDCASE]; StartFeedback: SIGNAL = CODE; Retrieve: PROC [destination: Destination] = BEGIN rs: Stream.Handle; Cleanup: PROC = BEGIN rs.delete[rs]; END; rs ¬ GetReadStream[! STP.Error => OthelloDefs.AbortingCommand[error]]; IF rs=NIL THEN RETURN; GrabBits[rs, destination ! STP.Error => OthelloDefs.AbortingCommand[error]; StartFeedback => { OthelloDefs.WriteString["Fetching..."L]; RESUME}; UNWIND => Cleanup[]; ]; Cleanup[]; END; GetReadStream: PROC RETURNS [rs: Stream.Handle] = { STP.Login[stp, userName, userPassword]; STP.SetDirectory[stp, directory]; rs ¬ STP.CreateRemoteStream[stp, file, read]; rs.options.signalEndOfStream ¬ TRUE; DO info: STP.FileInfo; s: LONG STRING; s ¬ STP.NextFileName[rs ! UNWIND => rs.delete[rs]]; IF s = NIL THEN {rs.delete[rs]; RETURN[NIL]}; info ¬ STP.GetFileInfo[stp ! UNWIND => rs.delete[rs]]; OthelloDefs.WriteString[s]; Heap.systemZone.FREE[@s]; OthelloDefs.WriteChar['[]; OthelloDefs.WriteString[info.create]; OthelloDefs.WriteString[", bytes = "]; OthelloDefs.WriteLongNumber[info.size]; OthelloDefs.WriteChar[']]; IF OthelloDefs.Yes[" [Confirm]: "L ! UNWIND => rs.delete[rs]] THEN EXIT; ENDLOOP; RETURN}; bufPages: CARDINAL = 8; GrabBits: PROC [ rs: Stream.Handle, destination: Destination] = { WITH destination SELECT FROM string => { SIGNAL StartFeedback; DO stringOverhead: CARDINAL = SIZE[StringBody]*Environment.bytesPerWord; string: LONG STRING = Space.ScratchMap[bufPages]; string­ ¬ [ length: 0, maxlength: bufPages*Environment.bytesPerPage - stringOverhead, text: ]; WHILE string.length < string.maxlength DO got: CARDINAL; [bytesTransferred: got] ¬ rs.get[ rs, [blockPointer: LOOPHOLE[@string.text], startIndex: string.length, stopIndexPlusOne: string.maxlength], rs.options ! Stream.EndOfStream => { got ¬ 0; string.length ¬ string.length + nextIndex; CONTINUE}; UNWIND => [] ¬ Space.Unmap[string]]; IF got = 0 THEN { stringProc[string! UNWIND => [] ¬ Space.Unmap[string]]; [] ¬ Space.Unmap[string]; RETURN}; string.length ¬ string.length + got; ENDLOOP; [] ¬ Space.Unmap[string]; OthelloDefs.AbortingCommand["Command file too long!"L]; ENDLOOP}; ENDCASE => ERROR}; --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- initialization --~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bootFileNumber ¬ String.CopyToNewString["25200002000", Heap.systemZone]; host ¬ String.CopyToNewString["Indigo", Heap.systemZone]; directory ¬ String.CopyToNewString["Portola>Parameters", Heap.systemZone]; file ¬ String.CopyToNewString[Indirect.GetParmFileName[], Heap.systemZone]; OthelloDefs.RegisterCommandProc[@commandProcessor]; END.....