diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5761abc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/README.md b/README.md index 63497f0..de37681 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,29 @@ # Guinness Server +[Official Website of Guinnessd](http://tnemeth.free.fr/projets/guinness-server.html) + ## Origine : -[Official Website](http://tnemeth.free.fr/projets/guinness-server.html) - La version d'origine a un **gros** souci : le `Makefile` tourne désepérement -en boucle ! J'ai donc décidé, pour occuper mes longues journées de +[en boucle](boucle-de-make.txt) ! +J'ai donc décidé, pour occuper mes longues journées de retraite sanitaire, de sortir la disqueuse et de tenter de trouver -le bug. +le bug. Et ça ne va pas être simple, le Makefile d'origine est +**très** convolué... -## Methodologie : +## Méthodologie : Pour commencer, je vais utiliser un mélange de [rache](https://la-rache.com/) et de [poudre verte](https://poudreverte.org/), additionné d'un peu de jus de citron pour le goût... +Première étape : tenter de compiler le `main()` du serveur. Oké, il demande +un certain nombre de `.h`, que je m'empresse de lui fournir à partir de +l'original. C'est au moment où il me demande le `config.h` que j'allume +la disqueuse, je n'ai qu'un `config.h.in` sous la main. +## Résultat : +« Ah, c'est l'heure d'aller boire une bière, et comme il ne faut jamais +boire le ventre vide, je vais manger une Guinness avant. » \ No newline at end of file diff --git a/broadcast.h b/broadcast.h new file mode 100644 index 0000000..7b3b54d --- /dev/null +++ b/broadcast.h @@ -0,0 +1,25 @@ +/* + * guinnessd + * architecture clients/serveur guinness : broadcast messages + * Thomas Nemeth -- le 15 juin 2001 + * + */ + + +#ifndef GUINNNESS_BROADCAST +#define GUINNNESS_BROADCAST + +#include "guinnessd.h" + +#define QUITTER 1 +#define TOURNEE 2 +#define MESSAGE 3 + + +int broadcast (int t, const char *f, const char *m); +int new_message (long cid); +int get_broadcastid (); +void get_broadcastmsg (int *t, char **f, char **m); +int send_broadcast (int socket_service, userinfos *infos); + +#endif diff --git a/clients.h b/clients.h new file mode 100644 index 0000000..ea0c1bb --- /dev/null +++ b/clients.h @@ -0,0 +1,20 @@ +/* + * clients + * architecture clients/serveur guinness + * Thomas Nemeth -- le 15 juin 2001 + * + */ + + +#ifndef GUINNESS_CLIENTS +#define GUINNESS_CLIENTS + + +void add_client (userinfos *infos); +void remove_client (userinfos *infos); +int rename_client (userinfos *infos, const char *new_nick); +char *list_clients (); +char *infos_client (int admin, const char *nick); + + +#endif diff --git a/commands.h b/commands.h new file mode 100644 index 0000000..731ec84 --- /dev/null +++ b/commands.h @@ -0,0 +1,47 @@ +/* + * commands + * architecture clients/serveur guinness + * Thomas Nemeth -- le 15 juin 2001 + * + */ + + +#ifndef SERVER_COMMANDS +#define SERVER_COMMANDS + +/*#define MAXCMDS 14*/ + + +typedef struct cmdslst { + char *nom; + char *aide; + int args; + int adm; + int interv; + int (*fct)(); +} cmdslst; + +int reply (int socket_service, char *commande, userinfos *infos); +int send_servercmds (int socket_service); + +/* Fonctions associées aux commandes */ +int f_help (int socket_service, const char *commande, userinfos *infos); +int f_quit (int socket_service, const char *commande, userinfos *infos); +int f_list (int socket_service, const char *commande, userinfos *infos); +int f_bevr (int socket_service, const char *commande, userinfos *infos); +int f_cold (int socket_service, const char *commande, userinfos *infos); +int f_turn (int socket_service, const char *commande, userinfos *infos); +int f_mesg (int socket_service, const char *commande, userinfos *infos); +int f_info (int socket_service, const char *commande, userinfos *infos); +int f_nick (int socket_service, const char *commande, userinfos *infos); +int f_glas (int socket_service, const char *commande, userinfos *infos); +int f_sadm (int socket_service, const char *commande, userinfos *infos); +int f_shut (int socket_service, const char *commande, userinfos *infos); +int f_rldb (int socket_service, const char *commande, userinfos *infos); +int f_addu (int socket_service, const char *commande, userinfos *infos); +int f_delu (int socket_service, const char *commande, userinfos *infos); +int f_save (int socket_service, const char *commande, userinfos *infos); +int f_load (int socket_service, const char *commande, userinfos *infos); + + +#endif diff --git a/config.h b/config.h new file mode 100644 index 0000000..0e9c6f1 --- /dev/null +++ b/config.h @@ -0,0 +1,15 @@ +/* + * from config.h.in : + * architecture clients/serveur guinness : configuration. + * homas Nemeth -- le 15 juin 2001 + * + 2020-03-28 : handcrafted by tth + * + */ + +#define VERSION "0.4.7-tth" +#define OS_TYPE "cp/m 68k" +#define COMPIL_DATE __DATE__ + +#define DRINKS_DIR "/var/tmp/drinks.d" + diff --git a/defines.h b/defines.h new file mode 100644 index 0000000..5da753c --- /dev/null +++ b/defines.h @@ -0,0 +1,31 @@ +/* + * defines + * Création et manipulation de sockets + * Thomas Nemeth -- le 15 juin 2001 + * + */ + +#ifndef GUINNESS_DEFINES +#define GUINNESS_DEFINES + +#include + +#define DEFAULT_SERVER_PORT 1664 +#define DEFAULT_DRINK "guinness" +#define DEFAULT_LOGOUT "Bye bye..." +#define DEFAULT_PSEUDO "toto" + +#define SEP "\n" + +#define MAXSTRLEN 4096 + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +/* Important macros */ +#define MY_ALLOC(var, nb, type) \ + ((var) = malloc((nb)*sizeof(type)), assert((var) != NULL)) + +#endif diff --git a/drinks.h b/drinks.h new file mode 100644 index 0000000..4080fe2 --- /dev/null +++ b/drinks.h @@ -0,0 +1,16 @@ +/* + * drinks + * architecture clients/serveur guinness : breuvages + * Thomas Nemeth -- le 15 juin 2001 + * + */ + + +#ifndef GUINNNESS_BEVRG +#define GUINNNESS_BEVRG + +char *drinks_get (const char *nom); +void drinks_list_files (const char *path); +void drinks_display_list (); + +#endif diff --git a/guinnessd.c b/guinnessd.c new file mode 100644 index 0000000..960bd8c --- /dev/null +++ b/guinnessd.c @@ -0,0 +1,576 @@ +/* + * guinnessd + * architecture clients/serveur guinness + * Thomas Nemeth -- le 15 juin 2001 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "defines.h" +#include "xmem.h" +#include "tools.h" +#include "printlog.h" +#include "lists.h" +#include "broadcast.h" +#include "drinks.h" +#include "clients.h" +#include "guinnessd.h" +#include "commands.h" +#include "config.h" + +/* Config spécifique serveur */ +char *adr_ip = NULL; +int port = 0; +int online = TRUE; +char *fichierlog = NULL; +char *fichiercfg = NULL; +char *chemin = NULL; +char *admin_passwd = NULL; +FILE *logfile = NULL; +FILE *outerr = NULL; +Elt *clients_list = NULL; +Elt *drinks_list = NULL; + +/* Config spécifique connexion des clients */ +char *pseudo = NULL; +char *drink = NULL; +char *logout = NULL; + + +#ifdef SunOS +char *crypt(const char *key, const char *salt); +#else +extern char *crypt __P ((__const char *__key, __const char *__salt)); +#endif + + +void install_handler (); + + +/* + * Gestionnaire de signal SIGPIPE, SIGTERM, SIGQUIT et SIGINT + * + */ +void handler_signaux (int sig) { + switch (sig) { + case SIGPIPE: + printlog (LOG_NOTIFY, "Signal SIGPIPE reçu...\n"); + install_handler (); + break; + case SIGTERM: + case SIGQUIT: + case SIGINT: + online = FALSE; + printlog (LOG_NOTIFY, "Signal de terminaison reçu...\n"); + break; + default: + printlog (LOG_NOTIFY, "Signal reçu...\n"); + } +} + + +/* + * Lecture du fichier de config : récupération des valeurs + * + */ +char *get_string_from_token (char *line) { + char *result = line; + char *tmp; + int keyval = 0; + + while ( (keyval != 1) && (result [0] != 0) ) { + if (result [0] == '=') keyval = 1; + if (keyval == 0) result++; + } + tmp = result++; + while (tmp [0] != 0) { + if (tmp [0] == '\n') tmp [0] = 0; + tmp++; + } + return result; +} + + +/* + * Lecture du fichier de config + * + */ +void load_config () { + FILE *file; + char tmpstr[MAXSTRLEN + 1]; + char *value; + + /* Ouverture du fichier */ + if ( (file = fopen (fichiercfg?fichiercfg:CONFIG_FILE, "r") ) != NULL) { + /* Lecture du fichier */ + while (! feof (file) ) { + memset (tmpstr, 0, MAXSTRLEN + 1); + fgets (tmpstr, (int) MAXSTRLEN, file); + value = get_string_from_token (tmpstr); + if ( (strncmp (tmpstr, "port=", 5) == 0) && (port == 0) ) + port = atoi (value); + if ( (strncmp (tmpstr, "passwd=", 7) == 0) && + (admin_passwd == NULL) ) + admin_passwd = xstrdup (crypt (value, "Gs") + 2); + if ( (strncmp (tmpstr, "rep=", 4) == 0) && (chemin == NULL) ) + chemin = xstrdup (value); + if ( (strncmp (tmpstr, "pseudo=", 7) == 0) && (pseudo == NULL) ) + pseudo = xstrdup (value); + if ( (strncmp (tmpstr, "drink=", 6) == 0) && (drink == NULL) ) + drink = xstrdup (value); + if ( (strncmp (tmpstr, "logout=", 7) == 0) && (logout == NULL) ) + logout = xstrdup (value); + } + fclose (file); +#ifdef DEBUG + } else { + fprintf (stderr, "Pas de fichier de config (%s).\n", CONFIG_FILE); +#endif + } +} + + +/* + * Aide + * + */ +void Usage (int help) { + printf ("guinnessd by Thomas Nemeth - v %s (compilation %s : %s)\n", + VERSION, OS_TYPE, COMPIL_DATE); + if (help) + printf ("Usage : guinnessd [-h] [-v] [-b] [-p port] " + "[-s passwd] [-d chemin] [-l fichier] [-f fichier]\n" + " -h : aide sur les paramètres\n" + " -v : affiche la version\n" + " -b : détache le serveur du terminal\n" + " -a adresse : spécifie l'adresse du serveur\n" + " -p port : spécifie le numéro du port\n" + " -s passwd : spécifie le mot de passe d'aministration\n" + " -d chemin : indique le chemin où se" + " trouvent les ascii-arts\n" + " -l fichier : fichier de log\n" + " -f fichier : fichier de configuration\n\n"); + exit (1); +} + + +/* + * Traitement des arguments + * + */ +int traite_argv (int argc, char *argv[]) { + int option; + int detach = FALSE; + + /* Vérification des paramètres */ + while ((option = getopt (argc, argv, "hvba:p:s:d:l:f:")) != -1) { + switch (option) { + case 'h' : + Usage (TRUE); + break; + case 'v' : + Usage (FALSE); + break; + case 'b' : + detach = TRUE; + break; + case 'a' : + adr_ip = optarg; + break; + case 'p' : + port = atoi (optarg); + break; + case 's' : + admin_passwd = xstrdup (crypt (optarg, "Gs") + 2); + break; + case 'd' : + if (! chemin) { + if (optarg[0] == '/') { + chemin = xstrdup (optarg); + } else { + char *Pwd; + Pwd = xmalloc ((MAXSTRLEN + 1) * sizeof (char)); + getcwd (Pwd, MAXSTRLEN); + chemin = xmalloc ( (strlen (Pwd) + strlen (optarg) + 2) + * sizeof (char) ); + snprintf (chemin, MAXSTRLEN, "%s/%s", + Pwd, optarg); + } + } + break; + case 'l' : + if (! fichierlog) { + fichierlog = xstrdup (optarg); + } + break; + case 'f' : + if (! fichiercfg) { + fichiercfg = xstrdup (optarg); + } + break; + default: + Usage (TRUE); + break; + } + } + if (optind < argc) { + if (argc - optind == 1) + fprintf (stderr, "%s: option inconnue --", argv[0]); + else + fprintf (stderr, "%s: options inconnues --", argv[0]); + for ( ; optind < argc ; optind++) + fprintf (stderr, " %s", argv[optind]); + fprintf (stderr, "\n"); + Usage (TRUE); + } + + return detach; +} + + +/* + * Fonction initiant la connexion. + * + */ +int initiate (int socket_service, userinfos *infos) { + int cont = TRUE; + char userdatas[MAXSTRLEN]; + char *datas, *token, *saveptr; + char delim[] = "\n\r"; + char *nom_distant = NULL; + char *ip_distant = NULL; + int port_distant = 0; + int port_local = 0; + time_t now; + struct tm *today; + + memset (userdatas, 0, MAXSTRLEN); + + /* Récupération des infos sur le connecté */ + get_sock_infos (socket_service, + &nom_distant, &ip_distant, + &port_local, &port_distant); + if (ip_distant) { + snprintf (infos->ip, MAXSTRLEN, "%s", ip_distant); + free (ip_distant); + } else sprintf (infos->ip, "0.0.0.0"); + if (nom_distant) { + snprintf (infos->host, MAXSTRLEN, "%s", nom_distant); + free (nom_distant); + } else sprintf (infos->host, "none"); + infos->port = port_distant; + + printlog (LOG_NOTIFY, "Connexion entrante : %s %s\n", + infos->ip, infos->host ? infos->host : ""); + printlog (LOG_NOTIFY, "Ports (loc/dist) : %d / %d\n", + port_local, infos->port); + + /* PROTOCOLE DE CONNEXION */ + /* 1. envoi des commandes du serveur */ + if ( (cont = send_servercmds (socket_service)) == FALSE) + return cont; + + /* 2. attente des données du connecté */ + if ( (cont = read_infos (socket_service, userdatas)) == FALSE) + return cont; + + /* FIN DU PROTOCOLE : Véricifations / ajout dans la liste / affichage */ + datas = xstrdup (userdatas); + + /* Nom d'utilisateur */ + token = strtok_r (datas, delim, &saveptr); + snprintf (infos->nom, MAXSTRLEN, "%s", token ? token : pseudo); + + /* Boisson préférée */ + token = strtok_r (NULL, delim, &saveptr); + snprintf (infos->prefb, MAXSTRLEN, "%s", token ? token : drink); + + /* Message d'au-revoir */ + token = strtok_r (NULL, delim, &saveptr); + snprintf (infos->logout, MAXSTRLEN, "%s", token ? token : logout); + + /* Date de connexion */ + time (&now); + today = localtime (&now); + strftime (infos->cxdate, MAXSTRLEN, "%a %d %b %Y %T", today); + + printlog (LOG_NOTIFY, "Utilisateur : [%s]\n", infos->nom); + printlog (LOG_NOTIFY, "Boisson préférée : [%s]\n", infos->prefb); + printlog (LOG_NOTIFY, "Message de logout : [%s]\n", infos->logout); + printlog (LOG_NOTIFY, "Date de connexion : [%s]\n", infos->cxdate); + + pthread_mutex_lock (&mutex_clients); + if (exist_elt (clients_list, infos->nom)) { + char nick_ok[MAXSTRLEN]; + snprintf (nick_ok, MAXSTRLEN, "@%s", infos->nom); + snprintf (infos->nom, MAXSTRLEN, "%s", nick_ok); + send_infos (socket_service, "@Pseudo déjà utilisé !\n"); + printlog (LOG_NOTIFY, "Pseudo déjà utilisé => %s\n", infos->nom); + pthread_mutex_unlock (&mutex_clients); + return FALSE; + } + send_infos (socket_service, "Bienvenue sur le serveur de Guinness.\n"); + add_client (infos); + pthread_mutex_unlock (&mutex_clients); + + if (! exist_elt (drinks_list, infos->prefb)) + send_infos (socket_service, + "Votre boisson préférée n'est pas disponible sur ce" + " serveur !\nVous aurez des Guinness à la place.\n"); + + /* Passage en mode non bloquant */ + fcntl (socket_service, F_SETFL, O_NONBLOCK); + + return cont; +} + + +/* + * Fonction de traitement de la connexion avec les clients + * + */ +void thread_service (int *sock_serv) { + pthread_t tid = pthread_self (); + long old_id = get_broadcastid (); + int socket_service = (int) *sock_serv; + int cont = TRUE; + int nb; + userinfos infos; + char commande[MAXSTRLEN + 1]; + + pthread_detach (tid); + + memset (infos.nom, 0, MAXSTRLEN + 1); + memset (infos.prefb, 0, MAXSTRLEN + 1); + memset (infos.logout, 0, MAXSTRLEN + 1); + infos.admin = FALSE; + infos.cold = FALSE; + + cont = initiate (socket_service, &infos); + + if (cont) { + snprintf (commande, MAXSTRLEN, + "%s a rejoint le serveur de Guinness.\n", infos.nom); + broadcast (MESSAGE, NULL, commande); + } + +#ifdef DEBUG + printlog (LOG_NOTIFY, "Prêt à recevoir des commandes.\n"); +#endif + + while (cont == TRUE) { + memset (commande, 0, MAXSTRLEN + 1); + + /* Lecture des caractères reçus */ + do { + sleep (1); + nb = read (socket_service, commande, MAXSTRLEN); + if ( (nb == -1) || (nb == 0) ) { + if ( (errno == EAGAIN) && (nb == -1) ) continue; + if ( (errno == EPIPE) || (nb == 0) ) { + cont = FALSE; + } else { + printlog (LOG_ERROR, "Erreur de connexion réception !\n"); + } + } + } while ( (cont != FALSE) && + (nb < 0) && + (new_message (old_id) != TRUE) ); + +#ifdef DEBUG + printlog (LOG_NOTIFY, "Commande reçue.\n"); +#endif + if (cont == TRUE) { + /* Traitement de la commande */ + if (nb > 0) + cont = reply (socket_service, commande, &infos); + /* Broadcast */ + if (new_message (old_id) == TRUE) { + old_id = get_broadcastid (); + cont = send_broadcast (socket_service, &infos); +#ifdef DEBUG + printlog (LOG_ERROR, "Émission broadcast pour %s (id = %ld)\n", + infos.nom, old_id); +#endif + } + } + } + printlog (LOG_NOTIFY, "Bye bye %s...\n", infos.nom); + + if (infos.nom[0] != '@') { + pthread_mutex_lock (&mutex_clients); + remove_client (&infos); + pthread_mutex_unlock (&mutex_clients); + + broadcast (QUITTER, infos.nom, infos.logout); + } + + close (socket_service); +} + + +/* + * Installation du gestionnaire de signal SIGPIPE et autres... + * + */ +void install_handler () { + signal (SIGPIPE, handler_signaux); + signal (SIGTERM, handler_signaux); + signal (SIGQUIT, handler_signaux); + signal (SIGINT, handler_signaux); +} + + +/* + * Initialisation générale + * + */ +void guinnessd_init (int argc, char *argv[]) { + pthread_mutexattr_t mutex_attr; + + setlocale (LC_ALL, ""); + install_handler (); + + /* Valeurs par défaut */ + logfile = stdout; + outerr = stderr; + + /* Traitement des paramètres */ + if (traite_argv (argc, argv) == TRUE) { + switch (fork()) { + case -1: /* erreur */ + perror ("fork()"); + exit (-1); + case 0: /* le fils */ + setsid (); + break; + default: /* le père */ + exit (0); + } + } + + /* Lecture du fichier de configuration */ + load_config (); + + /* Initialisation des sémaphores */ + pthread_mutexattr_init (&mutex_attr); + pthread_mutex_init (&mutex_broadcast, &mutex_attr); + pthread_mutex_init (&mutex_clients, &mutex_attr); + + /* Affectation des paramètres */ + if (IS_NOT_GOOD (pseudo)) SET_STRING (pseudo, DEFAULT_PSEUDO); + if (IS_NOT_GOOD (drink)) SET_STRING (drink, DEFAULT_DRINK); + if (IS_NOT_GOOD (logout)) SET_STRING (logout, DEFAULT_LOGOUT); + if (port == 0) port = DEFAULT_SERVER_PORT; + if (fichierlog) { + if ((logfile = fopen (fichierlog, "a"))) { + outerr = logfile; + } else { + fprintf (stderr, "Impossible d'ouvrir le fichier %s : %s\n", + fichierlog, strerror(errno)); + } + } + + /* Option pour le buffer de logs */ + setvbuf (logfile, NULL, _IOLBF, 0); + + /* Création de la liste de boissons par défaut*/ + add_elt (&drinks_list, "guinness"); + + if (! chemin) chemin = xstrdup (DRINKS_DIR); + drinks_list_files (chemin); + drinks_display_list (); +} + + +/* + * Fonction principale + * + */ +int main (int argc, char *argv[]) { + int socket_ecoute; + int socket_service; + int lg_adresse = sizeof (struct sockaddr_in); + struct sockaddr_in adresse; + pthread_t pthread_id; + + guinnessd_init (argc, argv); + + /* Installation de l'écoute du serveur */ + if ( (socket_ecoute = install_server (port, adr_ip, NULL)) == -1) { + printlog (LOG_ERROR, "Impossible d'installer le service.\n"); + return -1; + } + + /* Passage en mode non-bloquant */ + fcntl (socket_ecoute, F_SETFL, O_NONBLOCK); + + /* Boucle d'attente et d'ouverture de connexions */ + printlog (LOG_NOTIFY, "Serveur en attente de connexions (port %d)...\n", + port); + while (online == TRUE) { + sleep (1); + + /* Attente d'une connexion */ + socket_service = accept (socket_ecoute, (struct sockaddr *) &adresse, + &lg_adresse); + + /* SIGPIPE */ + if ( (socket_service == -1) && (errno == EINTR) ) continue; + + /* PAS DE CONNEXION => mode non bloquant pour attendre un ordre de + * terminaison + */ + if ( (socket_service == -1) && (errno == EAGAIN) ) continue; + + /* Autre erreur socket */ + if (socket_service == -1) { + /* Erreur */ + printlog (LOG_ERROR, + "Erreur d'acceptation de socket, errno = %d.\n", + errno); + perror (__FILE__ " accept"); + close (socket_ecoute); + return -1; + } + + /* Ici connexion acceptée */ + printlog (LOG_NOTIFY, "Connexion acceptée...\n"); + + /* Lancement d'une activité de traitement */ + if (pthread_create (&pthread_id, NULL/*pthread_attr_default*/, + (void *) thread_service, + (void *) &socket_service) == -1) { + printlog (LOG_ERROR, "Erreur création thread de service.\n"); + close (socket_service); + } + /* fflush (logfile); */ + sleep (2); + } + + printlog (LOG_NOTIFY, "Arrêt du serveur demandé.\n"); + /* fflush (logfile); */ + close (socket_ecoute); + + free_list (&clients_list); + free_list (&drinks_list); + + pthread_mutex_destroy (&mutex_broadcast); + pthread_mutex_destroy (&mutex_clients); + + return 0; +} diff --git a/guinnessd.h b/guinnessd.h new file mode 100644 index 0000000..33f59f0 --- /dev/null +++ b/guinnessd.h @@ -0,0 +1,37 @@ +/* + * guinnessd + * architecture clients/serveur guinness + * Thomas Nemeth -- le 15 juin 2001 + * + */ + + +#ifndef GUINNESS_SERVER +#define GUINNESS_SERVER + +#include + +#define CONFIG_FILE "/etc/guinnessdrc" + +#define ECRITURE 0 +#define LECTURE 1 + +typedef struct userinfos { + char nom[MAXSTRLEN + 1]; + char prefb[MAXSTRLEN + 1]; + char logout[MAXSTRLEN + 1]; + char cxdate[MAXSTRLEN + 1]; + char host[MAXSTRLEN + 1]; + char ip[MAXSTRLEN + 1]; + int port; + int admin; + int cold; + int comm[2]; /* Pas encore utilisé */ +} userinfos; + + +pthread_mutex_t mutex_broadcast; +pthread_mutex_t mutex_clients; + + +#endif diff --git a/lists.h b/lists.h new file mode 100644 index 0000000..7462189 --- /dev/null +++ b/lists.h @@ -0,0 +1,27 @@ +/* + * lists + * architecture clients/serveur guinness + * Thomas Nemeth -- le 15 juin 2001 + * + */ + + +#ifndef GUINNESS_LISTS +#define GUINNESS_LISTS + +typedef struct elt_t_ { + char *nom; + struct elt_t_ *next; +} Elt; + + +void add_elt (Elt **elt, const char *nom); +void remove_elt (Elt **elt, const char *nom); +void remove_elt_n (Elt **elt, int i); +int get_nb_elts (Elt *elt); +char *elt_number (Elt *elt, int i); +int exist_elt (Elt *elt, const char *nom); +char *get_elt (Elt *elt, const char *nom); +void free_list (Elt **elt); + +#endif diff --git a/printlog.h b/printlog.h new file mode 100644 index 0000000..75ce697 --- /dev/null +++ b/printlog.h @@ -0,0 +1,18 @@ +/* + * printlog + * architecture clients/serveur guinness + * Thomas Nemeth / Arnaud Giersch -- le 23 août 2001 + * + */ + + +#ifndef PRINT_LOGS +#define PRINT_LOGS + +enum log_level {LOG_NOTIFY, LOG_ERROR}; +typedef enum log_level log_level; + +void printlog (log_level loglevel, const char *format, ...); + + +#endif diff --git a/tools.h b/tools.h new file mode 100644 index 0000000..0ce1f21 --- /dev/null +++ b/tools.h @@ -0,0 +1,20 @@ +/* + * tools + * Création et manipulation de sockets + * Thomas Nemeth -- le 15 juin 2001 + * + */ + +#ifndef SOCKETS_TOOLS +#define SOCKETS_TOOLS + +#include + +int ouvre_socket (int port, char *adr_ip, struct sockaddr_in *ptr_adresse); +int connect_server (const char *machine, int port); +int install_server (int port, char *adr_ip, struct sockaddr_in *ptr_adresse); +int read_infos (int socket_data, char *infos); +int send_infos (int socket_data, const char *infos); +void get_sock_infos (int sock, char **nom, char **adr, int *prl, int *prd); + +#endif diff --git a/xmem.h b/xmem.h new file mode 100644 index 0000000..4329745 --- /dev/null +++ b/xmem.h @@ -0,0 +1,26 @@ +/* + * xmem + * architecture clients/serveur guinness : gestion mémoire + * Thomas Nemeth -- le 24 août 2001 + * + */ + + +#ifndef GUINNESS_XMEM +#define GUINNESS_XMEM + +#include +#include + +void *xmalloc (size_t taille); +char *xstrdup (const char *chaine); + + +#define IS_NOT_GOOD(string) (! string || (strcmp (string, "") == 0)) + +#define SET_STRING(string, value) {\ + if (string) free (string); \ + string = xstrdup (value); } + + +#endif