first flow of .h, one main() compilng
This commit is contained in:
parent
33f0954c7b
commit
850cf9d8bd
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.o
|
19
README.md
19
README.md
@ -1,20 +1,29 @@
|
|||||||
# Guinness Server
|
# Guinness Server
|
||||||
|
|
||||||
|
[Official Website of Guinnessd](http://tnemeth.free.fr/projets/guinness-server.html)
|
||||||
|
|
||||||
## Origine :
|
## Origine :
|
||||||
|
|
||||||
[Official Website](http://tnemeth.free.fr/projets/guinness-server.html)
|
|
||||||
|
|
||||||
La version d'origine a un **gros** souci :
|
La version d'origine a un **gros** souci :
|
||||||
le `Makefile` tourne désepérement
|
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
|
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/)
|
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
|
et de [poudre verte](https://poudreverte.org/), additionné d'un peu de
|
||||||
jus de citron pour le goût...
|
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. »
|
25
broadcast.h
Normal file
25
broadcast.h
Normal file
@ -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
|
20
clients.h
Normal file
20
clients.h
Normal file
@ -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
|
47
commands.h
Normal file
47
commands.h
Normal file
@ -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
|
15
config.h
Normal file
15
config.h
Normal file
@ -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"
|
||||||
|
|
31
defines.h
Normal file
31
defines.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* defines
|
||||||
|
* Création et manipulation de sockets
|
||||||
|
* Thomas Nemeth -- le 15 juin 2001
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GUINNESS_DEFINES
|
||||||
|
#define GUINNESS_DEFINES
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#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
|
16
drinks.h
Normal file
16
drinks.h
Normal file
@ -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
|
576
guinnessd.c
Normal file
576
guinnessd.c
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
/*
|
||||||
|
* guinnessd
|
||||||
|
* architecture clients/serveur guinness
|
||||||
|
* Thomas Nemeth -- le 15 juin 2001
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#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;
|
||||||
|
}
|
37
guinnessd.h
Normal file
37
guinnessd.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* guinnessd
|
||||||
|
* architecture clients/serveur guinness
|
||||||
|
* Thomas Nemeth -- le 15 juin 2001
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef GUINNESS_SERVER
|
||||||
|
#define GUINNESS_SERVER
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#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
|
27
lists.h
Normal file
27
lists.h
Normal file
@ -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
|
18
printlog.h
Normal file
18
printlog.h
Normal file
@ -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
|
20
tools.h
Normal file
20
tools.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* tools
|
||||||
|
* Création et manipulation de sockets
|
||||||
|
* Thomas Nemeth -- le 15 juin 2001
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOCKETS_TOOLS
|
||||||
|
#define SOCKETS_TOOLS
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
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
|
26
xmem.h
Normal file
26
xmem.h
Normal file
@ -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 <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
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
|
Loading…
Reference in New Issue
Block a user