This commit is contained in:
commit
781ed9aaf0
9 changed files with 1310 additions and 0 deletions
58
Makefile
Normal file
58
Makefile
Normal file
|
@ -0,0 +1,58 @@
|
|||
all:
|
||||
@echo "Usage: make <commande>"
|
||||
@echo ""
|
||||
@echo "Commandes disponibles:"
|
||||
@echo "- worm_inc : version modifiée des programmes, avec insertion de detect_init()"
|
||||
@echo " et bibliothèque de détection de pannes liée statiquement"
|
||||
@echo "- worm_shared : version modifiée des programmes, avec insertion de detect_init()"
|
||||
@echo " et bibliothèque de détection de pannes liée dynamiquement"
|
||||
@echo "- worm_preload: version non modifiée des programmes, avec préchargement de la "
|
||||
@echo " bibliothèque de détection de pannes, et execution de celle-ci."
|
||||
|
||||
worm_inc: clean server
|
||||
gcc -ggdb -o worms_mod libdetect.c worms_mod.c -lcurses -lrt -lpthread -Wall
|
||||
gcc -ggdb -o test_mod libdetect.c test_mod.c -lrt -lpthread -Wall
|
||||
@echo -e "\n* Pour executer, taper: "
|
||||
@echo -e "*\n* ./worms_mod"
|
||||
@echo -e "*\n* ou "
|
||||
@echo -e "*\n* ./test_mod\n*"
|
||||
|
||||
worm_shared: clean server
|
||||
gcc -fPIC -Wall -ggdb -c libdetect.c
|
||||
gcc -g -shared -Wl,-soname,libdetect.so.0 \
|
||||
-o libdetect.so.0.0 libdetect.o -lc
|
||||
/sbin/ldconfig -n .
|
||||
ln -sf libdetect.so.0 libdetect.so
|
||||
gcc -Wall -ggdb -o test_shr test_mod.c -L. -lrt -lpthread -ldetect
|
||||
gcc -Wall -ggdb -o worms_shr worms_mod.c -L. -lcurses -lrt -lpthread -ldetect
|
||||
@echo -e "\n* Pour executer, taper: "
|
||||
@echo -e "*\n* LD_LIBRARY_PATH="." ./worms_shr"
|
||||
@echo -e "*\n* ou "
|
||||
@echo -e "*\n* LD_LIBRARY_PATH="." ./test_shr\n*"
|
||||
|
||||
# run with:
|
||||
# LD_LIBRARY_PATH="." ./command
|
||||
|
||||
|
||||
worm_preload: clean server
|
||||
gcc -fPIC -Wall -ggdb -c libdetect.c -D_GYR_PRELOAD
|
||||
gcc -g -shared -Wl,-soname,libdetect.so.0 \
|
||||
-o libdetect.so.0.0 libdetect.o -lc
|
||||
/sbin/ldconfig -n .
|
||||
ln -sf libdetect.so.0 libdetect.so
|
||||
gcc -ggdb -o worms worms.c -lcurses -lrt -lpthread -Wall
|
||||
gcc -ggdb -o test test.c -lrt -lpthread -Wall
|
||||
@echo -e "\n* Pour executer, taper: "
|
||||
@echo -e "*\n* LD_LIBRARY_PATH="." LD_PRELOAD=libdetect.so ./worms"
|
||||
@echo -e "*\n* ou "
|
||||
@echo -e "*\n* LD_LIBRARY_PATH="." LD_PRELOAD=libdetect.so ./test\n*"
|
||||
|
||||
server:
|
||||
gcc -ggdb -o detector-server detector-server.c -Wall
|
||||
|
||||
clean:
|
||||
rm -f *.so*
|
||||
rm -f *.o
|
||||
rm -f detector-server
|
||||
rm -f test test_mod test_shr
|
||||
rm -f worms worms_mod worms_shr
|
35
README
Normal file
35
README
Normal file
|
@ -0,0 +1,35 @@
|
|||
|
||||
Prérequis: L'utilisation de ce projet nécessite un système GNU/Linux, et la
|
||||
présence du compilateur GNU GCC
|
||||
|
||||
|
||||
|
||||
make <commande>
|
||||
|
||||
* Détecteur de pannes, invoqué depuis main
|
||||
|
||||
Taper:
|
||||
|
||||
make worm_inc
|
||||
|
||||
et suivre les instructions.
|
||||
|
||||
|
||||
* Détecteur de pannes, invoqué depuis main et compilé
|
||||
dans une bibliothèque chargée dynamiquement
|
||||
|
||||
Taper:
|
||||
|
||||
make worm_shared
|
||||
|
||||
et suivre les instructions.
|
||||
|
||||
* Détecteur de pannes, dans une bibliothèque chargée
|
||||
dynamiquement, mais sans toucher au code source du programme original.
|
||||
|
||||
Taper:
|
||||
|
||||
make worm_preload
|
||||
|
||||
et suivre les instructions.
|
||||
|
348
detector-server.c
Normal file
348
detector-server.c
Normal file
|
@ -0,0 +1,348 @@
|
|||
#include <pthread.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define LINK_CELL_NAME_SIZE 100
|
||||
|
||||
#define KEEP_SOCK_MAX(x, y) if (x < ((y) +1)){ x = (y) + 1; }
|
||||
|
||||
#define FOREACH_SOCKET_IN_SOCKBASKET(i, sockbasket, link) for (i = 0; \
|
||||
((i < sockbasket->size) \
|
||||
&& (link_basket_get(sockbasket, i, &link)) \
|
||||
); \
|
||||
i++) \
|
||||
if (link != NULL)
|
||||
|
||||
#define SELECT_TIMEOUT 100000;
|
||||
#define REQUEST_INTERVAL 5
|
||||
#define REQUEST_TIMEOUT 30
|
||||
|
||||
#define MIN(x, y) (((x) < (y))?(x):(y))
|
||||
|
||||
#define bool short
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
typedef struct {
|
||||
int sock_desc;
|
||||
bool is_dead;
|
||||
bool is_alive;
|
||||
bool is_registered;
|
||||
time_t request_stamp;
|
||||
time_t answer_stamp;
|
||||
char * name;
|
||||
} link_cell_t;
|
||||
|
||||
typedef struct {
|
||||
link_cell_t ** data;
|
||||
int size;
|
||||
int next;
|
||||
} link_basket_t;
|
||||
|
||||
void show_progress(){
|
||||
static int prog = 0;
|
||||
prog = prog % 100;
|
||||
printf("[");
|
||||
if (prog < 25){
|
||||
printf("|");
|
||||
} else if (prog < 50) {
|
||||
printf("/");
|
||||
} else if (prog < 75) {
|
||||
printf("-");
|
||||
} else {
|
||||
printf("\\");
|
||||
}
|
||||
printf("] ");
|
||||
prog += 25;
|
||||
}
|
||||
bool link_basket_get (link_basket_t *sb, int index, link_cell_t ** res){
|
||||
bool result;
|
||||
if (index < sb->size){
|
||||
*res = sb->data[ index ];
|
||||
/*
|
||||
if (*res != NULL){
|
||||
printf ("Get at %d == %d\n", index, (*res)->sock_desc);
|
||||
} */
|
||||
result = 1;
|
||||
} else {
|
||||
*res = NULL;
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void link_basket_delete (link_basket_t * sb){
|
||||
free (sb->data);
|
||||
free (sb);
|
||||
}
|
||||
|
||||
void link_basket_remove (link_basket_t * sb, int index){
|
||||
link_cell_t * result = sb->data[ index ];
|
||||
if (sb->data[ index ]){
|
||||
free(result->name);
|
||||
free (result);
|
||||
}
|
||||
sb->data[ index ] = NULL;
|
||||
if (index < sb->next){
|
||||
sb->next = index;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void link_basket_add (link_basket_t * sb, int sockfd){
|
||||
int i;
|
||||
|
||||
assert (sb->next != -1); // basket overflow !
|
||||
|
||||
link_cell_t * cell = (link_cell_t *) malloc (sizeof (link_cell_t));
|
||||
|
||||
cell->sock_desc = sockfd;
|
||||
cell->is_dead = false;
|
||||
cell->is_alive = true;
|
||||
cell->is_registered = false;
|
||||
cell->request_stamp = time(NULL);
|
||||
cell->answer_stamp = time(NULL);
|
||||
cell->name = (char *) malloc (sizeof (char) * LINK_CELL_NAME_SIZE);
|
||||
memset(cell->name, 0, LINK_CELL_NAME_SIZE);
|
||||
|
||||
sb->data[ sb->next ] = cell;
|
||||
|
||||
for (i = sb->next; i < sb->size; i++){
|
||||
if (sb->data[ i ] == NULL){
|
||||
sb->next = i;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
link_basket_t * link_basket_create (int size){
|
||||
link_basket_t * result =
|
||||
(link_basket_t *) malloc (sizeof (link_basket_t));
|
||||
result->size = size;
|
||||
result->data = (link_cell_t **) malloc (sizeof (link_cell_t *) * size);
|
||||
result->next = 0;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < result->size; i++){
|
||||
result->data[i] = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main (){
|
||||
link_basket_t * basket = link_basket_create(10);
|
||||
|
||||
int main_sock ;
|
||||
int port;
|
||||
char * hostname;
|
||||
char * portstr;
|
||||
struct hostent * server;
|
||||
struct sockaddr_in * myaddr;
|
||||
|
||||
main_sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (main_sock < 0){
|
||||
perror ("Creation de la socket impossible");
|
||||
fprintf (stderr,"BOOM at %s:%d\n",__FILE__,__LINE__);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
hostname = getenv ("DETECTOR_HOSTNAME");
|
||||
portstr = getenv ("DETECTOR_PORT");
|
||||
if ((NULL == hostname) || (NULL == portstr)){
|
||||
printf("Environment variables DETECTOR_PORT and DETECTOR_HOSTNAME should have been defined.\n");
|
||||
exit(-1);
|
||||
}
|
||||
sscanf (portstr, "%d", &port);
|
||||
|
||||
|
||||
printf ("Lookup for %s...\n", hostname);
|
||||
server = gethostbyname(hostname);
|
||||
if (server == NULL){
|
||||
fprintf (stderr, "Error, no such host\n");
|
||||
exit (-1);
|
||||
}
|
||||
printf ("Host found\n");
|
||||
|
||||
|
||||
myaddr =
|
||||
(struct sockaddr_in *) malloc (sizeof(struct sockaddr_in));
|
||||
bzero (myaddr, sizeof(struct sockaddr_in));
|
||||
myaddr->sin_family = AF_INET;
|
||||
myaddr->sin_port = htons(port);
|
||||
|
||||
memcpy (&(myaddr->sin_addr.s_addr), server->h_addr, sizeof(u_long));
|
||||
//myaddr->sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
// on bind sur le port voulu...
|
||||
if (bind(main_sock, (struct sockaddr *)myaddr, sizeof(struct sockaddr)) < 0){
|
||||
perror("Unable to bind");
|
||||
fprintf(stderr,"Cannot bind on port %d of %s\n",port, inet_ntoa(myaddr->sin_addr));
|
||||
exit(-1);
|
||||
} else {
|
||||
printf("Bind on port %d of %s\n",port, inet_ntoa(myaddr->sin_addr));
|
||||
}
|
||||
|
||||
// on fait un listen
|
||||
if (listen(main_sock, 10) < 0){
|
||||
perror("Unable to listen");
|
||||
exit(-1);
|
||||
} else {
|
||||
printf("Ready to accept connexions.\n");
|
||||
}
|
||||
|
||||
fd_set sock_set;
|
||||
struct timeval tv;
|
||||
int sock_set_size = 0;
|
||||
|
||||
FD_ZERO(&sock_set);
|
||||
FD_SET(main_sock, &sock_set);
|
||||
sock_set_size++;
|
||||
|
||||
|
||||
while(1){
|
||||
printf("\r");
|
||||
show_progress();
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = SELECT_TIMEOUT;
|
||||
//
|
||||
// si on recoit qqchose sur la socket principale, on fait un accept
|
||||
// et on ajoute la nouvelle socket au set
|
||||
link_cell_t * link;
|
||||
int i;
|
||||
|
||||
fd_set read_set;//= sock_set;
|
||||
FD_ZERO(&read_set);
|
||||
FD_SET(main_sock, &read_set);
|
||||
KEEP_SOCK_MAX(sock_set_size, main_sock);
|
||||
|
||||
|
||||
// on ajoute tous les socket ouverts au read_set
|
||||
FOREACH_SOCKET_IN_SOCKBASKET (i, basket, link) {
|
||||
time_t curtime = time(NULL);
|
||||
bool must_add = false;
|
||||
if (link->is_registered){
|
||||
if (link->is_alive){
|
||||
// si le programme est en vie
|
||||
if (difftime(curtime, link->answer_stamp) > REQUEST_INTERVAL){
|
||||
// si le temps nécessaire est écoulé depuis la derniere réponse
|
||||
printf ("\nRequesting liveness for '%s'\n", link->name);
|
||||
|
||||
send(link->sock_desc,"status?", 7, 0);
|
||||
link->request_stamp = curtime;
|
||||
link->is_alive = false;
|
||||
must_add = true;
|
||||
} else {
|
||||
// sinon on attend le temps nécessaire avant de douter...
|
||||
// printf ("On attend que le temps s'écoule pour '%s'\n", link->name);
|
||||
}
|
||||
} else {
|
||||
// sinon
|
||||
if (difftime(curtime, link->request_stamp) > REQUEST_TIMEOUT){
|
||||
// ou on le tue...
|
||||
// FIXME: retirer de la corbeille a liens...
|
||||
printf ("\nTimeout: closing connection of '%s'\n", link->name);
|
||||
close(link->sock_desc);
|
||||
link_basket_remove(basket, i);
|
||||
} else {
|
||||
// on est toujours dans les temps de réponse...
|
||||
//printf ("\nWaiting for '%s'\n", link->name);
|
||||
must_add = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
must_add = true;
|
||||
}
|
||||
|
||||
if (must_add){
|
||||
//printf ("Adding '%s' (%d) to the set\n", link->name, link->sock_desc);
|
||||
FD_SET (link->sock_desc, &read_set);
|
||||
KEEP_SOCK_MAX (sock_set_size, link->sock_desc);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Select..."); fflush(stdout);
|
||||
select(sock_set_size, &read_set, NULL, NULL, &tv);
|
||||
printf("done"); fflush(stdout);
|
||||
|
||||
FOREACH_SOCKET_IN_SOCKBASKET(i, basket, link) {
|
||||
time_t curtime = time(NULL);
|
||||
|
||||
if (FD_ISSET(link->sock_desc, &read_set)){
|
||||
// on lit les données recues, et sinon on ferme la socket.
|
||||
// on vérifie qu'elle sont égales à ...
|
||||
int buffer_len = 1024;
|
||||
char * buffer = (char *) malloc (sizeof(char) * buffer_len);
|
||||
int recv_len;
|
||||
recv_len = recv(link->sock_desc, buffer, buffer_len, 0);
|
||||
|
||||
if (recv_len == 0){
|
||||
printf("\nClient '%s' has disconnected !\n", link->name);
|
||||
link_basket_remove(basket, i);
|
||||
} else {
|
||||
if ((recv_len >= 9) && (!strncmp("register:", buffer, 9))) {
|
||||
buffer[MIN(recv_len, buffer_len - 1)] = '\0';
|
||||
|
||||
int i=0;
|
||||
while(i < buffer_len -1){
|
||||
if ((buffer[i] == 0xD) || (buffer[i] == 0xA)) { buffer[i] = '\0'; }
|
||||
i++;
|
||||
}
|
||||
strncpy(link->name, buffer + 9, MIN(recv_len - 9, LINK_CELL_NAME_SIZE));
|
||||
printf("\nRegistering client : %s\n", link->name);
|
||||
link->is_registered = true;
|
||||
link->answer_stamp = curtime;
|
||||
|
||||
} else if ((recv_len >= 6) && (!strncmp("alive!", buffer, 6))) {
|
||||
//printf("Process on fd %d is alive !\n", link->sock_desc);
|
||||
link->is_alive = true;
|
||||
link->answer_stamp = curtime;
|
||||
|
||||
} else {
|
||||
buffer[99] = '\0';
|
||||
printf("\nUnknow message %s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// printf("Rien sur %d\n", link->sock_desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(main_sock, &read_set)){
|
||||
unsigned int sin_size = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in their_addr; /* Adresse du connecté */
|
||||
int sockfd;
|
||||
|
||||
sockfd = accept(main_sock, (struct sockaddr *)&their_addr,
|
||||
&sin_size);
|
||||
link_basket_add(basket, sockfd);
|
||||
printf("\nGot new connection at %d\n", sockfd);
|
||||
};
|
||||
|
||||
|
||||
// lors d'un accept, on ajoute au tableau des entrées
|
||||
// possibles l'hote qui se connecte
|
||||
|
||||
// regarder les entrées...
|
||||
// faire un select dessus
|
||||
// garde des timer pour chaque entrée
|
||||
// lorsque le temps D est écoule pour un timer
|
||||
// on envoie un paquet "WIEGEHTS" a la machine
|
||||
// et on attend une réponse en moins de 60 sec;
|
||||
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
130
libdetect.c
Normal file
130
libdetect.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _GYR_PRELOAD
|
||||
void __attribute__ ((constructor)) detector_init(void);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char * hostname;
|
||||
int port;
|
||||
} detector_serv_t;
|
||||
|
||||
void * detector_thread_fun(void * paramvoid){
|
||||
detector_serv_t * param = paramvoid;
|
||||
|
||||
printf("Thread launched\n");
|
||||
// se connecter
|
||||
int socket_desc = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (socket_desc < 0){
|
||||
perror("Creation de la socket impossible");
|
||||
fprintf(stderr,"BOUM at %s:%d\n",__FILE__,__LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("Lookup for %s...\n", param->hostname);
|
||||
struct hostent * server = gethostbyname(param->hostname);
|
||||
if (server == NULL){
|
||||
fprintf(stderr, "Error, no such host\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("Host found\n");
|
||||
|
||||
struct sockaddr_in * myaddr =
|
||||
(struct sockaddr_in *) malloc (sizeof(struct sockaddr_in));
|
||||
bzero(myaddr, sizeof(struct sockaddr_in));
|
||||
myaddr->sin_family = AF_INET;
|
||||
myaddr->sin_port = htons(param->port);
|
||||
|
||||
memcpy (&(myaddr->sin_addr.s_addr), server->h_addr, sizeof(u_long));
|
||||
// myaddr->sin_addr.s_addr = server->h_addr[0];
|
||||
|
||||
/*
|
||||
bcopy((char *)(server->h_addr),
|
||||
(char *)(myaddr->sin_addr.s_addr),
|
||||
server->h_length);
|
||||
*/
|
||||
|
||||
if (connect(socket_desc,
|
||||
(struct sockaddr *)myaddr,
|
||||
sizeof(struct sockaddr_in)) < 0){
|
||||
perror("Attachement de la socket impossible");
|
||||
fprintf(stderr,"No connect at %s:%d\n",__FILE__,__LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
printf("Thread connected\n");
|
||||
|
||||
char hostname[50];
|
||||
gethostname(hostname, 50);
|
||||
char ident[100];
|
||||
sprintf(ident, "%d@%s", getpid(), hostname);
|
||||
|
||||
char * message = (char *) malloc (sizeof(char) * 1024);
|
||||
memset(message, 0, 1024);
|
||||
sprintf(message, "register:%s\n", ident);
|
||||
|
||||
write(socket_desc, message, strlen(message));
|
||||
|
||||
// indiquer au serveur qu'il faut qu'il vérifie ce prog
|
||||
// identifant pid
|
||||
while(1){
|
||||
// on attend "status?", on répond "alive!"
|
||||
int recv_len;
|
||||
memset(message, 0, 1024);
|
||||
recv_len = recv (socket_desc, message, 1024, 0);
|
||||
|
||||
if (!strncmp("status?", message, 7)){
|
||||
send (socket_desc, "alive!", 6, 0);
|
||||
}
|
||||
|
||||
}
|
||||
// se déconnecter ?
|
||||
|
||||
}
|
||||
|
||||
void detector_init(){
|
||||
// créer un thread "a part" qui répond au serveur
|
||||
// et retourner dans le programme principal
|
||||
pthread_t thr_detector;
|
||||
pthread_attr_t thr_att;
|
||||
|
||||
pthread_attr_init(&thr_att);
|
||||
|
||||
detector_serv_t * param = (detector_serv_t *)
|
||||
malloc (sizeof(detector_serv_t));
|
||||
// FIXME: read environment variable
|
||||
param->hostname = getenv("DETECTOR_HOSTNAME");
|
||||
if (param->hostname == NULL){
|
||||
fprintf(stderr,"Undefined envirnoment variable DETECTOR_HOSTNAME\n");
|
||||
}
|
||||
|
||||
//FIXME: read env variable
|
||||
char * portstr = getenv("DETECTOR_PORT");
|
||||
if (portstr == NULL){
|
||||
fprintf(stderr,"Undefined envirnoment variable DETECTOR_HOSTNAME\n");
|
||||
}
|
||||
sscanf(portstr, "%d", &(param->port));
|
||||
printf("HOST (%s) PORT (%d)\n", param->hostname, param->port);
|
||||
|
||||
if (pthread_create (&thr_detector,
|
||||
&thr_att,
|
||||
detector_thread_fun,
|
||||
param))
|
||||
{
|
||||
perror("Impossible de créer le thread\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
11
test.c
Normal file
11
test.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
int main(){
|
||||
while(1){
|
||||
sleep(1);
|
||||
printf("Loooooping \n");
|
||||
}
|
||||
}
|
13
test_mod.c
Normal file
13
test_mod.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void detector_init();
|
||||
|
||||
int main(){
|
||||
detector_init();
|
||||
while(1){
|
||||
sleep(1);
|
||||
printf("Loooooping \n");
|
||||
}
|
||||
}
|
24
tip-macosx.txt
Normal file
24
tip-macosx.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
EXO 3 (pour macosX)
|
||||
-------------------------------------------------------
|
||||
gcc -dynamiclib -std=gnu99 -current-version 1.0
|
||||
-compatibility_version 1.0 -fvisibility=hidden
|
||||
-o (lib)Detect.A.dylib *.c
|
||||
|
||||
#define EXPORT __attribute__((visibility("default"))
|
||||
|
||||
|
||||
EXPORT:
|
||||
void detect_init(){ }
|
||||
|
||||
EXO 4 (pour macosX)
|
||||
-------------------------------------------------------
|
||||
__attribute__((constructor))
|
||||
static void initializer(void)
|
||||
}
|
||||
|
||||
|
||||
EXO 5 (pour macosX)
|
||||
-------------------------------------------------------
|
||||
DYLD_INSERT_LIBRARIES = ./libDetect.A.dylib
|
||||
|
344
worms.c
Normal file
344
worms.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* Copyright (c) 1980, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)worms.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD: /repoman/r/ncvs/src/games/worms/worms.c,v 1.11 2002/02/23 10:35:25 billf Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
*
|
||||
* @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
|
||||
* @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
|
||||
* @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
|
||||
* @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
|
||||
* @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
|
||||
* @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
|
||||
* @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
|
||||
* @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
|
||||
* @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
|
||||
*
|
||||
* Eric P. Scott
|
||||
* Caltech High Energy Physics
|
||||
* October, 1980
|
||||
*
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <curses.h>
|
||||
#include <err.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const struct options {
|
||||
int nopts;
|
||||
int opts[3];
|
||||
}
|
||||
normal[8] = {
|
||||
{ 3, { 7, 0, 1 } },
|
||||
{ 3, { 0, 1, 2 } },
|
||||
{ 3, { 1, 2, 3 } },
|
||||
{ 3, { 2, 3, 4 } },
|
||||
{ 3, { 3, 4, 5 } },
|
||||
{ 3, { 4, 5, 6 } },
|
||||
{ 3, { 5, 6, 7 } },
|
||||
{ 3, { 6, 7, 0 } }
|
||||
}, upper[8] = {
|
||||
{ 1, { 1, 0, 0 } },
|
||||
{ 2, { 1, 2, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 2, { 4, 5, 0 } },
|
||||
{ 1, { 5, 0, 0 } },
|
||||
{ 2, { 1, 5, 0 } }
|
||||
},
|
||||
left[8] = {
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 2, { 2, 3, 0 } },
|
||||
{ 1, { 3, 0, 0 } },
|
||||
{ 2, { 3, 7, 0 } },
|
||||
{ 1, { 7, 0, 0 } },
|
||||
{ 2, { 7, 0, 0 } }
|
||||
},
|
||||
right[8] = {
|
||||
{ 1, { 7, 0, 0 } },
|
||||
{ 2, { 3, 7, 0 } },
|
||||
{ 1, { 3, 0, 0 } },
|
||||
{ 2, { 3, 4, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 2, { 6, 7, 0 } }
|
||||
},
|
||||
lower[8] = {
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 2, { 0, 1, 0 } },
|
||||
{ 1, { 1, 0, 0 } },
|
||||
{ 2, { 1, 5, 0 } },
|
||||
{ 1, { 5, 0, 0 } },
|
||||
{ 2, { 5, 6, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } }
|
||||
},
|
||||
upleft[8] = {
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 1, { 3, 0, 0 } },
|
||||
{ 2, { 1, 3, 0 } },
|
||||
{ 1, { 1, 0, 0 } }
|
||||
},
|
||||
upright[8] = {
|
||||
{ 2, { 3, 5, 0 } },
|
||||
{ 1, { 3, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 1, { 5, 0, 0 } }
|
||||
},
|
||||
lowleft[8] = {
|
||||
{ 3, { 7, 0, 1 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 1, { 1, 0, 0 } },
|
||||
{ 2, { 1, 7, 0 } },
|
||||
{ 1, { 7, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } }
|
||||
},
|
||||
lowright[8] = {
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 1, { 7, 0, 0 } },
|
||||
{ 2, { 5, 7, 0 } },
|
||||
{ 1, { 5, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } }
|
||||
};
|
||||
|
||||
|
||||
static const char flavor[] = {
|
||||
'O', '*', '#', '$', '%', '0', '@', '~'
|
||||
};
|
||||
static const short xinc[] = {
|
||||
1, 1, 1, 0, -1, -1, -1, 0
|
||||
}, yinc[] = {
|
||||
-1, 0, 1, 1, 1, 0, -1, -1
|
||||
};
|
||||
static struct worm {
|
||||
int orientation, head;
|
||||
short *xpos, *ypos;
|
||||
} *worm;
|
||||
|
||||
volatile sig_atomic_t sig_caught = 0;
|
||||
void nomem(void);
|
||||
void onsig(int);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int x, y, h, n;
|
||||
struct worm *w;
|
||||
const struct options *op;
|
||||
short *ip;
|
||||
int CO, LI, last, bottom, ch, length, number, trail;
|
||||
short **ref;
|
||||
const char *field;
|
||||
char *mp;
|
||||
unsigned int delay = 0;
|
||||
|
||||
// hb_init();
|
||||
mp = NULL;
|
||||
length = 16;
|
||||
number = 3;
|
||||
trail = ' ';
|
||||
field = NULL;
|
||||
while ((ch = getopt(argc, argv, "d:fl:n:t")) != -1)
|
||||
switch(ch) {
|
||||
case 'd':
|
||||
if ((delay = (unsigned int)strtoul(optarg, (char **)NULL, 10)) < 1 || delay > 1000)
|
||||
errx(1, "invalid delay (1-1000)");
|
||||
delay *= 1000; /* ms -> us */
|
||||
break;
|
||||
case 'f':
|
||||
field = "WORM";
|
||||
break;
|
||||
case 'l':
|
||||
if ((length = atoi(optarg)) < 2 || length > 1024) {
|
||||
errx(1, "invalid length (%d - %d).",
|
||||
2, 1024);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if ((number = atoi(optarg)) < 1) {
|
||||
errx(1, "invalid number of worms.");
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
trail = '.';
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
(void)fprintf(stderr,
|
||||
"usage: worms [-ft] [-d delay] [-l length] [-n number]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(worm = malloc((size_t)number *
|
||||
sizeof(struct worm))) || !(mp = malloc((size_t)1024)))
|
||||
nomem();
|
||||
initscr();
|
||||
CO = COLS;
|
||||
LI = LINES;
|
||||
last = CO - 1;
|
||||
bottom = LI - 1;
|
||||
if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
|
||||
nomem();
|
||||
if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
|
||||
nomem();
|
||||
for (n = 0; n < LI; ++n) {
|
||||
ref[n] = ip;
|
||||
ip += CO;
|
||||
}
|
||||
for (ip = ref[0], n = LI * CO; --n >= 0;)
|
||||
*ip++ = 0;
|
||||
for (n = number, w = &worm[0]; --n >= 0; w++) {
|
||||
w->orientation = w->head = 0;
|
||||
if (!(ip = malloc((size_t)(length * sizeof(short)))))
|
||||
nomem();
|
||||
w->xpos = ip;
|
||||
for (x = length; --x >= 0;)
|
||||
*ip++ = -1;
|
||||
if (!(ip = malloc((size_t)(length * sizeof(short)))))
|
||||
nomem();
|
||||
w->ypos = ip;
|
||||
for (y = length; --y >= 0;)
|
||||
*ip++ = -1;
|
||||
}
|
||||
|
||||
(void)signal(SIGHUP, onsig);
|
||||
(void)signal(SIGINT, onsig);
|
||||
(void)signal(SIGQUIT, onsig);
|
||||
(void)signal(SIGSTOP, onsig);
|
||||
(void)signal(SIGTSTP, onsig);
|
||||
(void)signal(SIGTERM, onsig);
|
||||
|
||||
if (field) {
|
||||
const char *p = field;
|
||||
|
||||
for (y = LI; --y >= 0;) {
|
||||
for (x = CO; --x >= 0;) {
|
||||
addch(*p++);
|
||||
if (!*p)
|
||||
p = field;
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
refresh();
|
||||
if (sig_caught) {
|
||||
endwin();
|
||||
exit(0);
|
||||
}
|
||||
for (n = 0, w = &worm[0]; n < number; n++, w++) {
|
||||
if ((x = w->xpos[h = w->head]) < 0) {
|
||||
mvaddch(y = w->ypos[h] = bottom,
|
||||
x = w->xpos[h] = 0,
|
||||
flavor[n % sizeof(flavor)]);
|
||||
ref[y][x]++;
|
||||
}
|
||||
else
|
||||
y = w->ypos[h];
|
||||
if (++h == length)
|
||||
h = 0;
|
||||
if (w->xpos[w->head = h] >= 0) {
|
||||
int x1, y1;
|
||||
|
||||
x1 = w->xpos[h];
|
||||
y1 = w->ypos[h];
|
||||
if (--ref[y1][x1] == 0) {
|
||||
mvaddch(y1, x1, trail);
|
||||
}
|
||||
}
|
||||
op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
|
||||
switch (op->nopts) {
|
||||
case 0:
|
||||
refresh();
|
||||
abort();
|
||||
return(1);
|
||||
case 1:
|
||||
w->orientation = op->opts[0];
|
||||
break;
|
||||
default:
|
||||
w->orientation =
|
||||
op->opts[(int)random() % op->nopts];
|
||||
}
|
||||
mvaddch(y += yinc[w->orientation],
|
||||
x += xinc[w->orientation],
|
||||
flavor[n % sizeof(flavor)]);
|
||||
ref[w->ypos[h] = y][w->xpos[h] = x]++;
|
||||
}
|
||||
if (usleep(delay))
|
||||
onsig(SIGTERM);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
onsig(int signo)
|
||||
{
|
||||
sig_caught = 1;
|
||||
}
|
||||
|
||||
void
|
||||
nomem(void)
|
||||
{
|
||||
errx(1, "not enough memory.");
|
||||
}
|
347
worms_mod.c
Normal file
347
worms_mod.c
Normal file
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* Copyright (c) 1980, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)worms.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD: /repoman/r/ncvs/src/games/worms/worms.c,v 1.11 2002/02/23 10:35:25 billf Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
*
|
||||
* @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
|
||||
* @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
|
||||
* @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
|
||||
* @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
|
||||
* @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
|
||||
* @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
|
||||
* @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
|
||||
* @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
|
||||
* @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
|
||||
*
|
||||
* Eric P. Scott
|
||||
* Caltech High Energy Physics
|
||||
* October, 1980
|
||||
*
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <curses.h>
|
||||
#include <err.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const struct options {
|
||||
int nopts;
|
||||
int opts[3];
|
||||
}
|
||||
normal[8] = {
|
||||
{ 3, { 7, 0, 1 } },
|
||||
{ 3, { 0, 1, 2 } },
|
||||
{ 3, { 1, 2, 3 } },
|
||||
{ 3, { 2, 3, 4 } },
|
||||
{ 3, { 3, 4, 5 } },
|
||||
{ 3, { 4, 5, 6 } },
|
||||
{ 3, { 5, 6, 7 } },
|
||||
{ 3, { 6, 7, 0 } }
|
||||
}, upper[8] = {
|
||||
{ 1, { 1, 0, 0 } },
|
||||
{ 2, { 1, 2, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 2, { 4, 5, 0 } },
|
||||
{ 1, { 5, 0, 0 } },
|
||||
{ 2, { 1, 5, 0 } }
|
||||
},
|
||||
left[8] = {
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 2, { 2, 3, 0 } },
|
||||
{ 1, { 3, 0, 0 } },
|
||||
{ 2, { 3, 7, 0 } },
|
||||
{ 1, { 7, 0, 0 } },
|
||||
{ 2, { 7, 0, 0 } }
|
||||
},
|
||||
right[8] = {
|
||||
{ 1, { 7, 0, 0 } },
|
||||
{ 2, { 3, 7, 0 } },
|
||||
{ 1, { 3, 0, 0 } },
|
||||
{ 2, { 3, 4, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 2, { 6, 7, 0 } }
|
||||
},
|
||||
lower[8] = {
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 2, { 0, 1, 0 } },
|
||||
{ 1, { 1, 0, 0 } },
|
||||
{ 2, { 1, 5, 0 } },
|
||||
{ 1, { 5, 0, 0 } },
|
||||
{ 2, { 5, 6, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } }
|
||||
},
|
||||
upleft[8] = {
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 1, { 3, 0, 0 } },
|
||||
{ 2, { 1, 3, 0 } },
|
||||
{ 1, { 1, 0, 0 } }
|
||||
},
|
||||
upright[8] = {
|
||||
{ 2, { 3, 5, 0 } },
|
||||
{ 1, { 3, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 1, { 5, 0, 0 } }
|
||||
},
|
||||
lowleft[8] = {
|
||||
{ 3, { 7, 0, 1 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 1, { 1, 0, 0 } },
|
||||
{ 2, { 1, 7, 0 } },
|
||||
{ 1, { 7, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } }
|
||||
},
|
||||
lowright[8] = {
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 1, { 7, 0, 0 } },
|
||||
{ 2, { 5, 7, 0 } },
|
||||
{ 1, { 5, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } },
|
||||
{ 0, { 0, 0, 0 } }
|
||||
};
|
||||
|
||||
|
||||
static const char flavor[] = {
|
||||
'O', '*', '#', '$', '%', '0', '@', '~'
|
||||
};
|
||||
static const short xinc[] = {
|
||||
1, 1, 1, 0, -1, -1, -1, 0
|
||||
}, yinc[] = {
|
||||
-1, 0, 1, 1, 1, 0, -1, -1
|
||||
};
|
||||
static struct worm {
|
||||
int orientation, head;
|
||||
short *xpos, *ypos;
|
||||
} *worm;
|
||||
|
||||
volatile sig_atomic_t sig_caught = 0;
|
||||
void nomem(void);
|
||||
void onsig(int);
|
||||
|
||||
void detector_init();
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
detector_init();
|
||||
int x, y, h, n;
|
||||
struct worm *w;
|
||||
const struct options *op;
|
||||
short *ip;
|
||||
int CO, LI, last, bottom, ch, length, number, trail;
|
||||
short **ref;
|
||||
const char *field;
|
||||
char *mp;
|
||||
unsigned int delay = 0;
|
||||
|
||||
// hb_init();
|
||||
mp = NULL;
|
||||
length = 16;
|
||||
number = 3;
|
||||
trail = ' ';
|
||||
field = NULL;
|
||||
while ((ch = getopt(argc, argv, "d:fl:n:t")) != -1)
|
||||
switch(ch) {
|
||||
case 'd':
|
||||
if ((delay = (unsigned int)strtoul(optarg, (char **)NULL, 10)) < 1 || delay > 1000)
|
||||
errx(1, "invalid delay (1-1000)");
|
||||
delay *= 1000; /* ms -> us */
|
||||
break;
|
||||
case 'f':
|
||||
field = "WORM";
|
||||
break;
|
||||
case 'l':
|
||||
if ((length = atoi(optarg)) < 2 || length > 1024) {
|
||||
errx(1, "invalid length (%d - %d).",
|
||||
2, 1024);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if ((number = atoi(optarg)) < 1) {
|
||||
errx(1, "invalid number of worms.");
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
trail = '.';
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
(void)fprintf(stderr,
|
||||
"usage: worms [-ft] [-d delay] [-l length] [-n number]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(worm = malloc((size_t)number *
|
||||
sizeof(struct worm))) || !(mp = malloc((size_t)1024)))
|
||||
nomem();
|
||||
initscr();
|
||||
CO = COLS;
|
||||
LI = LINES;
|
||||
last = CO - 1;
|
||||
bottom = LI - 1;
|
||||
if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
|
||||
nomem();
|
||||
if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
|
||||
nomem();
|
||||
for (n = 0; n < LI; ++n) {
|
||||
ref[n] = ip;
|
||||
ip += CO;
|
||||
}
|
||||
for (ip = ref[0], n = LI * CO; --n >= 0;)
|
||||
*ip++ = 0;
|
||||
for (n = number, w = &worm[0]; --n >= 0; w++) {
|
||||
w->orientation = w->head = 0;
|
||||
if (!(ip = malloc((size_t)(length * sizeof(short)))))
|
||||
nomem();
|
||||
w->xpos = ip;
|
||||
for (x = length; --x >= 0;)
|
||||
*ip++ = -1;
|
||||
if (!(ip = malloc((size_t)(length * sizeof(short)))))
|
||||
nomem();
|
||||
w->ypos = ip;
|
||||
for (y = length; --y >= 0;)
|
||||
*ip++ = -1;
|
||||
}
|
||||
|
||||
(void)signal(SIGHUP, onsig);
|
||||
(void)signal(SIGINT, onsig);
|
||||
(void)signal(SIGQUIT, onsig);
|
||||
(void)signal(SIGSTOP, onsig);
|
||||
(void)signal(SIGTSTP, onsig);
|
||||
(void)signal(SIGTERM, onsig);
|
||||
|
||||
if (field) {
|
||||
const char *p = field;
|
||||
|
||||
for (y = LI; --y >= 0;) {
|
||||
for (x = CO; --x >= 0;) {
|
||||
addch(*p++);
|
||||
if (!*p)
|
||||
p = field;
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
refresh();
|
||||
if (sig_caught) {
|
||||
endwin();
|
||||
exit(0);
|
||||
}
|
||||
for (n = 0, w = &worm[0]; n < number; n++, w++) {
|
||||
if ((x = w->xpos[h = w->head]) < 0) {
|
||||
mvaddch(y = w->ypos[h] = bottom,
|
||||
x = w->xpos[h] = 0,
|
||||
flavor[n % sizeof(flavor)]);
|
||||
ref[y][x]++;
|
||||
}
|
||||
else
|
||||
y = w->ypos[h];
|
||||
if (++h == length)
|
||||
h = 0;
|
||||
if (w->xpos[w->head = h] >= 0) {
|
||||
int x1, y1;
|
||||
|
||||
x1 = w->xpos[h];
|
||||
y1 = w->ypos[h];
|
||||
if (--ref[y1][x1] == 0) {
|
||||
mvaddch(y1, x1, trail);
|
||||
}
|
||||
}
|
||||
op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
|
||||
switch (op->nopts) {
|
||||
case 0:
|
||||
refresh();
|
||||
abort();
|
||||
return(1);
|
||||
case 1:
|
||||
w->orientation = op->opts[0];
|
||||
break;
|
||||
default:
|
||||
w->orientation =
|
||||
op->opts[(int)random() % op->nopts];
|
||||
}
|
||||
mvaddch(y += yinc[w->orientation],
|
||||
x += xinc[w->orientation],
|
||||
flavor[n % sizeof(flavor)]);
|
||||
ref[w->ypos[h] = y][w->xpos[h] = x]++;
|
||||
}
|
||||
if (usleep(delay))
|
||||
onsig(SIGTERM);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
onsig(int signo)
|
||||
{
|
||||
sig_caught = 1;
|
||||
}
|
||||
|
||||
void
|
||||
nomem(void)
|
||||
{
|
||||
errx(1, "not enough memory.");
|
||||
}
|
Loading…
Reference in a new issue