다음 이전 차례

12. 네번째 예: Hearts

이번에는 80년대에 Bob Ankeney가 유닉스 시스템을 위해 작성했고, 1992년에 Mike Yang이 고쳤으며, 지금은 Jonathan Badger가 관리하고 있는 고색창연한 옛 게임인 Hearts다. 그 선조는 Oregon 소프트웨어의 Don Backus가 쓴 훨씬 더 오래된 파스칼 프로그램으로 나중에 Jeff Hemmerling이 개정했다. 원래는 다중 사용자 클라이언트를 염두에 둔 것이지만, 컴퓨터를 상대로 한 단일 사용자 모드도 가능하다. 세련된 면이 부족하고 컴퓨터 상대가 별로 강하지 않지만, 그래픽은 훌륭하다. 유닉스와 리눅스에서 가능한 것은 지금으로서도 친절한 Hearts 게임 밖에는 없는 듯 하다.

그 나이와 혈통 때문에, 이 패키지는 특히 리눅스 시스템에 설치하기 어렵다. 설치를 위해서는 길고 골치아픈 일련의 퍼즐을 풀어야 한다. 이 과정은 인내와 결의의 훈련이라 할 수 있다.

시작하기 전에, motiflesstif 라이브러리가 설치되어 있는지 확인하도록 하라.

xmkmf

make

client.c: In function `read_card':
client.c:430: `_tty' undeclared (first use in this function)
client.c:430: (Each undeclared identifier is reported only once
client.c:430: for each function it appears in.)
client.c: In function `scan':
client.c:685: `_tty' undeclared (first use in this function)
make: *** [client.o] Error 1

client.c에 범인이 있다.

#ifndef SYSV
        (buf[2] != _tty.sg_erase) && (buf[2] != _tty.sg_kill)) {
 #else
        (buf[2] != CERASE) && (buf[2] != CKILL)) {
#endif

client.c의 39째 줄에

#define SYSV
를 더한다. 이렇게 하면 _tty로의 참조를 무시한다.

make

client.c:41: sys/termio.h: No such file or directory
make: *** [client.o] Error 1

리눅스 시스템에서는 termio.h 파일이 /usr/include 에 있다. 더 오래된 유닉스에서는 /usr/include/sys에 있다. 따라서, clinet.c의 41째 줄을

#include <sys/termio.h>
에서
#include <termio.h>
로 바꾼다.

make

gcc -o hearts -g      -L/usr/X11R6/lib client.o hearts.o select.o connect.o
sockio.o start_dist.o  -lcurses -ltermlib       
/usr/bin/ld: cannot open -ltermlib: No such file or directory
collect2: ld returned 1 exit status
make: *** [hearts] Error 1

요즘의 리눅스 배포본은 구식의 termlib 데이터베이스 보다는 terminfotermcap을 사용한다.

Makefile의 655째 줄,

CURSES_LIBRARIES = -lcurses -ltermlib

CURSES_LIBRARIES = -lcurses -ltermcap
로 바꾼다.

make

gcc -o xmhearts -g      -L/usr/X11R6/lib xmclient.o hearts.o select.o
connect.o sockio.o start_dist.o gfx.o  -lXm_s -lXt -lSM -lICE -lXext -lX11
-lPW       
/usr/bin/ld: cannot open -lXm_s: No such file or directory
collect2: ld returned 1 exit status

lesstif의 주 라이브러리는 libXm_s가 아니라 libXm이다. 따라서 Makefile를 고친다.

653째 줄:

XMLIB = -lXm_s $(XTOOLLIB) $(XLIB) -lPW

다음과 같이 한다.

XMLIB = -lXm $(XTOOLLIB) $(XLIB) -lPW

make

gcc -o xmhearts -g      -L/usr/X11R6/lib xmclient.o hearts.o select.o
connect.o sockio.o start_dist.o gfx.o  -lXm -lXt -lSM -lICE -lXext -lX11 -lPW       
/usr/bin/ld: cannot open -lPW: No such file or directory
collect2: ld returned 1 exit status
make: *** [xmhearts] Error 1

늘 하던 의심을 해보자

PW라이브러리가 없다. Makefile를 고친다.

653째 줄,

XMLIB = -lXm $(XTOOLLIB) $(XLIB) -lPW

를 다음과 같이 한다.

XMLIB = -lXm $(XTOOLLIB) $(XLIB) -lPEX5
(The PEX5 lib comes closest to PW.)

make

rm -f xmhearts
gcc -o xmhearts -g      -L/usr/X11R6/lib xmclient.o hearts.o select.o
connect.o sockio.o start_dist.o gfx.o  -lXm -lXt -lSM -lICE -lXext -lX11 -lPEX5       

드디어 make에 성공했다. (만세!)

설치:

root로서 다음과 같이 한다.

[root@localhost hearts]# make install
install -c -s  hearts /usr/X11R6/bin/hearts
install -c -s  xmhearts /usr/X11R6/bin/xmhearts
install -c -s  xawhearts /usr/X11R6/bin/xawhearts
install in . done

시험삼아 돌려보자.

rehash

(우리는 tcsh 쉘을 쓰고 있다.)

xmhearts

localhost:~/% xmhearts
Can't invoke distributor!

heats 패키지의 README 파일에 다음과 같이 적혀 있다.

     heartsd, hearts_dist와 hearts.instr를 local.h에 정의된 HEARTSLIB 디렉터리 
     안에 두고, 이 파일들에 누구나 접근할 수 있도록 하라.

local.h 파일 내용:

/* where the distributor, dealer and instructions live */

#define HEARTSLIB "/usr/local/lib/hearts"

이것은 RTFM의 고전적인 경우다.

root로서 다음과 같이 한다.

cd /usr/local/lib

mkdir hearts

cd !$

설치될 파일들을 이 디렉터리에 복사한다.

cp /home/username/hearts/heartsd .

cp /home/username/hearts/hearts_dist .

cp /home/username/hearts/hearts.instr .

다시 한 번 시험삼아 돌려보자.

xmhearts

한동안 돌아가다가 dealer died! 라는 메시지를 내며 죽는다.

"distributor"와 "dealer"는 하드웨어의 포트들을 조사(scan)한다. 따라서 우리는 이 프로그램들이 root의 권한을 필요로 하는지 의심해야 한다.

root로서 다음과 같이 해보자,

chmod u+s /usr/local/lib/heartsd

chmod u+s /usr/local/lib/hearts_dist

(앞서 이야기했듯이, suid된 바이너리는 보안 상의 허점을 만들 수도 있다는 것에 주의하라.)

xmhearts

드디어 돌아간다!

Hearts선사이트에서 구할 수 있다.


다음 이전 차례