端末幅の取得

私は端末のケイパビリティで困った時には,とりあえず export TERM=vt100 としてみる.もちろん根本的におかしいことがあるとそのような小細工は役立たないが,端末がGNU Screen経由してるせいで TERMscreen.mlterm とかだと,古い terminfo にエントリが無いときがある.異なるマシンで terminfo のバージョンが違うと... とか言い出すと色々面倒で,とりあえず vt100 というのはそういうときにアドホックに役立ってくれる.
ところが「VT100って80x24の端末だよね? 接続元でターミナル・エミュレータのサイズを変えたときに接続先でVimとか混乱しないの? 端に空白とかできちゃうんじゃないの?」と質問を受けた.まぁ実際試してみればそんなことにはならないと分かるはずだが,じゃあそのメカニズムは? という訳で.
端末サイズは基本的にOSのpseudo TTY (pty) 内で管理されてるようで,ptyドライバに対し ioctl(fd, TIOCGWINSZ, &winSize); を発行すれば取得できる.vt100xterm といった各々の TERM の値に対し ncurses の tgetnum(3) or tigetnum(3) で取得できるのはあくまでもせいぜいフォールバック用途 *1 という感じかな.アプリによっては全く見てない *2
ここから余談: POSIX範囲外だがLinux, BSD, Solarisには SIGWINCH なるシグナルがあって,OS側(ptyドライバ?)からアプリに「今ユーザが端末幅を変えやがったから,今いっぺん ioctl(2) して更新してくんな」と通知されるらしい.それはいいのだが,Apacheはそれをgraceful-stopのためのトリガに濫用してるらしい.ユーザ定義で使いたいシグナルの割り当てが足りないからって,そんなことを.さらにnginxも挙動を合わせたっぽく,本来の意味で飛んできた SIGWINCH で困った人が:

  • id:hiboma:20110627:1309178689 nginxをフォアグラウンドで起動してる時に screenやらターミナルのウィンドウのサイズ変えるとSIGWINCH飛んできて死ぬ => 加筆修正いれました

もう2011年なんだし もうちょっとIPCを近代化してもいいよね... デスクトップ周りで人気のDBusLinux以外にもどんどん移植して行く? とも思ったが,ちょっとモデルがPOSIXシグナルとは別物だね.

*1:例: lv

*2:例: nano