LinuxやFreeBSDへtelnetプロトコルでloginできたところで、manでマニュアルを見てみよう
[pepo1@~]$ man ls
LS(1) User Commands LS(1)
NAME
ls - list directory contents
SYNOPSIS
ls [OPTION]... [FILE]...
DESCRIPTION
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort.
Mandatory arguments to long options are mandatory for short options
too.
-a, --all
do not ignore entries starting with .
: ←カーソルがこの位置に表示してしまう・・正解は画面の最下段に表示
do not list implied . and ..
--author
with -l, print the author of each file
中略
直ぐに分かる事なのだが、↓↑でmanualの前後の表示をさせようとするが、まともに表示ない
理由は現在の端末の画面サイズがtelnetサーバ側へ伝わっていないからだ
と言うことで、以下のシーケンスのようにサーバへWill Negotiate About Window Sizeを送信、応答を待って現在の端末Window Sizeを取得しサーバへ送出するようにします
クライアント→サーバ
Command: Will Negotiate About Window Size
サーバ→クライアント
Command: Do Negotiate About Window Size
クライアント→サーバ
Suboption Begin: Negotiate About Window Size
Command: Suboption End
実際の処理は以下ように
zmodem_check() { /* zmodem check & telnet option */
int chh;
chh = ch & 0377;
ch3 = chh;
if ( iac_step_flag != 0 ) {
if ( iac_step_flag == 1 ) {
dont_flag = do_flag = will_flag = 0;
iac_step_flag++;
switch(chh) {
case DONT:
dont_flag = 1;
break;
case WILL:
will_flag = 1;
break;
case DO:
do_flag = 1;
break;
case SB:
sb_flag = 1;
break;
}
return;
}
if ( iac_step_flag == 2 ) {
iac_step_flag = 0;
display_flag = 1;
switch(chh) {
case TELOPT_ECHO:
if (dont_flag == 1) display_flag = 0;
if (do_flag == 1) {
display_flag = 1;
send_wont_char(ch3);
}
if (will_flag == 1) {
display_flag = 1;
}
break;
case TELOPT_ENCRYPT:
if (do_flag == 1) send_wont_char(ch3);
if (will_flag == 1) send_dont_char(ch3);
break;
case TELOPT_AUTHENTICATION:
if (do_flag == 1) send_wont_char(ch3);
if (will_flag == 1) send_dont_char(ch3);
break;
case TELOPT_STATUS:
if (will_flag == 1 || do_flag == 1) send_wont_char(ch3);
if (dont_flag == 1) send_dont_char(ch3);
break;
case TELOPT_NAWS:
if (send_window_flag == 1 && do_flag == 1) {
send_window_size();
}
break;
case TELOPT_TTYPE:
if (send_ttype_flag == 1 && sb_flag == 1) {
send_ttype();
}
break;
default:
if (will_flag == 1) send_dont_char(ch3);
if (do_flag == 1) send_wont_char(ch3);
if (send_window_flag == 0) {
send_will_window();
send_window_flag = 1;
send_will_ttype();
send_ttype_flag = 1;
}
break;
}
return;
}
}
send_will_window() {
sprintf(f3,"%c%c%c",IAC,WILL,TELOPT_NAWS);
write(fp2,&f3,strlen(f3));
return;
}
現在の端末ウィンドサイズを取得してサーバへ送信
send_window_size() {
int dummy = 0;
// setupterm(MY_TTYPE, fileno(stdout), (int *) 0);
setupterm(NULL, fileno(stdout), (int *) 0);
my_height = tigetnum("lines");
my_width = tigetnum("cols");
sprintf(f3,"%c%c%c%c%c%c%c%c%c",IAC,SB,TELOPT_NAWS,dummy,my_width,dummy,my_height,IAC,SE);
write(fp2,&f3,9);
return;
}
pepoと