Avanti Indietro Indice

12. Quarto esempio: Hearts

Ecco il vecchio canuto gioco Hearts, scritto per i sistemi UNIX da Bob Ankeney negli anni '80, rivisto nel 1992 da Mike Yang, ed attualmente mantenuto da Jonathan Badger. Il suo predecessore era un ancor più vecchio programma Pascal di Don Backus della Oregon Software, poi aggiornato da Jeff Hemmerling. Originariamente pensato come client per più giocatori, funziona bene anche per un solo giocatore contro avversari gestiti dal computer. La grafica è bella, benché il gioco manchi di caratteristiche più sofisticate e i giocatori computerizzati non siano molto forti. Nonostante tutto, sembra essere il solo Hearts decente disponibile per macchine UNIX e Linux ancora oggi.

A causa della sua stirpe ed età, questo pacchetto è particolarmente difficile da compilare su di un sistema Linux. Richiede la soluzione di una lunga e sconcertante serie di puzzle. È un esercizio di pazienza e determinazione.

Prima di iniziare, accertatevi di avere le librerie motif o le lesstif installate.

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

Questi sono i colpevoli nel file client.c:

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

In client.c, aggiungiamo
#define SYSV
alla linea 39. Ciò bypasserà il riferimento a _tty.

make

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

Il file include termio.h è nella directory /usr/include su di un sistema Linux, invece che nella /usr/include/sys, come era sulle vecchie macchine UNIX. Perciò, cambiamo la linea 41 di client.c da

#include <sys/termio.h>
a
#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

Le moderne distribuzioni Linux usano il database terminfo e/o termcap, piuttosto che l'obsoleto termlib.

Editiamo il Makefile.

Linea 655:

CURSES_LIBRARIES = -lcurses -ltermlib

cambiamola in:

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

La principale libreria lesstif è libXm, piuttosto che libXm_s. Quindi, editiamo il Makefile.

Nella linea 653:

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

cambia in:

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

Raduniamo i soliti sospetti.

Non c'è nessuna libreria PW. Editiamo il Makefile.

Linea 653:

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

cambia in:

XMLIB = -lXm $(XTOOLLIB) $(XLIB) -lPEX5
(La libreria PEX5 è quella più simile alla 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       

Il make finalmente funziona (hurra!)

Installazione:

Come 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

Esecuzione di prova:

rehash

(Stiamo eseguendo la shell tcsh.)

xmhearts

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

Dal file README nel pacchetto hearts:

     Put heartsd, hearts_dist, and hearts.instr in the HEARTSLIB
     directory defined in local.h and make them world-accessible.
(Traducendo: Mettete Heartsd, hearts_dist, e hearts.instr nella directory HEARTSLIB definita in local.h e rendeteli accessibili a chiunque)

Dal file local.h:

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

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

Questo è un classico caso: RTFM (leggete il fottuto manuale).

Come root,

cd /usr/local/lib

mkdir hearts

cd !$

Copiamo i file di distributor in questa directory.

cp /home/username/hearts/heartsd .

cp /home/username/hearts/hearts_dist .

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

Lanciamo un'altra esecuzione di prova.

xmhearts

Qualche volta funziona, ma il più delle volte si pianta con un messaggio dealer died!.

Il "distributor" e il "dealer" esaminano le porte hardware. Dovremmo perciò sospettare che quei programmi abbiano bisogno dei privilegi di root.

Proviamo, come root,

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

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

(Osserviamo che, come discusso precedentemente, i binari suid possono creare dei buchi di sicurezza.)

xmhearts

Alla fine funziona!

Hearts è disponibile da Sunsite.


Avanti Indietro Indice