// Gateway.bcpl

// Last modified March 10, 1979  3:30 PM by Boggs

get "Pup0.decl"
get "Pup1.decl"

external
[
// outgoing procedures
Gateway; GatewayFinish

// incoming procedures
GatewayInit; CallContextList; Enqueue; SetAllocation
AddToZone; Allocate; Free; CallDos; ResetTimeServ
Ws; Endofs; Gets; HaltGateway; SetTimer; TimerHasExpired

// outgoing statics
versionText

// incoming statics
pbiFreeQ; lenPBI; ndbQ; socketQ; dPSIB; numNets
userFinishProc; sysZone; ctxQ; keys
]

static versionText

manifest
[
// Dos commands
reset = 65000b
ertn = 66400b
]

//----------------------------------------------------------------------------
let Gateway(blv) be
//----------------------------------------------------------------------------
[
versionText = "Nova Gateway of March 10, 1979"

GatewayInit(blv)

// throw away initialization code, add space to zone,
AddToZone(sysZone, GatewayInit, blv!29-GatewayInit-1)

// turn all remaining storage into pbis except for a small chunk
let pbiCount = 0
let freeSlop = Allocate(sysZone, 400)
   [
   let pbi = Allocate(sysZone, lenPBI, true)
   if pbi eq 0 break
   Enqueue(pbiFreeQ, pbi)
   pbiCount = pbiCount+1
   ] repeat
Free(sysZone, freeSlop)

// fix allocations to reflect real number of pbis
pbiCount = pbiCount-numNets
let fakeSoc = dPSIB - offset PupSoc.psib/16
SetAllocation(fakeSoc, pbiCount, pbiCount-1, pbiCount-1)
let soc = socketQ!0
while soc ne 0 do
   [  //update allocations in all sockets
   SetAllocation(soc, pbiCount, pbiCount-1, pbiCount-1)
   soc = soc!0
   ]
let ndb = ndbQ!0
while ndb ne 0 do
   [  //update gateway allocations in ndbs
   ndb>>NDB.numGPBI = pbiCount rshift 1
   ndb = ndb!0
   ]

ResetTimeServ()
Ws("**** Gateway in operation *****N*L")

let quitTimer = 0
   [
   if quitTimer ne 0 & TimerHasExpired(lv quitTimer) then quitTimer = 0
   unless Endofs(keys) switchon Gets(keys) into
      [
      case $Q: case $q:
         [
         Ws("*NQuit [Confirm] ")
         SetTimer(lv quitTimer, 1000)
         endcase
         ]
      case $*177: case $N: case $n:
         if quitTimer ne 0 then
            [ Ws("No.*N"); quitTimer = 0; endcase ]
      case $*N: case $Y: case $y:
         if quitTimer ne 0 then
            [ Ws("Yes.*N"); HaltGateway(); quitTimer = 0; endcase ]
      default:
         [ Ws("*N? - There is only one command: QUIT"); endcase ]
      ]
   CallContextList(ctxQ!0)
   ] repeat
]

//----------------------------------------------------------------------------
and GatewayFinish(code) be
//----------------------------------------------------------------------------
[
Ws("**** Shutdown complete *****N*L")  // well, not quite, but close enough
while userFinishProc ne 0 do userFinishProc()
CallDos(reset)
CallDos(ertn, nil, nil, code)
]