stty設定が変更された場合は、ユーザーに監視して警告しますか?

stty設定が変更された場合は、ユーザーに監視して警告しますか?

特に大きな(〜10 ^ 6 LOC)プログラムのために私のstty設定がからに変更されましたecho ixon icanon-echo -ixon -icanon

私は明らかにこの混乱のOOPスパゲッティコードを介して実行を追跡したくありません。

stty設定を監視し、変更を記録する方法は?strace私は必要な情報を提供できると思いますawkが、どのシステムコールをフィルタリングするのかわかりません。

答え1

特定のタスクや対話によってイベントが発生する可能性があると思う場合、最も簡単な方法は次のとおりです。

 watch -d -n1 "stty -F /dev/pts/106 -a | grep -Eo '.(icanon|ixon)'"

新しい端末で実行してください。オプションは-Fプログラムを実行する端末です(tty実行する前に実行してプログラムが何であるかを確認してください)。| grep ..端末の状態全体を観察するには、省略してください。

Linuxを使用している場合、次のオプションは次のものを使用することです。ltraceライブラリ呼び出しのトレースは似ていますがstrace(一部の機能を含むstrace)、カーネルシステム呼び出しだけでなくユーザー空間ライブラリでも機能します。

ltrace -tt -e tcgetattr+tcsetattr myprogram ...

tcgetattr()これにより、ターミナル属性を取得して設定するためのlibc関数と関数のタイムスタンプ呼び出しが表示され、追加されます。tcsetattr()

ioctl()最終的に、これらのlibc呼び出しは、またはを使用して追跡できるシステム呼び出しを使用します。straceLinuxでこれを行う方法は次のとおりですtrussstrace

strace -tt -e trace=ioctl myprogram [...]

ここで大きな利点は、straceさまざまなパラメータをシステムコールにデコードすることです。

上記のいずれも、プログラムで問題が発生する可能性がある場所を論理的に知らせず、デバッガまたはDLLの挿入という2つのオプションがあります。

簡単にgdbブレークポイントを設定しtcsetattr()てから呼び出しスタックを調べることができますが、呼び出しが多い場合は面倒です。libcのビルドまたはシンボルのデバッグ最良の結果を得るために)。

最も包括的なオプション(ターゲットプログラムが動的にリンクされていると仮定)は、追跡する必要がある機能を傍受またはラップする独自のDLLを挿入することですtcsetattr()

#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>
#include <termios.h>

/* 
 * gcc -nostartfiles -shared -ldl -Wl,-soname,tcsetattr -o tc.so wraptc.c
 * LD_PRELOAD=./tc.so stty -icanon ixon
 *
 */

#define DEBUG 1
#define dfprintf(fmt, ...) \
    do { if (DEBUG) fprintf(stderr, "[%14s#%04d:%8s()] " fmt, \
          __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)


typedef int tcsetattr_fp(int fd, int optional_actions, 
                     const struct termios *termios_p);
static tcsetattr_fp    *real_tcsetattr;

void _init()
{
    dfprintf("It's alive!\n","");
    real_tcsetattr = dlsym(RTLD_NEXT, "tcsetattr");
    dfprintf("Hooked %p tcsetattr()\n",(void *)real_tcsetattr);
}

int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
{
     void *bt[20];
     size_t btsz;

     int rc,stacktr=0;
     dfprintf("Caught tcsetattr(%i,%04x,...)\n",fd,optional_actions);

     if ( (fd==0) && !((termios_p->c_lflag) & ICANON)) {
         dfprintf("ICANON off!\n","");
         stacktr=1;
     }
     if ( (fd==0) && !((termios_p->c_iflag) & IXON)) {
         dfprintf("IXON off!\n","");
         stacktr=1;
     }
     if (stacktr) {
         btsz=backtrace(bt,sizeof(bt));
         backtrace_symbols_fd(bt,btsz,STDERR_FILENO);
     }

     rc=real_tcsetattr(fd,optional_actions, termios_p);
     return rc;
}

コメントの指示に従ってコンパイルして呼び出します。このコードは実際のlibctcsetattr()関数を探し、代替バージョンを含みます。このコードは、backtrace()FD 0で潜在的に興味深いアクティビティを見つけて、実際のlibcバージョンを呼び出すと呼び出されます。若干の調整が必要な場合があります。

関連情報