// IfsTelnet.bcpl -- top level command interpreter and useful subroutines // Copyright Xerox Corporation 1979, 1980, 1982 // Last modified April 9, 1982 5:14 PM by Taft get "IfsRs.decl" get "IfsTelnet.decl" get "CmdScan.decl" get "IfsFiles.decl" external [ // outgoing procedures TelnetTopLevel GetKeywordOrCR; Plural; TelnetAborting; TelnetCommandLoop; TelnetCommandQuit TelnetSubcommandPrompt; SelectKeyword; CreateKeywordIntegerMap; TelnetConfirm // incoming procedures InitTelnetJob; CleanupTelnetJob InitCmd; GetKeyword; GetPhrase; TerminatingChar; Confirm CreateKeywordTable; DestroyKeywordTable; InsertKeyword EnableCatch; DisableCatch; EndCatch DefaultArgs; ReturnFrom; IFSError; CallWithArgVec Puts; Endofs; Closes; Resets; Errors; Wss; Ws // incoming statics CtxRunning; keys; dsp atSubPrompt; bangSubPrompt; pluralString; singularString ] manifest ecReturnFromReturned = 103 //--------------------------------------------------------------------------- let TelnetTopLevel(ctx) be //--------------------------------------------------------------------------- // Top-level procedure for telnet server context. [ InitTelnetJob(ctx) [ //repeat TelnetCommandLoop(ctx>>TCtx.topKT, (ctx>>TCtx.userInfo>>UserInfo.capabilities ne 0? "*n!", "*n@")) if ctx>>TCtx.kill break if ctx>>TCtx.controlC then [ Resets(dsp) Resets(keys) ctx>>TCtx.controlC = false Ws("↑C") ] ] repeat CleanupTelnetJob(ctx) ] //--------------------------------------------------------------------------- and GetKeywordOrCR(cs, kt) = valof //--------------------------------------------------------------------------- // Returns pointer to keyword table entry, or zero if just a carriage // return is typed in. [ let entry = GetKeyword(cs, kt, true) if entry eq 0 then [ Resets(cs) unless GetPhrase(cs) eq 0 & TerminatingChar(cs) eq $*n do Errors(cs, ecKeyNotFound) ] resultis entry ] //--------------------------------------------------------------------------- and TelnetCommandLoop(kt, prompt, returnOnCR, arg, numChars, numPhrases, FixedProc; numargs na) be //--------------------------------------------------------------------------- // Accepts a keyword table kt whose entries are command procedures. // Repeatedly inputs a command keyword and calls Proc(cs, arg), where // Proc is the corresponding command procedure. If returnOnCR is true, // returns if just a carriage return is typed in response to the prompt. // If FixedProc is supplied, then instead of calling Proc(cs, arg) it // calls FixedProc(cs, entry, arg). [ DefaultArgs(lv na, -2, false, 0, maxCmdChars, maxCmdPhrases, 0) [ //repeat let cs = InitCmd(numChars, numPhrases) if cs ne 0 then [ Wss(cs, prompt) let entry = GetKeywordOrCR(cs, kt) if entry ne 0 then test FixedProc eq 0 ifso (entry!0)(cs, arg) ifnot FixedProc(cs, entry, arg) Closes(cs) if entry eq 0 & returnOnCR break ] ] repeatuntil TelnetAborting() ] //--------------------------------------------------------------------------- and TelnetCommandQuit(cs, nil) be //--------------------------------------------------------------------------- // This command procedure quits out of the innermost TelnetCommandLoop [ Closes(cs) ReturnFrom(TelnetCommandLoop) IFSError(ecReturnFromReturned) ] //--------------------------------------------------------------------------- and TelnetSubcommandPrompt() = //--------------------------------------------------------------------------- CtxRunning>>TCtx.userInfo>>UserInfo.capabilities ne 0? bangSubPrompt, atSubPrompt; //--------------------------------------------------------------------------- and Plural(number) = number eq 1? singularString, pluralString; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- and TelnetAborting() = CtxRunning>>TCtx.aborting ne 0 //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- and SelectKeyword(cs, key1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil; numargs na) = valof //--------------------------------------------------------------------------- // Takes a list of up to 15 keywords, calls GetKeyword with that list, // and returns the index (1-15) of the one matching the word typed in. // Keyword arguments may be omitted by supplying zero in some argument // positions; this permits keywords to be included conditionally. [ Puts(cs, $*s) let kt = nil if EnableCatch(cs) then [ DestroyKeywordTable(kt); EndCatch(cs) ] kt = CallWithArgVec(CreateKeywordIntegerMap, lv key1, na-1) let which = GetKeyword(cs, kt)!0 DestroyKeywordTable(kt) DisableCatch(cs) resultis which ] //--------------------------------------------------------------------------- and CreateKeywordIntegerMap(key1, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil; numargs na) = valof //--------------------------------------------------------------------------- // Takes a list of up to 15 keywords and returns a keyword table // containing those keywords, each of whose entries is the index (1-15) // of the corresponding keyword in the argument list. // Keyword arguments may be omitted by supplying zero in some argument // positions; this permits keywords to be included conditionally. [ let kt = CreateKeywordTable(na) for i = 1 to na do [ let keyword = (lv key1)!(i-1) if keyword ne 0 then InsertKeyword(kt, keyword)!0 = i ] resultis kt ] //--------------------------------------------------------------------------- and TelnetConfirm(string; numargs na) = valof //--------------------------------------------------------------------------- // Requests an isolated confirmation, i.e., one not in the context of // an existing command line. [ let result = false let ccs = InitCmd(50, 1) if ccs ne 0 then [ result = Confirm(ccs, na gr 0 & string) Closes(ccs) ] resultis result ]