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에서 이를 수행하는 방법은 다음과 같습니다 truss.strace

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

여기서 큰 장점은 strace다양한 매개변수를 시스템 호출로 디코딩해 준다는 것입니다.

위의 어느 것도 프로그램에서 문제가 발생할 수 있는 위치를 논리적으로 알려주지 않으며, 디버거 또는 DLL 삽입이라는 두 가지 옵션이 있습니다.

쉽게 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;
}

주석에 지시된 대로 컴파일하고 호출하십시오. 이 코드는 실제 libc tcsetattr()함수를 찾고 대체 버전을 포함합니다. 이 코드는 backtrace()FD 0에서 잠재적으로 흥미로운 활동을 발견한 다음 실제 libc 버전을 호출할 때 호출됩니다. 약간의 조정이 필요할 수 있습니다.

관련 정보