-- File: InitParms.mesa - last edit:
-- WIrish.PA 25-Feb-88 21:27:52
-- HGM 10-Mar-85 5:54:04
-- Copyright (C) 1982, 1984, 1985, 1988 by Xerox Corporation. All rights reserved.
DIRECTORY
Boot USING [EthernetBootFileNumber, Location],
Device USING [Type],
DeviceTypes USING [ethernet, ethernetOne],
EERom USING [SeeData],
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
EERom, 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];
EERom.SeeData[]; -- a boot switch may have "deactivated" the EERom
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.....