-- File: PupHacks.mesa, Last Edit: HGM January 24, 1981 2:16 PM -- From OthelloPup.mesa of August 29, 1980 9:21 AM DIRECTORY -- Things from the system IODefs, Process USING [Detach, Yield], Runtime USING [GetBcdTime], String USING [AppendLongDecimal], Time USING [Append, Unpack], -- Pup things... DriverDefs USING [Network], PupDefs USING [ AppendPupAddress, DataWordsPerPupBuffer, GetFreePupBuffer, GetPupAddress, GetPupContentsBytes, MoveStringBodyToPupBuffer, ReturnFreePupBuffer, PupBuffer, PupNameTrouble, PupPackageDestroy, PupPackageMake, PupRouterBroadcastThis, PupSocket, PupSocketDestroy, PupSocketMake, SecondsToTocks, SetPupContentsBytes], PupRouterDefs USING [ EnumerateRoutingTable, GetRoutingTableEntry, RoutingTableEntry], PupTypes USING [ echoSoc, fillInPupAddress, fillInSocketID, maxDataWordsPerGatewayPup, miscSrvSoc, PupAddress]; PupHacks: PROGRAM IMPORTS IODefs, Process, Runtime, String, Time, PupDefs, PupRouterDefs = BEGIN OPEN IODefs; name: STRING _ [40]; -- Global so ESC will work AddressToName: PROCEDURE = BEGIN OPEN PupTypes, PupDefs; soc: PupSocket; b: PupBuffer; a: PupAddress _ [, , [0, 0]]; hit: BOOLEAN _ FALSE; WriteString["Address to Name for: "L]; ReadID[name ! Rubout => {WriteLine[" XXX"L]; GOTO NoName; }]; IF name.length = 0 THEN BEGIN WriteLine["Address needed."L]; RETURN; END; GetPupAddress[ @a, name ! PupNameTrouble => BEGIN WriteLine[e]; GOTO NoName; END]; soc _ PupSocketMake[fillInSocketID, fillInPupAddress, SecondsToTocks[2]]; THROUGH [0..10) UNTIL hit DO b _ GetFreePupBuffer[]; b.pupType _ addressLookup; b.pupID _ [0, 0]; b.dest.socket _ PupTypes.miscSrvSoc; b.source _ soc.getLocalAddress[]; b.address _ a; SetPupContentsBytes[b, 2*SIZE[PupAddress]]; PupRouterBroadcastThis[b]; UNTIL hit OR (b _ soc.get[]) = NIL DO SELECT b.pupType FROM addressIs => BEGIN hit _ TRUE; WriteString[" => "L]; PrintBodyAsText[b]; END; nameError => BEGIN hit _ TRUE; WriteString[" => ERROR: "L]; PrintBodyAsText[b]; END; ENDCASE => PrintErrorPup[b]; WriteLine["."L]; ReturnFreePupBuffer[b]; ENDLOOP; IF ~hit THEN WriteLine["No Response that try."L]; ENDLOOP; PupSocketDestroy[soc]; EXITS NoName => NULL; END; EchoUser: PROCEDURE = BEGIN OPEN PupDefs, PupTypes; bytesPerBuffer: CARDINAL; funny, late, recv, sent, wrong: LONG CARDINAL _ 0; me, where: PupAddress _ [, , echoSoc]; mySoc: PupSocket; packetNumber: CARDINAL _ 0; pleaseStop: BOOLEAN _ FALSE; routing: PupRouterDefs.RoutingTableEntry; Watch: PROCEDURE = {[] _ ReadChar[]; pleaseStop _ TRUE}; WriteString["Echo to: "L]; ReadID[name ! Rubout => {WriteLine[" XXX"L]; GOTO NoName; }]; IF name.length = 0 THEN BEGIN WriteLine["Name needed"L]; RETURN; END; GetPupAddress[ @where, name ! PupNameTrouble => {WriteString[" ***** "L]; WriteLine[e]; GOTO NoName}]; mySoc _ PupSocketMake[fillInSocketID, where, SecondsToTocks[2]]; me _ mySoc.getLocalAddress[]; WriteString[". ["L]; PrintPupAddress[me]; WriteString["] => ["L]; routing _ PupRouterDefs.GetRoutingTableEntry[where.net]; IF routing.hop # 0 THEN BEGIN -- UGH WriteNumber[routing.network.netNumber.b, [8, FALSE, TRUE, 0]]; WriteChar['#]; WriteNumber[routing.route, [8, FALSE, TRUE, 0]]; WriteChar['#]; WriteString["] => ["L]; END; PrintPupAddress[where]; WriteLine["]..."L]; Process.Detach[FORK Watch[]]; bytesPerBuffer _ 2*MIN[DataWordsPerPupBuffer[], maxDataWordsPerGatewayPup]; UNTIL pleaseStop DO FOR len: CARDINAL IN [0..bytesPerBuffer] UNTIL pleaseStop DO b: PupBuffer _ GetFreePupBuffer[]; b.pupID.a _ b.pupID.b _ (packetNumber _ packetNumber + 1); b.pupType _ echoMe; SetPupContentsBytes[b, len]; FOR i: CARDINAL IN [0..len) DO b.pupBytes[i] _ i; ENDLOOP; mySoc.put[b]; sent _ sent + 1; Process.Yield[]; -- be sure we don't hog machine UNTIL (b _ mySoc.get[]) = NIL DO SELECT TRUE FROM (b.pupType # iAmEcho) => {funny _ funny + 1; PrintErrorPup[b]}; ((b.pupID.a # packetNumber) OR (b.pupID.b # packetNumber) OR (len # GetPupContentsBytes[b])) => {WriteChar['#]; late _ late + 1}; ENDCASE => BEGIN FOR i: CARDINAL IN [0..len) DO IF b.pupBytes[i] # (i MOD 400B) THEN { wrong _ wrong + 1; WriteChar['~]; GOTO Wrong}; ENDLOOP; WriteChar['!]; recv _ recv + 1; EXIT; END; ReturnFreePupBuffer[b]; REPEAT Wrong => NULL; ENDLOOP; IF b # NIL THEN ReturnFreePupBuffer[b] ELSE WriteChar['?]; ENDLOOP; WriteCR[]; ENDLOOP; PupSocketDestroy[mySoc]; WriteString["Out: "L]; WriteLongNumber[sent]; WriteString[", In: "L]; WriteLongNumber[recv]; WriteString[" ("L]; WriteLongNumber[(recv*100)/sent]; WriteLine["%)"L]; IF late # 0 THEN BEGIN WriteString["Late: "L]; WriteLongNumber[late]; WriteString[" ("L]; WriteLongNumber[(late*100)/sent]; WriteLine["%)"L]; END; IF funny # 0 THEN {WriteLongNumber[funny]; WriteLine[" funny"L]}; IF wrong # 0 THEN {WriteLongNumber[wrong]; WriteLine[" wrong data"L]}; EXITS NoName => NULL; END; NameToAddress: PROCEDURE = BEGIN OPEN PupTypes, PupDefs; soc: PupSocket; b: PupBuffer; hit: BOOLEAN _ FALSE; WriteString["Name to Address for: "L]; ReadID[name ! Rubout => {WriteLine[" XXX"L]; GOTO NoName; }]; IF name.length = 0 THEN BEGIN WriteLine["Name needed"L]; RETURN; END; soc _ PupSocketMake[fillInSocketID, fillInPupAddress, SecondsToTocks[2]]; THROUGH [0..10) UNTIL hit DO b _ GetFreePupBuffer[]; b.pupType _ nameLookup; b.pupID _ [0, 0]; b.dest.socket _ PupTypes.miscSrvSoc; b.source _ soc.getLocalAddress[]; MoveStringBodyToPupBuffer[b, name]; PupRouterBroadcastThis[b]; UNTIL hit OR (b _ soc.get[]) = NIL DO SELECT b.pupType FROM nameIs => BEGIN n: CARDINAL _ GetPupContentsBytes[b]/(2*SIZE[PupAddress]); addresses: LONG POINTER TO ARRAY [0..0) OF PupAddress _ LOOPHOLE[@b.pupBody]; hit _ TRUE; WriteString[" => "L]; FOR i: CARDINAL IN [0..n) DO IF i # 0 THEN WriteString[", "L]; PrintPupAddress[addresses[i]]; ENDLOOP; END; nameError => BEGIN hit _ TRUE; WriteString[" => ERROR: "L]; PrintBodyAsText[b]; END; ENDCASE => PrintErrorPup[b]; WriteCR[]; ReturnFreePupBuffer[b]; ENDLOOP; IF ~hit THEN WriteLine["No Response that try."L]; ENDLOOP; PupSocketDestroy[soc]; EXITS NoName => NULL; END; RoutingTable: PROCEDURE = BEGIN PrintOne: PROCEDURE [rte: PupRouterDefs.RoutingTableEntry] = BEGIN network: DriverDefs.Network _ rte.network; IF network = NIL THEN RETURN; nets _ nets + 1; IF k = 0 THEN WriteChar['|]; O4[rte.net]; O4[network.netNumber.b]; WriteChar['#]; IF rte.hop # 0 THEN O3Z[rte.route] ELSE O3Z[network.hostNumber]; WriteChar['#]; O4[rte.hop]; WriteString[" |"L]; IF (k _ k + 1) = 3 THEN BEGIN WriteCR[]; k _ 0; END; END; k, nets: CARDINAL _ 0; WriteCR[]; WriteLine[" Local Routing Table."L]; WriteLine["| Net Via Hops | Net Via Hops | Net Via Hops |"L]; WriteLine["|-------------------|-------------------|-------------------|"L]; PupRouterDefs.EnumerateRoutingTable[PrintOne]; IF k # 0 THEN WriteCR[]; IF nets > 1 THEN BEGIN WriteString["There are "L]; WriteDecimal[nets - 1]; WriteLine[" active networks."L]; END; END; PrintErrorPup: PROCEDURE [b: PupDefs.PupBuffer] = BEGIN source: PupTypes.PupAddress _ b.source; WriteCR[]; IF b.pupType = error THEN BEGIN len: CARDINAL = PupDefs.GetPupContentsBytes[b]; WriteString["[Error Pup, code="L]; WriteOctal[b.errorCode]; WriteString[", from: "L]; PrintPupAddress[source]; WriteString["] "L]; FOR i: CARDINAL IN [0..len - 2*(10 + 1 + 1)) DO WriteChar[b.errorText[i]]; ENDLOOP; END ELSE BEGIN WriteString[" ***** "L]; WriteString["Funny PupType = "L]; WriteOctal[b.pupType]; WriteString[" ***** "L]; END; WriteCR[]; END; PrintPupAddress: PROCEDURE [a: PupTypes.PupAddress] = BEGIN buffer: STRING _ [50]; PupDefs.AppendPupAddress[buffer, a]; WriteString[buffer]; END; PrintBodyAsText: PROCEDURE [b: PupDefs.PupBuffer] = BEGIN FOR i: CARDINAL IN [0..PupDefs.GetPupContentsBytes[b]) DO WriteChar[b.pupChars[i]]; ENDLOOP; END; CommandLoop: PROCEDURE = BEGIN PupDefs.PupPackageMake[]; PrintHeaderLine[]; DO c: CHARACTER; WriteChar['>]; c _ ReadChar[]; SELECT c FROM 'A, 'a => AddressToName[]; 'E, 'e => EchoUser[]; 'N, 'n => NameToAddress[]; 'R, 'r => RoutingTable[]; 'Q, 'q => BEGIN WriteLine["Quit."L]; EXIT; END; 'H, 'h, '? => WriteLine[ " Commands are: A(ddress to Name), E(cho), N(ame to Address), or R(outing). H(elp) or ? prints this message. Q(uit) gets you out of here."L]; ENDCASE => WriteLine["? XXX"L]; ENDLOOP; PupDefs.PupPackageDestroy[]; END; PrintHeaderLine: PROCEDURE = BEGIN version: STRING = [20]; me: PupTypes.PupAddress _ [, , [0, 0]]; WriteString[" PupHacks of "L]; Time.Append[version, Time.Unpack[Runtime.GetBcdTime[]]]; WriteString[version]; WriteString[" running on "L]; PupDefs.GetPupAddress[@me, "ME"L]; PrintPupAddress[me]; WriteLine["."]; END; WriteLongNumber: PROCEDURE [n: LONG CARDINAL] = BEGIN temp: STRING = [20]; String.AppendLongDecimal[temp, n]; WriteString[temp]; END; -- prints 4 chars, octal, no trailing B O4: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, [8, FALSE, TRUE, 4]]; END; -- prints 3 chars, octal, leading zeros O3Z: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, [8, TRUE, TRUE, 3]]; END; WriteCR: PROCEDURE = BEGIN WriteLine[""L]; END; -- initialization CommandLoop[]; END.