6. 시스템에서 해줘야할 일

시스템을 표준에 맞게 하고자 하는 사람들을 혼란스럽게 만드는 주된 문제는 그들이 종종 잘못된 방식으로 일을 한다는 것임을 상기하자. 정상적으로 작동하는 부분들은 흔히 우연히 그렇게 작동하는 것이기 때문에 어떤 것이 잘못되었다는 가정 하에 시스템을 수정하려 하는 것은 정상적인 설정까지도 틀리게 만들기도 한다.

6.1. 해야할 일

6.1.1. 변종을 찾는다

깔끔한 해결책을 위한 첫 걸음은 어떤 터미날이 변종이고 어떤 것이 아닌지를 정확히 아는 것이다. 흔히 터미날들은 모두 콘솔처럼 작동하며 이런 경우에 매우 적은 양의 수정만으로 모두 정상적으로 작동하도록 할 수 있다. 그러나 변종 터미날 (gnome-terminal의 변종같은) 을 사용한다면 이를 특별한 방법으로 다뤄줘야 한다.

아래의 한 줄짜리 C 프로그램

void main(void) {int c; while(c = getchar()) printf("%d 0x%02X\n", c, c);}
이 도움이 될 수도 있다. 이 프로그램을 ascii.c이라는 이름으로 저장한 후 gcc ascii.c -o ascii 명령으로 컴파일하고 ./ascii로 실행시킨다. 그리곤 아무 키나 누른 후 RETURN을 누른다. 이 프로그램은 발생된 ASCII 문자열의 코드들을 10진수와 16진수 형태로 보여준다 (모든 코드들을 보길 원한다면 우선 stty erase ^- 명령을 실행한다). 이제 Backspace 키가 무슨 일을 하는지를 쉽게 볼 수 있다. 이 키가 DEL(127)을 발생시킨다면 표준 에뮬레이터를 사용하는 것이고 BS(8)을 발생시킨다면 변종 에뮬레이터를 사용하고 있는 것이다.

6.1.2. 에뮬레이터간의 구분

변종 에뮬레이터를 사용한다면 이를 표준의 것과 구분해야 한다. 이론적으론 이것은 문제가 되어서는 안되는데 이는 다른 방식으로 작동하는 터미날들에 대해서는 터미날 데이타베이스의 서로 다른 항목이 적용되기 때문이다 (사용되는 항목은 TERM 변수의 값에 따라 다르다).

여기서는 모든 변종 VT100 에뮬레이터들에는 gnome 항목이, 표준 에뮬레이터들에는 xterm 항목이 적용되도록 하겠다. 이는 일부 배포판들에 잘 적용된다 (예외는 5.0 이하의 RedHat 같은 일부의 경우인데 이런 배포판들에서는 xterm 항목도 변종이다).

그러나 gnome-terminal은 기본적으로 xterm과 동일한 항목을 사용하므로 둘 중 하나는 변종이고 다른 하나는 표준이라면 이를 구분할 방법을 찾아야 한다. 이론적으로는 gnome-terminaltermname 옵션이 사용자에게 TERM 변수를 좀 더 적절한 값으로 설정할 수 있도록 해줘야 하지만 gnome-terminal 1.2.1과 같은 경우에는 이 옵션이 작동하지 않는다.

여기서 사용할 수 있는 괜찮은 방법은 gnome-terminalCOLORTERM 변수를 gnome-terminal로 설정한다는 사실이다. 따라서 쉘 설정 파일에 간단한 검사 항목을 추가함으로써 우리는 TERM 변수값을 수정할 수 있게 된다.

6.1.3. 터미날 데이타베이스의 정정

이제 문제는 터미날 데이타베이스가 변종 터미날들에 사용될 gnome 항목이 없을 수도 있다는 것이다 (이는 많은 termcapterminfo에서 발생한다). 최신의 terminfo 데이타베이스는 gnome 항목을 가지고 있지만 말이다. 그러나 gnome-terminal은 특정한 두 키들만 제외하면 xterm과 기본적으로 동일하게 작동하므로 이 항목을 새로 만드는 것도 가능하다.

6.1.4. 쉘 작동방식 정정

The readline library used by the bash and by many other programs to read the input line can be customized so to recognize specific sequences of characters. The customization can also depend on the TERM variable, so once we can distinguish terminals we can do fine tuning of the keyboard.

bash과 많은 프로그램들이 입력줄을 읽어들이기 위해 사용하는 readline 라이브러리는 특정 문자열을 인식하도록 설정이 가능하다. 이러한 설정 또한 TERM 변수값에 의존하게 되며 따라서 일단 터미날들을 구분할 수 있게 되면 키보드를 보다 정교히 조작하는 것이 가능해진다.

더불어 줄 입력을 직접 처리하는 less나 다른 어플리케이션들 역시 올바르게 작동하게 하려면 변종 터미날 에뮬레이터 하에서 삭제 문자가 DEL이 아닌 BS이라는 것을 쉘에 주지시켜야 한다 (표준의 경우에는 Backspace 키가 이미 DEL을 생성하므로 우리가 직접 해줄 일은 없다). 이는 stty 명령을 사용하면 된다.

6.2. 하는 방법

경고

이 수정사항들은 일부 문제점을 가지고있다. 첫째로, 특정 터미날들에서만 작동한다. 둘때로, 이론적으로는 (그러나 거의 일어나지 않을 것이다) 다른 터미날들에서의 readline 라이브러리의 정상 작동을 힙들게 할 수 있다. 그러나 이런 두 한계점들은 거의 해롭진 않다.

먼저 infocmp gnome 명령으로 현재의 terminfo 데이타베이스 안에 gnome 항목이 있는지를 검사한다 (termcap에 대해서는 나중에 다루겠다). 만약 이 항목이 없다면 아래의 명령으로 ~/.terminfo에 적당한 항목을 만든다.

bash$ tic <(infocmp xterm |\
        sed 's/xterm|/gnome|/' |\
        sed 's/kbs=\\177,/kbs=^H,/' |\
        sed 's/kdch1=\\E\[3~,/kdch1=\\177,/')
똑같은 명령을 root가 실행시키면 시스템 전체의 데이타베이스에 항목을 추가하게 된다 (이는 TERMINFO~/.terminfo으로 설정함으로써 바꿔줄 수 있다). 여러분이 가지고 있는 xterm 항목이 이미 변종이라면 (예를 들어 5.0 이전의 Red Hat의 경우) 이 스크립트는 이를 수정 없이 그대로 복사할 것이고 이것은 정확히 원하던 결과이다.

이제 아래 줄들을 ~/.inputrc [1]에 추가한다:

"\e[3~": delete-char
이 줄은 readline 라이브러리에게 표준 터미날에서 Delete 키를 다루는 표준적인 방식을 알려준다. 그리고 운 좋게도 이것은 다른 터미날들을 간섭하진 않는다. 이와 함께 DEL 문자의 변종 터미날 상에서의 의미에 대해서도 라이브러리에게 알려줘야 하며 다음과 같은 줄을 ~/.inputrc에 추가하여 할 수 있다.

$if term=gnome
DEL: delete-char
$endif
xterm도 변종인 경우엔 추가로 세 줄 정도를 더 넣어줘야 한다. 반면에 변종 터미날이 없다면 이 부분은 필요가 없다. 여기서 다루는 모든 수정사항들은 /etc/inputrc 파일을 직접 수정하면 시스템 전체에 영향을 주게 된다.

조건문에 의해 변종 터미날 에뮬레이터가 TERM 변수가 올바르에 설정되었다는 가정 하에 작동하게 된다는 것을 주목할 필요가 있다. 이를 보장해 주기 위해서 쓸 수 있는 트릭이 몇 개가 있다. 먼저, gnome-terminal에 기본으로 사용되는 TERM의 값이 xterm이기 때문에 모든 터미날이 변종이 아니라면 아무 것도 할 필요가 없다. 그러나 기본으로 xterm 항목을 사용하는 터미날이 변종이라면 우리는 TERM 변수를 올바르게 설정해 주는 방법을 찾아야 한다. gnome-terminal의 경우가 그렇다고 가정하자.

이런 효과를 위한 가장 간단한 방법은 gnome-terminal--termname=gnome 인자를 줘서 실행하는 것이다. 그러나 예전 버전을 가지고 있어서 이 방법이 효과가 없다면 다음 줄들을

if [ "$COLORTERM" = "gnome-terminal" ]
then
    export TERM=gnome
fi
~/.bashrc 설정 파일에 넣어준다[2]. 이 설정문은 gnome-terminal에서만 실행되어서 TERM 변수를 알맞게 설정해준다.

참고: 터미날을 gnome으로 설정하는면 ls에서 색깔을 사용하지 못할 수도 있다. 이는 ls의 많은 버전들이 gnome-terminal에서 색깔 사용이 가능하다는 것을 모르기 때문이다. 이를 방지하기 위해선 dircolors --print-database > ~/.dircolors 명령으로 ~/.dircolors 파일을 만근 후 이 파일에 TERM=gnome 줄을 추가한다.

이제 변종 터미날 에뮬레이터에 알맞은 termcap 항목을 만들 것이다. 아래처럼 하면 되며 이를 ~/.bashrc에 넣어놓아도 된다.

if [ "$TERM" = "gnome" ]
then
    export TERMCAP=$(infocmp -C gnome | grep -v '^#' | \
                    tr '\n\t' '  ' | sed 's/\\  //g' | sed s/::/:/g)
fi

마지막으로 터미날 장치에게 삭제 키에 의해서 어떤 문자가 생성되는지를 알려줘야 한다. 일반적으로 삭제 키는 backspace를 의미하므로 우선은 이처럼 설정한 후에 각각의 변종 터미날에 대한 조건문을 추가할 것이다. 물론 ~/.bashrc 안에 넣게된다.

stty erase ^?

if [ "$TERM" = "gnome" ]
then
    stty erase ^H
fi
여러분이 사용하는 터미날 에뮬레이터가 모두 변종이라면 아무 조건문 없이 삭제 문자를 설정하면 된다.

참고: 어떤 배포판들은 이 문제들을 전체 시스템용 설정파일인 /etc/inputrc 안에서 교정해 놓고 있다. 이런 경우는 여러분의 ~/.inputrc에서 중복되는 줄들을 빼도 된다.

6.3. tcsh용 수정사항

tcsh의 경우에는 모든 수정사항들이 ~/.tcshrc 안에 들어며 bash의 경우와 동일한 작동을 하게 된다.

bindkey "^[[3~" delete-char

if ($?COLORTERM) then
   if ($COLORTERM == "gnome-terminal") then
      setenv TERM gnome
   endif
endif

stty erase ^?

if ($?TERM) then
   if ($TERM == "gnome") then
      setenv TERMCAP \
       "`infocmp -C gnome | grep -v '^#' | tr '\n\t' '  ' | sed 's/\\  //g' | sed s/::/:/g`"
      bindkey "\177" delete-char
      stty erase ^H
   endif
endif
두 번째 부분은 모든 변종 터미날에 대해서 똑같이 복사되어야 한다. 물론 termcap 항목이 이미 있다면 새로 만들 필요가 없다.

주석

[1]

이전 버전의 bash에서는 INPUTRC를 알맞게 설정해 주는 것을 잊어선 안된다. 예를 들어

export INPUTRC=~/.inputrc
~/.profile (혹은 로긴 쉘이 읽어들이는 여타 다른 파일) 안에 넣어준다.

[2]

더 정확히 말해서 모든 로긴 쉘 뿐 아니라 모든 쉘이 읽어들이는 설정 파일이다.