Browse Source

first flow of .h, one main() compilng

tonton Th 8 months ago
parent
commit
850cf9d8bd
14 changed files with 873 additions and 5 deletions
  1. 1
    0
      .gitignore
  2. 14
    5
      README.md
  3. 25
    0
      broadcast.h
  4. 20
    0
      clients.h
  5. 47
    0
      commands.h
  6. 15
    0
      config.h
  7. 31
    0
      defines.h
  8. 16
    0
      drinks.h
  9. 576
    0
      guinnessd.c
  10. 37
    0
      guinnessd.h
  11. 27
    0
      lists.h
  12. 18
    0
      printlog.h
  13. 20
    0
      tools.h
  14. 26
    0
      xmem.h

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+*.o

+ 14
- 5
README.md View File

@@ -1,20 +1,29 @@
1 1
 # Guinness Server
2 2
 
3
-## Origine :
3
+[Official Website of Guinnessd](http://tnemeth.free.fr/projets/guinness-server.html)
4 4
 
5
-[Official Website](http://tnemeth.free.fr/projets/guinness-server.html)
5
+## Origine :
6 6
 
7 7
 La version d'origine a un **gros** souci :
8 8
 le `Makefile` tourne désepérement
9
-en boucle ! J'ai donc décidé, pour occuper mes longues journées de
9
+[en boucle](boucle-de-make.txt) !
10
+J'ai donc décidé, pour occuper mes longues journées de
10 11
 retraite sanitaire, de sortir la disqueuse et de tenter de trouver 
11
-le bug.
12
+le bug. Et ça ne va pas être simple, le Makefile d'origine est 
13
+**très** convolué...
12 14
 
13
-## Methodologie :
15
+## Méthodologie :
14 16
 
15 17
 Pour commencer, je vais utiliser un mélange de [rache](https://la-rache.com/)
16 18
 et de [poudre verte](https://poudreverte.org/), additionné d'un peu de
17 19
 jus de citron pour le goût...
18 20
 
21
+Première étape : tenter de compiler le `main()` du serveur. Oké, il demande
22
+un certain nombre de `.h`, que je m'empresse de lui fournir à partir de
23
+l'original. C'est au moment où il me demande le `config.h` que j'allume
24
+la disqueuse, je n'ai qu'un `config.h.in` sous la main.
19 25
 
26
+## Résultat :
20 27
 
28
+« Ah, c'est l'heure d'aller boire une bière, et comme il ne faut jamais
29
+boire le ventre vide, je vais manger une Guinness avant. »

+ 25
- 0
broadcast.h View File

@@ -0,0 +1,25 @@
1
+/*
2
+ * guinnessd
3
+ * architecture clients/serveur guinness : broadcast messages
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+
9
+#ifndef GUINNNESS_BROADCAST
10
+#define GUINNNESS_BROADCAST
11
+
12
+#include "guinnessd.h"
13
+
14
+#define QUITTER   1
15
+#define TOURNEE   2
16
+#define MESSAGE   3
17
+
18
+
19
+int broadcast (int t, const char *f, const char *m);
20
+int new_message (long cid);
21
+int get_broadcastid ();
22
+void get_broadcastmsg (int *t, char **f, char **m);
23
+int send_broadcast (int socket_service, userinfos *infos);
24
+
25
+#endif

+ 20
- 0
clients.h View File

@@ -0,0 +1,20 @@
1
+/*
2
+ * clients
3
+ * architecture clients/serveur guinness
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+
9
+#ifndef GUINNESS_CLIENTS
10
+#define GUINNESS_CLIENTS
11
+
12
+
13
+void  add_client    (userinfos *infos);
14
+void  remove_client (userinfos *infos);
15
+int   rename_client (userinfos *infos, const char *new_nick);
16
+char *list_clients  ();
17
+char *infos_client  (int admin, const char *nick);
18
+
19
+
20
+#endif

+ 47
- 0
commands.h View File

@@ -0,0 +1,47 @@
1
+/*
2
+ * commands
3
+ * architecture clients/serveur guinness
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+
9
+#ifndef SERVER_COMMANDS
10
+#define SERVER_COMMANDS
11
+
12
+/*#define MAXCMDS 14*/
13
+
14
+
15
+typedef struct cmdslst {
16
+    char *nom;
17
+    char *aide;
18
+    int   args;
19
+    int   adm;
20
+    int   interv;
21
+    int  (*fct)();
22
+} cmdslst;
23
+
24
+int reply (int socket_service, char *commande, userinfos *infos);
25
+int send_servercmds (int socket_service);
26
+
27
+/* Fonctions associées aux commandes */
28
+int f_help (int socket_service, const char *commande, userinfos *infos);
29
+int f_quit (int socket_service, const char *commande, userinfos *infos);
30
+int f_list (int socket_service, const char *commande, userinfos *infos);
31
+int f_bevr (int socket_service, const char *commande, userinfos *infos);
32
+int f_cold (int socket_service, const char *commande, userinfos *infos);
33
+int f_turn (int socket_service, const char *commande, userinfos *infos);
34
+int f_mesg (int socket_service, const char *commande, userinfos *infos);
35
+int f_info (int socket_service, const char *commande, userinfos *infos);
36
+int f_nick (int socket_service, const char *commande, userinfos *infos);
37
+int f_glas (int socket_service, const char *commande, userinfos *infos);
38
+int f_sadm (int socket_service, const char *commande, userinfos *infos);
39
+int f_shut (int socket_service, const char *commande, userinfos *infos);
40
+int f_rldb (int socket_service, const char *commande, userinfos *infos);
41
+int f_addu (int socket_service, const char *commande, userinfos *infos);
42
+int f_delu (int socket_service, const char *commande, userinfos *infos);
43
+int f_save (int socket_service, const char *commande, userinfos *infos);
44
+int f_load (int socket_service, const char *commande, userinfos *infos);
45
+
46
+
47
+#endif

+ 15
- 0
config.h View File

@@ -0,0 +1,15 @@
1
+/*
2
+ * from config.h.in :
3
+ *	architecture clients/serveur guinness : configuration.
4
+ * 	homas Nemeth -- le 15 juin 2001
5
+ *
6
+   2020-03-28 : handcrafted by tth
7
+ *
8
+ */
9
+
10
+#define VERSION		"0.4.7-tth"
11
+#define OS_TYPE		"cp/m 68k"
12
+#define COMPIL_DATE	__DATE__
13
+
14
+#define DRINKS_DIR	"/var/tmp/drinks.d"
15
+

+ 31
- 0
defines.h View File

@@ -0,0 +1,31 @@
1
+/*
2
+ * defines
3
+ * Création et manipulation de sockets
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+#ifndef GUINNESS_DEFINES
9
+#define GUINNESS_DEFINES
10
+
11
+#include <assert.h>
12
+
13
+#define DEFAULT_SERVER_PORT 1664
14
+#define DEFAULT_DRINK  "guinness"
15
+#define DEFAULT_LOGOUT "Bye bye..."
16
+#define DEFAULT_PSEUDO "toto"
17
+
18
+#define SEP "\n"
19
+
20
+#define MAXSTRLEN           4096
21
+
22
+#ifndef TRUE
23
+#define TRUE                1
24
+#define FALSE               0
25
+#endif
26
+
27
+/* Important macros */
28
+#define MY_ALLOC(var, nb, type) \
29
+    ((var) = malloc((nb)*sizeof(type)), assert((var) != NULL))
30
+
31
+#endif

+ 16
- 0
drinks.h View File

@@ -0,0 +1,16 @@
1
+/*
2
+ * drinks
3
+ * architecture clients/serveur guinness : breuvages
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+
9
+#ifndef GUINNNESS_BEVRG
10
+#define GUINNNESS_BEVRG
11
+
12
+char *drinks_get (const char *nom);
13
+void drinks_list_files (const char *path);
14
+void drinks_display_list ();
15
+
16
+#endif

+ 576
- 0
guinnessd.c View File

@@ -0,0 +1,576 @@
1
+/*
2
+ * guinnessd
3
+ * architecture clients/serveur guinness
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+#include <stdio.h>
9
+#include <stdlib.h>
10
+#include <unistd.h>
11
+#include <time.h>
12
+#include <errno.h>
13
+#include <signal.h>
14
+#include <pthread.h>
15
+#include <fcntl.h>
16
+#include <getopt.h>
17
+#include <sys/types.h>
18
+#include <sys/socket.h>
19
+#include <netinet/in.h>
20
+#include <string.h>
21
+#include <strings.h>
22
+#include <locale.h>
23
+#include "defines.h"
24
+#include "xmem.h"
25
+#include "tools.h"
26
+#include "printlog.h"
27
+#include "lists.h"
28
+#include "broadcast.h"
29
+#include "drinks.h"
30
+#include "clients.h"
31
+#include "guinnessd.h"
32
+#include "commands.h"
33
+#include "config.h"
34
+
35
+/* Config spécifique  serveur */
36
+char *adr_ip       = NULL;
37
+int   port         = 0;
38
+int   online       = TRUE;
39
+char *fichierlog   = NULL;
40
+char *fichiercfg   = NULL;
41
+char *chemin       = NULL;
42
+char *admin_passwd = NULL;
43
+FILE *logfile      = NULL;
44
+FILE *outerr       = NULL;
45
+Elt  *clients_list = NULL;
46
+Elt  *drinks_list  = NULL;
47
+
48
+/* Config spécifique connexion des clients */
49
+char *pseudo       = NULL;
50
+char *drink        = NULL;
51
+char *logout       = NULL;
52
+
53
+
54
+#ifdef SunOS
55
+char *crypt(const char *key, const char *salt);
56
+#else
57
+extern char *crypt __P ((__const char *__key, __const char *__salt));
58
+#endif
59
+
60
+
61
+void install_handler ();
62
+
63
+
64
+/*
65
+ * Gestionnaire de signal SIGPIPE, SIGTERM, SIGQUIT et SIGINT
66
+ *
67
+ */
68
+void handler_signaux (int sig) {
69
+    switch (sig) {
70
+        case SIGPIPE:
71
+            printlog (LOG_NOTIFY, "Signal SIGPIPE reçu...\n");
72
+            install_handler ();
73
+            break;
74
+        case SIGTERM:
75
+        case SIGQUIT:
76
+        case SIGINT:
77
+            online = FALSE;
78
+            printlog (LOG_NOTIFY, "Signal de terminaison reçu...\n");
79
+            break;
80
+        default:
81
+            printlog (LOG_NOTIFY, "Signal reçu...\n");
82
+    }
83
+}
84
+
85
+
86
+/*
87
+ * Lecture du fichier de config : récupération des valeurs
88
+ *
89
+ */
90
+char *get_string_from_token (char *line) {
91
+    char *result = line;
92
+    char *tmp;
93
+    int   keyval = 0;
94
+
95
+    while ( (keyval != 1) && (result [0] != 0) ) {
96
+        if (result [0] == '=') keyval = 1;
97
+        if (keyval == 0) result++;
98
+    }
99
+    tmp = result++;
100
+    while (tmp [0] != 0) {
101
+        if (tmp [0] == '\n') tmp [0] = 0;
102
+        tmp++;
103
+    }
104
+    return result;
105
+}
106
+
107
+
108
+/*
109
+ * Lecture du fichier de config
110
+ *
111
+ */
112
+void load_config () {
113
+    FILE *file;
114
+    char  tmpstr[MAXSTRLEN + 1];
115
+    char *value;
116
+
117
+    /* Ouverture du fichier */
118
+    if ( (file = fopen (fichiercfg?fichiercfg:CONFIG_FILE, "r") ) != NULL) {
119
+        /* Lecture du fichier */
120
+        while (! feof (file) ) {
121
+            memset (tmpstr, 0, MAXSTRLEN + 1);
122
+            fgets (tmpstr, (int) MAXSTRLEN, file);
123
+            value = get_string_from_token (tmpstr);
124
+            if ( (strncmp (tmpstr, "port=", 5) == 0) && (port == 0) )
125
+                port = atoi (value);
126
+            if ( (strncmp (tmpstr, "passwd=", 7) == 0) &&
127
+                 (admin_passwd == NULL) )
128
+                admin_passwd = xstrdup (crypt (value, "Gs") + 2);
129
+            if ( (strncmp (tmpstr, "rep=", 4) == 0) && (chemin == NULL) )
130
+                chemin = xstrdup (value);
131
+            if ( (strncmp (tmpstr, "pseudo=", 7) == 0) && (pseudo == NULL) )
132
+                pseudo = xstrdup (value);
133
+            if ( (strncmp (tmpstr, "drink=", 6) == 0) && (drink == NULL) )
134
+                drink = xstrdup (value);
135
+            if ( (strncmp (tmpstr, "logout=", 7) == 0) && (logout == NULL) )
136
+                logout = xstrdup (value);
137
+        }
138
+        fclose (file);
139
+#ifdef DEBUG
140
+    } else {
141
+        fprintf (stderr, "Pas de fichier de config (%s).\n", CONFIG_FILE);
142
+#endif
143
+    }
144
+}
145
+
146
+
147
+/*
148
+ * Aide
149
+ *
150
+ */
151
+void Usage (int help) {
152
+    printf ("guinnessd by Thomas Nemeth - v %s (compilation %s : %s)\n",
153
+            VERSION, OS_TYPE, COMPIL_DATE);
154
+    if (help)
155
+        printf ("Usage : guinnessd [-h] [-v] [-b] [-p port] "
156
+                "[-s passwd] [-d chemin] [-l fichier] [-f fichier]\n"
157
+                "   -h         : aide sur les paramètres\n"
158
+                "   -v         : affiche la version\n"
159
+                "   -b         : détache le serveur du terminal\n"
160
+                "   -a adresse : spécifie l'adresse du serveur\n"
161
+                "   -p port    : spécifie le numéro du port\n"
162
+                "   -s passwd  : spécifie le mot de passe d'aministration\n"
163
+                "   -d chemin  : indique le chemin où se"
164
+                " trouvent les ascii-arts\n"
165
+                "   -l fichier : fichier de log\n"
166
+                "   -f fichier : fichier de configuration\n\n");
167
+    exit (1);
168
+}
169
+
170
+
171
+/*
172
+ * Traitement des arguments
173
+ *
174
+ */
175
+int traite_argv (int argc, char *argv[]) {
176
+    int option;
177
+    int detach = FALSE;
178
+
179
+    /* Vérification des paramètres */
180
+    while ((option = getopt (argc, argv, "hvba:p:s:d:l:f:")) != -1) {
181
+        switch (option) {
182
+            case 'h' :
183
+                Usage (TRUE);
184
+                break;
185
+            case 'v' :
186
+                Usage (FALSE);
187
+                break;
188
+            case 'b' :
189
+                detach = TRUE;
190
+                break;
191
+            case 'a' :
192
+                adr_ip = optarg;
193
+                break;
194
+            case 'p' :
195
+                port = atoi (optarg);
196
+                break;
197
+            case 's' :
198
+                admin_passwd = xstrdup (crypt (optarg, "Gs") + 2);
199
+                break;
200
+            case 'd' :
201
+                if (! chemin) {
202
+                    if (optarg[0] == '/') {
203
+                        chemin = xstrdup (optarg);
204
+                    } else {
205
+                        char *Pwd;
206
+                        Pwd = xmalloc ((MAXSTRLEN + 1) * sizeof (char));
207
+                        getcwd (Pwd, MAXSTRLEN);
208
+                        chemin = xmalloc ( (strlen (Pwd) + strlen (optarg) + 2)
209
+                                           * sizeof (char) );
210
+                        snprintf (chemin, MAXSTRLEN, "%s/%s",
211
+                                  Pwd, optarg);
212
+                    }
213
+                }
214
+                break;
215
+            case 'l' :
216
+                if (! fichierlog) {
217
+                    fichierlog = xstrdup (optarg);
218
+                }
219
+                break;
220
+            case 'f' :
221
+                if (! fichiercfg) {
222
+                    fichiercfg = xstrdup (optarg);
223
+                }
224
+                break;
225
+            default:
226
+                Usage (TRUE);
227
+                break;
228
+        }
229
+    }
230
+    if (optind < argc) {
231
+        if (argc - optind == 1)
232
+            fprintf (stderr, "%s: option inconnue --", argv[0]);
233
+        else
234
+            fprintf (stderr, "%s: options inconnues --", argv[0]);
235
+        for ( ; optind < argc ; optind++)
236
+            fprintf (stderr, " %s", argv[optind]);
237
+        fprintf (stderr, "\n");
238
+        Usage (TRUE);
239
+    }
240
+
241
+    return detach;
242
+}
243
+
244
+
245
+/*
246
+ * Fonction initiant la connexion.
247
+ *
248
+ */
249
+int initiate (int socket_service, userinfos *infos) {
250
+    int        cont = TRUE;
251
+    char       userdatas[MAXSTRLEN];
252
+    char      *datas, *token, *saveptr;
253
+    char       delim[] = "\n\r";
254
+    char      *nom_distant = NULL;
255
+    char      *ip_distant = NULL;
256
+    int        port_distant = 0;
257
+    int        port_local = 0;
258
+    time_t     now;
259
+    struct tm *today;
260
+
261
+    memset (userdatas, 0, MAXSTRLEN);
262
+
263
+    /* Récupération des infos sur le connecté */
264
+    get_sock_infos (socket_service,
265
+                    &nom_distant, &ip_distant,
266
+                    &port_local, &port_distant);
267
+    if (ip_distant) {
268
+        snprintf (infos->ip, MAXSTRLEN, "%s", ip_distant);
269
+        free (ip_distant);
270
+    } else sprintf (infos->ip, "0.0.0.0");
271
+    if (nom_distant) {
272
+        snprintf (infos->host, MAXSTRLEN, "%s", nom_distant);
273
+        free (nom_distant);
274
+    } else sprintf (infos->host, "none");
275
+    infos->port = port_distant;
276
+
277
+    printlog (LOG_NOTIFY, "Connexion entrante : %s %s\n",
278
+              infos->ip, infos->host ? infos->host : "");
279
+    printlog (LOG_NOTIFY, "Ports (loc/dist)   : %d / %d\n",
280
+              port_local, infos->port);
281
+
282
+    /* PROTOCOLE DE CONNEXION */
283
+    /* 1. envoi des commandes du serveur */
284
+    if ( (cont = send_servercmds (socket_service)) == FALSE)
285
+        return cont;
286
+
287
+    /* 2. attente des données du connecté */
288
+    if ( (cont = read_infos (socket_service, userdatas)) == FALSE)
289
+        return cont;
290
+
291
+    /* FIN DU PROTOCOLE : Véricifations / ajout dans la liste / affichage */
292
+    datas = xstrdup (userdatas);
293
+
294
+    /* Nom d'utilisateur */
295
+    token = strtok_r (datas, delim, &saveptr);
296
+    snprintf (infos->nom, MAXSTRLEN, "%s", token ? token : pseudo);
297
+
298
+    /* Boisson préférée */
299
+    token = strtok_r (NULL, delim, &saveptr);
300
+    snprintf (infos->prefb, MAXSTRLEN, "%s", token ? token : drink);
301
+
302
+    /* Message d'au-revoir */
303
+    token = strtok_r (NULL, delim, &saveptr);
304
+    snprintf (infos->logout, MAXSTRLEN, "%s", token ? token : logout);
305
+
306
+    /* Date de connexion */
307
+    time (&now);
308
+    today = localtime (&now);
309
+    strftime (infos->cxdate, MAXSTRLEN, "%a %d %b %Y %T", today);
310
+
311
+    printlog (LOG_NOTIFY, "Utilisateur        : [%s]\n", infos->nom);
312
+    printlog (LOG_NOTIFY, "Boisson préférée   : [%s]\n", infos->prefb);
313
+    printlog (LOG_NOTIFY, "Message de logout  : [%s]\n", infos->logout);
314
+    printlog (LOG_NOTIFY, "Date de connexion  : [%s]\n", infos->cxdate);
315
+
316
+    pthread_mutex_lock (&mutex_clients);
317
+    if (exist_elt (clients_list, infos->nom)) {
318
+        char nick_ok[MAXSTRLEN];
319
+        snprintf (nick_ok, MAXSTRLEN, "@%s", infos->nom);
320
+        snprintf (infos->nom, MAXSTRLEN, "%s", nick_ok);
321
+        send_infos (socket_service, "@Pseudo déjà utilisé !\n");
322
+        printlog (LOG_NOTIFY, "Pseudo déjà utilisé => %s\n", infos->nom);
323
+        pthread_mutex_unlock (&mutex_clients);
324
+        return FALSE;
325
+    }
326
+    send_infos (socket_service, "Bienvenue sur le serveur de Guinness.\n");
327
+    add_client (infos);
328
+    pthread_mutex_unlock (&mutex_clients);
329
+
330
+    if (! exist_elt (drinks_list, infos->prefb))
331
+        send_infos (socket_service,
332
+                    "Votre boisson préférée n'est pas disponible sur ce"
333
+                    " serveur !\nVous aurez des Guinness à la place.\n");
334
+
335
+    /* Passage en mode non bloquant */
336
+    fcntl (socket_service, F_SETFL, O_NONBLOCK);
337
+
338
+    return cont;
339
+}
340
+
341
+
342
+/*
343
+ * Fonction de traitement de la connexion avec les clients
344
+ *
345
+ */
346
+void thread_service (int *sock_serv) {
347
+    pthread_t tid            = pthread_self ();
348
+    long      old_id         = get_broadcastid ();
349
+    int       socket_service = (int) *sock_serv;
350
+    int       cont           = TRUE;
351
+    int       nb;
352
+    userinfos infos;
353
+    char      commande[MAXSTRLEN + 1];
354
+
355
+    pthread_detach (tid);
356
+
357
+    memset (infos.nom,    0, MAXSTRLEN + 1);
358
+    memset (infos.prefb,  0, MAXSTRLEN + 1);
359
+    memset (infos.logout, 0, MAXSTRLEN + 1);
360
+    infos.admin = FALSE;
361
+    infos.cold  = FALSE;
362
+
363
+    cont = initiate (socket_service, &infos);
364
+
365
+    if (cont) {
366
+        snprintf (commande, MAXSTRLEN,
367
+                  "%s a rejoint le serveur de Guinness.\n", infos.nom);
368
+        broadcast (MESSAGE, NULL, commande);
369
+    }
370
+
371
+#ifdef DEBUG
372
+    printlog (LOG_NOTIFY, "Prêt à recevoir des commandes.\n");
373
+#endif
374
+
375
+    while (cont == TRUE) {
376
+        memset (commande, 0, MAXSTRLEN + 1);
377
+
378
+        /* Lecture des caractères reçus */
379
+        do {
380
+            sleep (1);
381
+            nb = read (socket_service, commande, MAXSTRLEN);
382
+            if ( (nb == -1) || (nb == 0) ) {
383
+                if ( (errno == EAGAIN) && (nb == -1) ) continue;
384
+                if ( (errno == EPIPE) || (nb == 0) ) {
385
+                    cont = FALSE;
386
+                } else {
387
+                    printlog (LOG_ERROR, "Erreur de connexion réception !\n");
388
+                }
389
+            }
390
+        } while ( (cont != FALSE) &&
391
+                  (nb < 0) &&
392
+                  (new_message (old_id) != TRUE) );
393
+
394
+#ifdef DEBUG
395
+        printlog (LOG_NOTIFY, "Commande reçue.\n");
396
+#endif
397
+        if (cont == TRUE) {
398
+            /* Traitement de la commande */
399
+            if (nb > 0)
400
+                cont = reply (socket_service, commande, &infos);
401
+            /* Broadcast */
402
+            if (new_message (old_id) == TRUE) {
403
+                old_id = get_broadcastid ();
404
+                cont = send_broadcast (socket_service, &infos);
405
+#ifdef DEBUG
406
+                printlog (LOG_ERROR, "Émission broadcast pour %s (id = %ld)\n",
407
+                         infos.nom, old_id);
408
+#endif
409
+            }
410
+        }
411
+    }
412
+    printlog (LOG_NOTIFY, "Bye bye %s...\n", infos.nom);
413
+
414
+    if (infos.nom[0] != '@') {
415
+        pthread_mutex_lock (&mutex_clients);
416
+        remove_client (&infos);
417
+        pthread_mutex_unlock (&mutex_clients);
418
+
419
+        broadcast (QUITTER, infos.nom, infos.logout);
420
+    }
421
+
422
+    close (socket_service);
423
+}
424
+
425
+
426
+/*
427
+ * Installation du gestionnaire de signal SIGPIPE et autres...
428
+ *
429
+ */
430
+void install_handler () {
431
+    signal (SIGPIPE, handler_signaux);
432
+    signal (SIGTERM, handler_signaux);
433
+    signal (SIGQUIT, handler_signaux);
434
+    signal (SIGINT,  handler_signaux);
435
+}
436
+
437
+
438
+/*
439
+ * Initialisation générale
440
+ *
441
+ */
442
+void guinnessd_init (int argc, char *argv[]) {
443
+    pthread_mutexattr_t mutex_attr;
444
+
445
+    setlocale (LC_ALL, "");
446
+    install_handler ();
447
+
448
+    /* Valeurs par défaut */
449
+    logfile = stdout;
450
+    outerr  = stderr;
451
+
452
+    /* Traitement des paramètres */
453
+    if (traite_argv (argc, argv) == TRUE) {
454
+        switch (fork()) {
455
+            case -1: /* erreur */
456
+                perror ("fork()"); 
457
+                exit (-1);
458
+            case  0: /* le fils */
459
+                setsid ();
460
+                break;
461
+            default: /* le père */
462
+                exit (0);
463
+        }
464
+    }
465
+
466
+    /* Lecture du fichier de configuration */
467
+    load_config ();
468
+
469
+    /* Initialisation des sémaphores */
470
+    pthread_mutexattr_init (&mutex_attr);
471
+    pthread_mutex_init (&mutex_broadcast, &mutex_attr);
472
+    pthread_mutex_init (&mutex_clients, &mutex_attr);
473
+
474
+    /* Affectation des paramètres */
475
+    if (IS_NOT_GOOD (pseudo))  SET_STRING (pseudo,  DEFAULT_PSEUDO);
476
+    if (IS_NOT_GOOD (drink))   SET_STRING (drink,   DEFAULT_DRINK);
477
+    if (IS_NOT_GOOD (logout))  SET_STRING (logout,  DEFAULT_LOGOUT);
478
+    if (port == 0) port = DEFAULT_SERVER_PORT;
479
+    if (fichierlog) {
480
+        if ((logfile = fopen (fichierlog, "a"))) {
481
+            outerr  = logfile;
482
+        } else {
483
+            fprintf (stderr, "Impossible d'ouvrir le fichier %s : %s\n",
484
+                     fichierlog, strerror(errno));
485
+        }
486
+    }
487
+
488
+    /* Option pour le buffer de logs */
489
+    setvbuf (logfile, NULL, _IOLBF, 0);
490
+
491
+    /* Création de la liste de boissons par défaut*/
492
+    add_elt (&drinks_list, "guinness");
493
+
494
+    if (! chemin) chemin = xstrdup (DRINKS_DIR);
495
+    drinks_list_files (chemin);
496
+    drinks_display_list ();
497
+}
498
+
499
+
500
+/*
501
+ * Fonction principale
502
+ *
503
+ */
504
+int main (int argc, char *argv[]) {
505
+    int                  socket_ecoute;
506
+    int                  socket_service;
507
+    int                  lg_adresse = sizeof (struct sockaddr_in);
508
+    struct sockaddr_in   adresse;
509
+    pthread_t            pthread_id;
510
+
511
+    guinnessd_init (argc, argv);
512
+
513
+    /* Installation de l'écoute du serveur */
514
+    if ( (socket_ecoute = install_server (port, adr_ip, NULL)) == -1) {
515
+        printlog (LOG_ERROR, "Impossible d'installer le service.\n");
516
+        return -1;
517
+    }
518
+
519
+    /* Passage en mode non-bloquant */
520
+    fcntl (socket_ecoute, F_SETFL, O_NONBLOCK);
521
+
522
+    /* Boucle d'attente et d'ouverture de connexions */
523
+    printlog (LOG_NOTIFY, "Serveur en attente de connexions (port %d)...\n",
524
+              port);
525
+    while (online == TRUE) {
526
+        sleep (1);
527
+
528
+        /* Attente d'une connexion */
529
+        socket_service = accept (socket_ecoute, (struct sockaddr *) &adresse,
530
+                                 &lg_adresse);
531
+
532
+        /* SIGPIPE */
533
+        if ( (socket_service == -1) && (errno == EINTR) ) continue;
534
+
535
+        /* PAS DE CONNEXION => mode non bloquant pour attendre un ordre de
536
+         * terminaison
537
+         */
538
+        if ( (socket_service == -1) && (errno == EAGAIN) ) continue;
539
+
540
+        /* Autre erreur socket */
541
+        if (socket_service == -1) {
542
+            /* Erreur */
543
+            printlog (LOG_ERROR,
544
+                      "Erreur d'acceptation de socket, errno = %d.\n",
545
+                      errno);
546
+            perror (__FILE__ " accept");
547
+            close (socket_ecoute);
548
+            return -1;
549
+        }
550
+
551
+        /* Ici connexion acceptée */
552
+        printlog (LOG_NOTIFY, "Connexion acceptée...\n");
553
+
554
+        /* Lancement d'une activité de traitement */
555
+        if (pthread_create (&pthread_id, NULL/*pthread_attr_default*/,
556
+                            (void *) thread_service,
557
+                            (void *) &socket_service) == -1) {
558
+            printlog (LOG_ERROR, "Erreur création thread de service.\n");
559
+            close (socket_service);
560
+        }
561
+        /* fflush (logfile); */
562
+        sleep (2);
563
+    }
564
+
565
+    printlog (LOG_NOTIFY, "Arrêt du serveur demandé.\n");
566
+    /* fflush (logfile); */
567
+    close (socket_ecoute);
568
+
569
+    free_list (&clients_list);
570
+    free_list (&drinks_list);
571
+
572
+    pthread_mutex_destroy (&mutex_broadcast);
573
+    pthread_mutex_destroy (&mutex_clients);
574
+
575
+    return 0;
576
+}

+ 37
- 0
guinnessd.h View File

@@ -0,0 +1,37 @@
1
+/*
2
+ * guinnessd
3
+ * architecture clients/serveur guinness
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+
9
+#ifndef GUINNESS_SERVER
10
+#define GUINNESS_SERVER
11
+
12
+#include <pthread.h>
13
+
14
+#define CONFIG_FILE "/etc/guinnessdrc"
15
+
16
+#define ECRITURE 0
17
+#define LECTURE  1
18
+
19
+typedef struct userinfos {
20
+    char nom[MAXSTRLEN + 1];
21
+    char prefb[MAXSTRLEN + 1];
22
+    char logout[MAXSTRLEN + 1];
23
+    char cxdate[MAXSTRLEN + 1];
24
+    char host[MAXSTRLEN + 1];
25
+    char ip[MAXSTRLEN + 1];
26
+    int  port;
27
+    int  admin;
28
+    int  cold;
29
+    int  comm[2]; /* Pas encore utilisé */
30
+} userinfos;
31
+
32
+
33
+pthread_mutex_t mutex_broadcast;
34
+pthread_mutex_t mutex_clients;
35
+
36
+
37
+#endif

+ 27
- 0
lists.h View File

@@ -0,0 +1,27 @@
1
+/*
2
+ * lists
3
+ * architecture clients/serveur guinness
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+
9
+#ifndef GUINNESS_LISTS
10
+#define GUINNESS_LISTS
11
+
12
+typedef struct elt_t_ {
13
+    char          *nom;
14
+    struct elt_t_ *next;
15
+} Elt;
16
+
17
+
18
+void  add_elt      (Elt **elt, const char *nom);
19
+void  remove_elt   (Elt **elt, const char *nom);
20
+void  remove_elt_n (Elt **elt, int i);
21
+int   get_nb_elts  (Elt  *elt);
22
+char *elt_number   (Elt  *elt, int i);
23
+int   exist_elt    (Elt  *elt, const char *nom);
24
+char *get_elt      (Elt  *elt, const char *nom);
25
+void  free_list    (Elt **elt);
26
+
27
+#endif

+ 18
- 0
printlog.h View File

@@ -0,0 +1,18 @@
1
+/*
2
+ * printlog
3
+ * architecture clients/serveur guinness
4
+ * Thomas Nemeth / Arnaud Giersch -- le 23 août 2001
5
+ *
6
+ */
7
+
8
+
9
+#ifndef PRINT_LOGS
10
+#define PRINT_LOGS
11
+
12
+enum log_level {LOG_NOTIFY, LOG_ERROR};
13
+typedef enum log_level log_level;
14
+
15
+void printlog (log_level loglevel, const char *format, ...);
16
+
17
+
18
+#endif

+ 20
- 0
tools.h View File

@@ -0,0 +1,20 @@
1
+/*
2
+ * tools
3
+ * Création et manipulation de sockets
4
+ * Thomas Nemeth -- le 15 juin 2001
5
+ *
6
+ */
7
+
8
+#ifndef SOCKETS_TOOLS
9
+#define SOCKETS_TOOLS
10
+
11
+#include <netinet/in.h>
12
+
13
+int ouvre_socket   (int port, char *adr_ip, struct sockaddr_in *ptr_adresse);
14
+int connect_server (const char *machine, int port);
15
+int install_server (int port, char *adr_ip, struct sockaddr_in *ptr_adresse);
16
+int read_infos (int socket_data, char *infos);
17
+int send_infos (int socket_data, const char *infos);
18
+void get_sock_infos (int sock, char **nom, char **adr, int *prl, int *prd);
19
+
20
+#endif

+ 26
- 0
xmem.h View File

@@ -0,0 +1,26 @@
1
+/*
2
+ * xmem
3
+ * architecture clients/serveur guinness : gestion mémoire
4
+ * Thomas Nemeth -- le 24 août 2001
5
+ *
6
+ */
7
+
8
+
9
+#ifndef GUINNESS_XMEM
10
+#define GUINNESS_XMEM
11
+
12
+#include <string.h>
13
+#include <strings.h>
14
+
15
+void *xmalloc (size_t taille);
16
+char *xstrdup (const char *chaine);
17
+
18
+
19
+#define IS_NOT_GOOD(string) (! string || (strcmp (string, "") == 0))
20
+
21
+#define SET_STRING(string, value) {\
22
+    if (string) free (string); \
23
+    string = xstrdup (value); }
24
+
25
+
26
+#endif

Loading…
Cancel
Save