-- Copyright (C) 1983 by Xerox Corporation. All rights reserved.
-- PupBootServerNoDisk.mesa, HGM, 11-Dec-83 19:00:15
DIRECTORY
Ascii USING [CR],
CmFile USING [Handle, TableError],
Event USING [aboutToSwap],
EventTypes USING [aboutToBoot, aboutToBootPhysicalVolume],
Heap USING [systemZone],
Process USING [Detach],
Put USING [Text],
String USING [AppendChar, AppendNumber, AppendString],
StringLookUp USING [noMatch],
Supervisor USING [
AddDependency, AgentProcedure, CreateSubsystem, RemoveDependency,
SubsystemHandle],
Token USING [FreeTokenString, Item, Octal],
Buffer USING [ReturnBuffer],
BootServerDefs USING [
bootStatsRequest,
BreatherOff, BreatherOn,
lockBooterRequest, lockBooterReply, unlockBooterRequest, unlockBooterReply,
microcodeRequest, sunBootRequest],
Driver USING [Network],
Indirect USING [Close, GetParmFileName, NextValue, OpenSection],
MiscServerDefs USING [
PupMiscServerOn, PupMiscServerOff, IgnoreThisPacket, SetBootServer],
PupDefs USING [
GetPupAddress, PupBuffer, PupNameTrouble, PupRouterSendThis, ReturnPup],
PupTypes USING [fillInPupAddress, PupAddress, PupNetID],
Stats USING [StatCounterIndex, StatsStringToIndex];
PupBootServerNoDisk: MONITOR
IMPORTS
CmFile, Event, Heap, Indirect, Process, Put,
String, Supervisor, Token, MiscServerDefs,
Buffer, BootServerDefs, PupDefs, Stats
EXPORTS Buffer, BootServerDefs
SHARES Buffer =
BEGIN
Network: PUBLIC TYPE = Driver.Network;
broom: Supervisor.SubsystemHandle = Supervisor.CreateSubsystem[Broom];
z: UNCOUNTED ZONE = Heap.systemZone;
remote: Chain ← NIL;
Chain: TYPE = LONG POINTER TO ChainSlot;
ChainSlot: TYPE = RECORD [
next: Chain,
source: PupTypes.PupNetID,
dest: PupTypes.PupAddress,
target: LONG STRING];
dirRunning: PUBLIC BOOLEAN ← FALSE;
useCount: CARDINAL ← 0;
lock: BOOLEAN ← FALSE;
verbose: BOOLEAN = TRUE;
parmFileName: LONG STRING ← Indirect.GetParmFileName[];
statLife: PUBLIC Stats.StatCounterIndex;
PupBootServerOn: PUBLIC ENTRY PROCEDURE =
BEGIN
IF (useCount ← useCount + 1) = 1 THEN
BEGIN
Supervisor.AddDependency[client: broom, implementor: Event.aboutToSwap];
dirRunning ← TRUE;
Starter[];
END;
END;
Starter: PROCEDURE =
BEGIN
MiscServerDefs.PupMiscServerOn[];
ScanParameterFile[];
MiscServerDefs.SetBootServer[PupBootServer];
Process.Detach[FORK BootServerDefs.BreatherOn[]];
END;
PupBootServerOff: PUBLIC ENTRY PROCEDURE =
BEGIN
IF useCount # 0 AND (useCount ← useCount - 1) = 0 THEN
BEGIN
dirRunning ← FALSE;
Stopper[];
Supervisor.RemoveDependency[client: broom, implementor: Event.aboutToSwap];
END;
END;
Stopper: INTERNAL PROCEDURE =
BEGIN
BootServerDefs.BreatherOff[];
MiscServerDefs.SetBootServer[MiscServerDefs.IgnoreThisPacket];
ForgetParameters[];
MiscServerDefs.PupMiscServerOff[];
END;
PupBootServer: PUBLIC PROCEDURE [b: PupDefs.PupBuffer] =
BEGIN OPEN BootServerDefs;
SELECT b.pup.pupType FROM
bootFileSend, microcodeRequest, bootDirReq, sunBootRequest => ForwardThisOne[b];
bootStatsRequest => Buffer.ReturnBuffer[b];
lockBooterRequest =>
BEGIN lock ← TRUE; PupDefs.ReturnPup[b, lockBooterReply, 0]; END;
unlockBooterRequest =>
BEGIN lock ← FALSE; PupDefs.ReturnPup[b, unlockBooterReply, 0]; END;
ENDCASE => Buffer.ReturnBuffer[b];
END;
ForwardThisOne: PROCEDURE [b: PupDefs.PupBuffer] =
BEGIN
in: Driver.Network = b.network;
IF b.pup.source.net = 0 THEN b.pup.source.net ← [in.pupNetNumber];
FOR finger: Chain ← remote, finger.next UNTIL finger = NIL DO
IF in.pupNetNumber = finger.source THEN
BEGIN
IF finger.dest = PupTypes.fillInPupAddress THEN EXIT;
b.pup.dest.net ← finger.dest.net;
b.pup.dest.host ← finger.dest.host;
PupDefs.PupRouterSendThis[b];
RETURN;
END;
ENDLOOP;
Buffer.ReturnBuffer[b];
END;
ScanParameterFile: PROCEDURE =
BEGIN
cmFile: CmFile.Handle;
Option: TYPE = {remote};
NextValue: PROCEDURE [
h: CmFile.Handle, table: LONG DESCRIPTOR FOR ARRAY Option OF LONG STRING]
RETURNS [Option] = LOOPHOLE[Indirect.NextValue];
optionTable: ARRAY Option OF LONG STRING ← [remote: "Remote"L];
cmFile ← Indirect.OpenSection["PupBootServer"L];
IF cmFile = NIL THEN RETURN;
DO
option: Option;
option ← NextValue[
cmFile, DESCRIPTOR[optionTable] !
CmFile.TableError =>
BEGIN
IF name[0] # '; THEN Message["Unrecognized parameter: ", name];
RETRY;
END];
SELECT option FROM
LOOPHOLE[StringLookUp.noMatch] => EXIT;
remote =>
BEGIN
source: PupTypes.PupNetID = [Token.Octal[cmFile]];
temp: LONG STRING ← Token.Item[cmFile, FALSE];
new: Chain ← z.NEW[ChainSlot];
new↑ ← [NIL, source, PupTypes.fillInPupAddress, z.NEW[StringBody[temp.length]]];
String.AppendString[new.target, temp];
[] ← Token.FreeTokenString[temp];
PupDefs.GetPupAddress[@new.dest, new.target ! PupDefs.PupNameTrouble => CONTINUE];
IF remote = NIL THEN remote ← new
ELSE
BEGIN
FOR finger: Chain ← remote, finger.next DO
IF finger.next = NIL THEN
BEGIN
finger.next ← new;
EXIT;
END;
ENDLOOP;
END;
MessageNet["Forwarding Pup boot requests from net "L, new.source, " to "L, new.target];
END;
ENDCASE => ERROR;
ENDLOOP;
Indirect.Close[cmFile];
END;
ForgetParameters: PROCEDURE =
BEGIN
UNTIL remote = NIL DO
temp: Chain ← remote;
remote ← remote.next;
z.FREE[@temp.target];
z.FREE[@temp];
ENDLOOP;
END;
MessageNet: PROCEDURE [one: LONG STRING, net: CARDINAL, three, four: LONG STRING] =
BEGIN
two: STRING = [20];
String.AppendNumber[two, net, 8];
Message[one, two, three, four];
END;
Message: PROCEDURE [one, two, three, four: LONG STRING ← NIL] =
BEGIN
text: STRING = [200];
String.AppendString[text, one];
IF two # NIL THEN String.AppendString[text, two];
IF three # NIL THEN String.AppendString[text, three];
IF four # NIL THEN String.AppendString[text, four];
LogString[text];
END;
LogString: PROCEDURE [text: LONG STRING] =
BEGIN
String.AppendChar[text, '.];
String.AppendChar[text, Ascii.CR];
Put.Text[NIL, text];
END;
Broom: ENTRY Supervisor.AgentProcedure =
BEGIN
SELECT event FROM
EventTypes.aboutToBoot, EventTypes.aboutToBootPhysicalVolume =>
IF dirRunning THEN Stopper[];
ENDCASE => NULL;
END;
-- initialization
statLife ← Stats.StatsStringToIndex["Breath of Life packets sent"];
PupBootServerOn[];
END.