// IfsTelnetLogin.bcpl -- IFS server telnet Login, Logout, Connect commands
// Copyright Xerox Corporation 1979, 1980, 1981

// Last modified November 17, 1981  9:15 PM by Taft

get "Ifs.decl"
get "IfsRs.decl"
get "IfsTelnet.decl"
get "IfsFiles.decl"
get "IfsDirs.decl"

external
[
// outgoing procedures
ExecLogin; ExecLogout; ExecConnect; ExecDirectory

// incoming procedures
CreateUserInfo; DestroyUserInfo
GetPhrase; GetString; TerminatingChar; Confirm; EnableCatch; EndCatch
BeginDefaultPhrase; EndDefaultPhrase
TelnetCommandQuit; AbortCmd
Login; Connect; Password; FreePointer; IFSPrintError; PutTemplate
LookupIFSFile; DestroyFD; ByteBlt
Puts; Errors; Wss; Ws; SysFree; FalsePredicate

// incoming statics
noLoginKT; loginKT; enableKT; entFlag; haltFlag
CtxRunning; dsp
]

//---------------------------------------------------------------------------
let ExecLogin(cs) be
//---------------------------------------------------------------------------
// Login <username> <password> <optional-account>
[
let name, password = 0, 0
Wss(cs, " (user) ")
if EnableCatch(cs) then
   [
   DestroyUserInfo(CtxRunning>>TCtx.userInfo)
   CtxRunning>>TCtx.userInfo = CreateUserInfo()
   FreePointer(lv name, lv password)
   EndCatch(cs)
   ]

let ui = CtxRunning>>TCtx.userInfo
name = GetString(cs, 0, Wss, "user name")
Wss(cs, " (password) ")
password = GetString(cs, 0, Wss, "password", FalsePredicate)
let ec = Login(name, password, ui)
FreePointer(lv name, lv password)

if ec ne 0 then
   [ Puts(dsp, $*n); IFSPrintError(dsp, ec); AbortCmd(cs) ]

if TerminatingChar(cs) ne $*n then
   [
   Wss(cs, " (account) ")
   GetPhrase(cs, 0, 0, 0, Wss, "account")
   ]

CtxRunning>>TCtx.topKT = loginKT
CtxRunning>>TCtx.capabilities = ui>>UserInfo.capabilities
ui>>UserInfo.capabilities = 0
TelnetCommandQuit(cs)  //so new topKT is noticed
]

//---------------------------------------------------------------------------
and ExecConnect(cs) be
//---------------------------------------------------------------------------
// Connect <dir-name> <password>
[
let ui = CtxRunning>>TCtx.userInfo
let name = 0
let ec = ecConnectPassword
Wss(cs, " (to directory) ")
if EnableCatch(cs) then [ FreePointer(lv name); EndCatch(cs) ]

name = GetString(cs, 0, Wss, "directory name")
if TerminatingChar(cs) eq $*n then
   ec = Connect(name, "", ui)  // attempt to connect without password

if ec eq ecConnectPassword then
   [
   Wss(cs, " (password) ")
   let password = GetString(cs, 0, Wss, "password", FalsePredicate)
   ec = Connect(name, password, ui)
   SysFree(password)
   ]

if ec ne 0 then
   [ Puts(dsp, $*n); IFSPrintError(dsp, ec); AbortCmd(cs) ]

FreePointer(lv name, lv ui>>UserInfo.defaultDir)
]

//---------------------------------------------------------------------------
and ExecLogout(cs) be
//---------------------------------------------------------------------------
[
if TerminatingChar(cs) eq $*n % Confirm(cs) then
   [
   if not entFlag & not haltFlag &
    CtxRunning>>TCtx.userInfo>>UserInfo.capabilities.wheel then
      unless Confirm(cs, "*nLogins are disabled!  Are you sure?") return
   Puts(cs, $*n)
   CtxRunning>>TCtx.logout = true
   TelnetCommandQuit(cs)
   ]
]

//---------------------------------------------------------------------------
and ExecDirectory(cs) be
//---------------------------------------------------------------------------
// Directory <default-directory-pathname>
[
Wss(cs, " (default) ")
let ui = CtxRunning>>RSCtx.userInfo
BeginDefaultPhrase(cs)
PutTemplate(cs, "<$S>", (ui>>UserInfo.defaultDir ne 0?
 ui>>UserInfo.defaultDir, ui>>UserInfo.connName))
EndDefaultPhrase(cs)
let dir = GetString(cs, 0, Wss, "<directory>subdirectory>...>")

test dir>>String.length eq 0
   ifso
      [
      FreePointer(lv dir, lv ui>>UserInfo.defaultDir)
      dir = ui>>UserInfo.connName
      ]
   ifnot
      [
      if dir>>String.char↑1 eq $< then
         [
         dir>>String.length = dir>>String.length-1
         ByteBlt(dir, 1, dir, 2, dir>>String.length)
         ]
      if dir>>String.char↑(dir>>String.length) eq $> then
         dir>>String.length = dir>>String.length-1

      // Check that it is well-formed and that the initial <dir> substring
      // corresponds to an existing directory name.
      let ec = nil
      let fd = LookupIFSFile("", lcVHighest, lv ec, 0, dir)
      if fd ne 0 then DestroyFD(fd)
      unless ec eq 0 % ec eq ecFileNotFound do
         [ SysFree(dir); Errors(cs, 0) ]
      FreePointer(lv ui>>UserInfo.defaultDir)
      ui>>UserInfo.defaultDir = dir
      ]

PutTemplate(dsp, "*nDefault directory changed to <$S>.", dir)
]