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