NB. jtelnet class
NB. tn=:conew'jtelnet'    - create new jtelnet
NB. destory__tn''         - destroy object and free resources
NB. logon__tn'host user password pause'
NB.                       - host can be name or IP address nnn.nnn.nnn.nnn
NB.                       - pause is normally 0, but may need to be 1 or 2
NB.                       - seconds for reliable login on some systems
NB. run__tn sentence      - run sentence and return result
NB. start__tn sentence    - start sentence
NB. log__tn               - log of all output and input

0 : 0 NB. input lines for a sample session
require'jtelnet'
tn=.conew'jtelnet'
logon__tn'host user password pause'
run__tn'ls'
log__tn
destroy__j''
)

require'socket'
coclass'jtelnet'
coextend'jsocket'

TELNETPORT=:23
'WILL WONT DO DONT IAC'=:a.{~251+i.5
sk=:INV=:'x'
mtm=: i.0 0
error=: 3 : 'y. 13!:8[3'

create=: 3 : 'mtm'
destroy=: 3 : 0
if. sk~:INV do. sdclose sk end.
codestroy''
)

NB. return 1 if new data added to log
NB. return 0 if no new data within y. (default 3) seconds
NB. replies to option negotiation DO with WONT
NB. replies to option negotiation WILL with DO
get=: 3 : 0
int=. 1000 * {. y.,3
if. -.sk e.>1{sdselect sk;'';'';int do. 0 return. end.
d=.,>sdcheck sdrecv sk,5000,0
if. 0=#d do. error'disconnected' end.
b=.+/0 _1 _2|."0 1(3,#b)$b=.d=IAC
c=.b#d     NB. option negotiations IAC,cmd,option
d=. toJ (-.b)#d NB. plain text
if. #c do.
 log=:log,'recv: ',(showoptions c),LF
 c=. WONT ((c=DO)#i.#c)} c
 c=. DO ((c=WILL)#i.#c)} c
 send c
  log=:log,'send: ',(showoptions c),LF
end.
log=:log,d
1
)

send=: 3 : '(toHOST y.) sdsend sk,0'

NB. y. address;user;password
NB. address can be name or nnn.nnn.nnn.nnn
logon=: 3 : 0
'ip user pswd pause'=.;:y. NB. IP address is a J word
pause=.".pause
log=:''
NB. convert name to x.x.x.x
if. -.*./ip e. '.0123456789' do.ip=.>2{sdgethostbyname_jsocket_ ip end.
sk=:>0{sdcheck sdsocket''
sdcheck sdconnect sk;AF_INET;ip;TELNETPORT
while. get'' do.
 t=.(1+log i: LF)}.log NB. last line
 if. 'login:'-:6{.t do.
  if. user-:'' do. error'login failed' end.
  6!:3[pause NB. some systems require a few seconds for reliable login
  send user,LF
  user=.'' NB. only try once
 elseif. 'password:' -: tolower 9{.t do. send pswd,LF
 elseif. detectprompt'' do. break.
 end.
end.
mtm
)

NB. run command on telent server and return result
run=: 3 : 0
i=.#log
send y.,LF
while. get'' do.
 if. detectprompt'' do. break. end.
end.
t=.i}.log
NB. (2+t i.CR)}.(t i: CR){.t
(1+t i.LF)}.(t i: LF){.t
)

NB. run command on telent server and return
start=: 3 : 'send y.,LF'

NB. return 1 if log ends with prompt
NB. test first 3 and last 3 chars of last line
detectprompt=: 3 : 0
(LF,'[]$ ')-:,3 _3{."0 1(log i: LF)}.log
)

NB. format option negotiations
showoptions=: 3 : 0
n=.":each<"0 i.256
n=. 5{.each('echo';'sga';'sb';'will';'wont';'do';'dont';'iac') (1 3,250+i.6)}n
d=.(y.~:IAC)#y.
;(a.i.d){n
)
