이번에는 80년대에 Bob Ankeney가 유닉스 시스템을 위해 작성했고, 1992년에 Mike Yang이 고쳤으며, 지금은 Jonathan Badger가 관리하고 있는 고색창연한 옛 게임인 Hearts다. 그 선조는 Oregon 소프트웨어의 Don Backus가 쓴 훨씬 더 오래된 파스칼 프로그램으로 나중에 Jeff Hemmerling이 개정했다. 원래는 다중 사용자 클라이언트를 염두에 둔 것이지만, 컴퓨터를 상대로 한 단일 사용자 모드도 가능하다. 세련된 면이 부족하고 컴퓨터 상대가 별로 강하지 않지만, 그래픽은 훌륭하다. 유닉스와 리눅스에서 가능한 것은 지금으로서도 친절한 Hearts 게임 밖에는 없는 듯 하다.
그 나이와 혈통 때문에, 이 패키지는 특히 리눅스 시스템에 설치하기 어렵다. 설치를 위해서는 길고 골치아픈 일련의 퍼즐을 풀어야 한다. 이 과정은 인내와 결의의 훈련이라 할 수 있다.
시작하기 전에, motif
나 lesstif
라이브러리가
설치되어 있는지 확인하도록 하라.
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 데이터베이스 보다는 terminfo나 termcap을 사용한다.
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는
선사이트에서 구할 수 있다.