// FtpUserProt.bcpl - User FTP protocol routines
// Copyright Xerox Corporation 1979, 1980, 1982
// Last modified May 13, 1982  1:09 PM by Boggs

get "Pup.decl"
get "FtpProt.decl"

external
[
// outgoing procedures
UserOpen; UserClose
UserFlushEOC; UserGetYesNo; UserProtocolError

// incoming procedrues
CloseBSPSocket; Wss; Free
FTPM; GetCommand

// incoming statics
CtxRunning; defaultTimeout; sysZone
]

//-----------------------------------------------------------------------------------------
let UserOpen(Version) = valof
//-----------------------------------------------------------------------------------------
[
CtxRunning>>FtpCtx.serverFlag = false
CtxRunning>>FtpCtx.newStore = true
CtxRunning>>FtpCtx.newDirectory = true
FTPM(markVersion, FTPVersion, "$P", true, Version)
let ok = valof
   [
   let mark = GetCommand()
   if mark<<Mark.mark ne markVersion resultis false
   if mark<<Mark.subCode eq FTPVersion resultis UserFlushEOC()
   Wss(CtxRunning>>FtpCtx.lst, "*NProtocol incompatible -- aborting")
   resultis false
   ]
test ok
   ifso CtxRunning>>FtpCtx.connFlag = true
   ifnot UserClose(true)
resultis ok
]

//-----------------------------------------------------------------------------------------
and UserClose(abortIt) be
//-----------------------------------------------------------------------------------------
[
if CtxRunning>>FtpCtx.getCmdString then
   [
   Free(sysZone, CtxRunning>>FtpCtx.getCmdString)
   CtxRunning>>FtpCtx.getCmdString = 0
   ]
if CtxRunning>>FtpCtx.connFlag then
   [
   CtxRunning>>FtpCtx.connFlag = false
   CloseBSPSocket(CtxRunning>>FtpCtx.bspSoc, (abortIt? 0, defaultTimeout))
   ]
]

//-----------------------------------------------------------------------------------------
and UserFlushEOC() = valof
//-----------------------------------------------------------------------------------------
//suck up byte stream until next EOC, return false if error
[
let mark = GetCommand()
if mark<<Mark.mark eq markEndOfCommand then resultis true
unless mark eq 0 do UserProtocolError()
resultis false
]

//-----------------------------------------------------------------------------------------
and UserGetYesNo(flushEOC) = valof
//-----------------------------------------------------------------------------------------
// Returns markYes|markNo,,subCode
// Returns 0 if something is seriously wrong
[
let mark = GetCommand()
switchon mark<<Mark.mark into
   [
   default: UserProtocolError()  //falls through
   case 0: resultis 0
   case markYes: case markNo:
      [
      if flushEOC then unless UserFlushEOC() resultis 0
      resultis mark
      ]
   ]
]

//-----------------------------------------------------------------------------------------
and UserProtocolError() be
//-----------------------------------------------------------------------------------------
[
Wss(CtxRunning>>FtpCtx.lst, "*NFTP protocol error -- aborting connection")
UserClose(true)
]