Compare commits
15 Commits
56a7863884
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b89f86b71 | ||
| 65b4622447 | |||
| fb0ea65c80 | |||
|
|
c313b58375 | ||
|
|
002154f58f | ||
| 6159b7d07e | |||
|
|
58c7549e65 | ||
|
|
25ccec2fd3 | ||
|
|
8a9dff3514 | ||
|
|
311baad6cb | ||
|
|
efeef4140b | ||
|
|
0ef949ce91 | ||
|
|
236e274656 | ||
|
|
0040d27acc | ||
|
|
5e17585bea |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1 +1,7 @@
|
||||
|
||||
|
||||
*.o
|
||||
|
||||
guinnessd
|
||||
guinness
|
||||
|
||||
|
||||
20
Dockerfile
Normal file
20
Dockerfile
Normal file
@@ -0,0 +1,20 @@
|
||||
FROM debian:12 AS guinnessd-base
|
||||
RUN apt-get update && \
|
||||
apt-get upgrade -y && \
|
||||
apt-get install -y make gcc && \
|
||||
useradd -m -d /home/guinness -s /bin/false -r guinness
|
||||
|
||||
FROM guinnessd-base
|
||||
COPY . /home/guinness/src
|
||||
WORKDIR /home/guinness
|
||||
RUN make -C /home/guinness/src && \
|
||||
mv /home/guinness/src/guinnessd /usr/local/bin && \
|
||||
mv /home/guinness/src/picoles /usr/local/share && \
|
||||
chmod +x /usr/local/bin/guinnessd && \
|
||||
rm -Rf /home/guinness/src && \
|
||||
apt-get remove -y make gcc && \
|
||||
apt-get autoremove -y
|
||||
USER guinness
|
||||
CMD ["/usr/local/bin/guinnessd", "-p", "1664", "-d", "/usr/local/share/picoles"]
|
||||
|
||||
|
||||
51
Makefile
51
Makefile
@@ -4,16 +4,63 @@
|
||||
# Makefile handcrafted by tTh
|
||||
#
|
||||
|
||||
all: guinness guinnessd
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
H_DEP = broadcast.h commands.h defines.h guinnessd.h printlog.h \
|
||||
xmem.h clients.h config.h drinks.h lists.h tools.h
|
||||
|
||||
COPT = -Wall -g
|
||||
COPT = -fPIE -Wno-error -g
|
||||
|
||||
D_OBJS = xmem.o broadcast.o printlog.o lists.o tools.o drinks.o \
|
||||
commands.o clients.o
|
||||
|
||||
C_OBJS = xmem.o tools.o
|
||||
|
||||
D_LIBS = -lpthread -lcrypt
|
||||
|
||||
# ---------------------------------------------------------
|
||||
#
|
||||
# Main program
|
||||
#
|
||||
|
||||
guinnessd.o: guinnessd.c Makefile
|
||||
guinnessd: guinnessd.o Makefile $(D_OBJS)
|
||||
gcc -g $< $(D_OBJS) $(D_LIBS) -o $@
|
||||
|
||||
guinnessd.o: guinnessd.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
#
|
||||
|
||||
guinness: guinness.o Makefile $(D_OBJS)
|
||||
gcc -g $< $(C_OBJS) $(D_LIBS) -o $@
|
||||
|
||||
guinness.o: guinness.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
# ---------------------------------------------------------
|
||||
#
|
||||
# modules needed by the daemon
|
||||
#
|
||||
|
||||
broadcast.o: broadcast.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
printlog.o: printlog.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
lists.o: lists.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
xmem.o: xmem.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
tools.o: tools.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
drinks.o: drinks.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
commands.o: commands.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
clients.o: clients.c Makefile $(H_DEP)
|
||||
gcc $(COPT) -c $<
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
4
Makefile.docker
Normal file
4
Makefile.docker
Normal file
@@ -0,0 +1,4 @@
|
||||
.PHONY: build
|
||||
|
||||
build:
|
||||
docker build -t guinnessd:latest .
|
||||
127
README.md
127
README.md
@@ -12,18 +12,139 @@ retraite sanitaire, de sortir la disqueuse et de tenter de trouver
|
||||
le bug. Et ça ne va pas être simple, le Makefile d'origine est
|
||||
**très** convolué...
|
||||
|
||||
Par la suite, j'ai l'intention d'y apporter quelques modifications
|
||||
que je trouverais à mon gout. Elles seront décrites plus bas
|
||||
dans la page.
|
||||
|
||||
## 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...
|
||||
jus de citron pour le goût : importer les fichiers un à un jusqu'à ce
|
||||
que ça marche. Et par la suite, remttre les choses au clair.
|
||||
|
||||
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.
|
||||
la disqueuse, je n'ai qu'un `config.h.in` sous la main. Qu'à cela ne tienne,
|
||||
_kraftons_ vite ce fichier manquant à la main.
|
||||
|
||||
Voilà finalement, avec cette méthode (que je n'hésite à appeler le
|
||||
goutte-à-goutte), j'ai reconstitué un Makefile qui fonctionne et
|
||||
compile le client et le serveur.
|
||||
|
||||
## Résultat :
|
||||
|
||||
Et voilà une session typique de remote-picole :
|
||||
|
||||
```
|
||||
tth@lubitel:~/Devel/GuinnessServer$ ./guinnessd
|
||||
guinnessd: Sat 28 Mar 2020 15:21:35 - Impossible d'ouvrir le repertoire [/var/tmp/drinks.d]
|
||||
guinnessd: Sat 28 Mar 2020 15:21:35 - Boissons disponibles :
|
||||
guinnessd: Sat 28 Mar 2020 15:21:35 - 0 : guinness
|
||||
guinnessd: Sat 28 Mar 2020 15:21:35 - Serveur en attente de connexions (port 1664)...
|
||||
guinnessd: Sat 28 Mar 2020 15:22:18 - Connexion acceptee...
|
||||
guinnessd: Sat 28 Mar 2020 15:22:18 - Connexion entrante : 127.0.0.1 localhost
|
||||
guinnessd: Sat 28 Mar 2020 15:22:18 - Ports (loc/dist) : 1664 / 47647
|
||||
guinnessd: Sat 28 Mar 2020 15:22:18 - Utilisateur : [tth]
|
||||
guinnessd: Sat 28 Mar 2020 15:22:18 - Boisson preferee : [guinness]
|
||||
guinnessd: Sat 28 Mar 2020 15:22:18 - Message de logout : [Bye bye...]
|
||||
guinnessd: Sat 28 Mar 2020 15:22:18 - Date de connexion : [Sat 28 Mar 2020 15:22:18]
|
||||
guinnessd: Sat 28 Mar 2020 15:22:19 - Broadcast pour [tth] : MESSAGE
|
||||
guinnessd: Sat 28 Mar 2020 15:22:19 - de [---] : tth a rejoint le serveur de Guinness.
|
||||
```
|
||||
|
||||
|
||||
« 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. »
|
||||
boire le ventre vide, je vais manger une Guinness avant. »
|
||||
|
||||
|
||||
```
|
||||
tth@lubitel:~/Devel/GuinnessServer$ ./guinness -u tth
|
||||
Serveur : [127.0.0.1] Port : [1664]
|
||||
Utilisateur : [tth] Boisson : [guinness] Logout : [Bye bye...]
|
||||
Préfixe : [/]
|
||||
-+- Connexion acceptee. -+-
|
||||
|
||||
Bienvenue sur le serveur de Guinness.
|
||||
> <---> tth a rejoint le serveur de Guinness.
|
||||
> /1
|
||||
.____,ooo____.
|
||||
,d#MMMMMMMMMMMMMMMMMM#o.
|
||||
|MMMMMMMMMMMMMMMMMMMMMMMM
|
||||
|MMMMMMMMMMMMMMMMMMMMMMMM
|
||||
|MMMMMMMMMMMMMMMMMMH#*#**
|
||||
|M'"""""""""""""'`
|
||||
|M.
|
||||
`ML
|
||||
HP ##o#
|
||||
|L TMP]
|
||||
M . *&' . `
|
||||
|, |dL.?-\.~b \:^ |
|
||||
`| ` ` ' `` ,
|
||||
H `
|
||||
|.
|
||||
`| |
|
||||
M ,'
|
||||
| |
|
||||
|, |
|
||||
|| |
|
||||
J' |
|
||||
M. J|
|
||||
HM\\ -':|
|
||||
`"=+\&#HMH#*??v/''
|
||||
`""""`""
|
||||
>
|
||||
|
||||
```
|
||||
## Modifications
|
||||
|
||||
* ajouter une variable d'environnement `DRINKS_DIR` pour spécifier l'emplacement
|
||||
de la réserve de picole.
|
||||
* modifier la gestion des fichiers de picole afin d'avoir une description
|
||||
succinte dans le listing du bar.
|
||||
|
||||
## Conteneur
|
||||
|
||||
Le serveur BaaS (Beverage as a Service) est dorénavant disponible sous forme de conteneur.
|
||||
|
||||
### Génération de l'image
|
||||
|
||||
Création de l'image `guinnessd:latest`
|
||||
|
||||
```bash
|
||||
make -f Makefile.docker build
|
||||
```
|
||||
|
||||
### Utilisation du conteneur
|
||||
|
||||
- Le service écoute sur le port `1664`.
|
||||
- Le bar se situe dans `/usr/local/share/picoles` et est déjà approvionné. il est donc possible d'en faire un *volume Docker*.
|
||||
|
||||
```bash
|
||||
docker run --rm -p 1664:1664 guinnessd:latest
|
||||
```
|
||||
|
||||
### *Docker Swarm*
|
||||
|
||||
Ma préférence allant à l'utilisation de *Docker* via les *Docker Swarm*, vous touverez ci-dessous un fichier de *stack*
|
||||
|
||||
```yaml
|
||||
version: 3.9
|
||||
service:
|
||||
guinnessd:
|
||||
image: guinnessd:latest
|
||||
logging:
|
||||
driver: journald
|
||||
options:
|
||||
tag: "docker: guinnessd"
|
||||
ports:
|
||||
- target: 1664
|
||||
published: 1664
|
||||
mode: host
|
||||
deploy:
|
||||
endpoint_mode: dnsrr
|
||||
mode: replicated
|
||||
replicas: 1 # Multipliez les barmen en ajoutant des réplicas :-)
|
||||
```
|
||||
|
||||
|
||||
275
broadcast.c
Normal file
275
broadcast.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* guinnessd
|
||||
* architecture clients/serveur guinness : broadcast messages
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "defines.h"
|
||||
#include "printlog.h"
|
||||
#include "xmem.h"
|
||||
#include "guinnessd.h"
|
||||
#include "lists.h"
|
||||
#include "tools.h"
|
||||
#include "broadcast.h"
|
||||
#include "drinks.h"
|
||||
|
||||
pthread_mutex_t mutex_broadcast;
|
||||
|
||||
extern Elt *clients_list;
|
||||
extern FILE *outerr;
|
||||
|
||||
|
||||
static int count = 0;
|
||||
static unsigned long id = 0;
|
||||
static Elt *bdcast_list = NULL;
|
||||
|
||||
|
||||
unsigned long get_first_id () {
|
||||
unsigned long ret = id;
|
||||
|
||||
if (bdcast_list) {
|
||||
char *first_msg;
|
||||
first_msg = elt_number (bdcast_list, 0);
|
||||
ret = strtoul (first_msg, (char **)NULL, 10);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
unsigned long get_last_id () {
|
||||
unsigned long ret = id;
|
||||
|
||||
if (bdcast_list) {
|
||||
char *last_msg;
|
||||
last_msg = elt_number (bdcast_list, get_nb_elts (bdcast_list) - 1);
|
||||
ret = strtoul (last_msg, (char **)NULL, 10);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void next_broadcast (int new) {
|
||||
#ifdef DEBUG
|
||||
printlog (LOG_NOTIFY, "Suivant ? (%ld restants / %s)\n",
|
||||
get_nb_elts (bdcast_list), new ? "NEW" : "SUITE");
|
||||
#endif
|
||||
if ( (new && (get_nb_elts (bdcast_list) == 1) ) ||
|
||||
( (!new) && (get_nb_elts (bdcast_list) >= 1) ) ) {
|
||||
pthread_mutex_lock (&mutex_clients);
|
||||
count = get_nb_elts (clients_list);
|
||||
pthread_mutex_unlock (&mutex_clients);
|
||||
id = get_last_id ();
|
||||
#ifdef DEBUG
|
||||
printlog (LOG_NOTIFY, "Message en lisse (id = %ld / count = %d)...\n",
|
||||
id, count);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int broadcast (int t, const char *f, const char *m) {
|
||||
int taille;
|
||||
char sid[MAXSTRLEN];
|
||||
char stype[MAXSTRLEN];
|
||||
char *message;
|
||||
|
||||
pthread_mutex_lock (&mutex_clients);
|
||||
if (get_nb_elts (clients_list) == 0) {
|
||||
pthread_mutex_unlock (&mutex_clients);
|
||||
return TRUE;
|
||||
}
|
||||
pthread_mutex_unlock (&mutex_clients);
|
||||
|
||||
pthread_mutex_lock (&mutex_broadcast);
|
||||
|
||||
memset (sid, 0, MAXSTRLEN);
|
||||
memset (stype, 0, MAXSTRLEN);
|
||||
snprintf (sid, MAXSTRLEN - 1, "%ld", get_last_id () + 1);
|
||||
snprintf (stype, MAXSTRLEN - 1, "%d", t);
|
||||
|
||||
taille = (strlen (sid) +
|
||||
strlen (stype) +
|
||||
(f ? strlen (f) : 3) +
|
||||
(m ? strlen (m) : 0) +
|
||||
5) * sizeof (char);
|
||||
|
||||
message = xmalloc (taille);
|
||||
memset (message, 0, taille);
|
||||
/* i_| t_| f_| m_ */
|
||||
snprintf (message, taille, "%s%s%s%s%s%s%s",
|
||||
sid, SEP,
|
||||
stype, SEP,
|
||||
f ? f : "---", SEP,
|
||||
m ? m : "");
|
||||
|
||||
add_elt (&bdcast_list, message);
|
||||
free (message);
|
||||
next_broadcast (TRUE);
|
||||
|
||||
#ifdef DEBUG
|
||||
printlog (LOG_NOTIFY,
|
||||
"Broadcast id = %s\t"
|
||||
"type = %s\t"
|
||||
"de = %s\n",
|
||||
sid,
|
||||
t == 1 ? "QUITTER" :
|
||||
t == 2 ? "TOURNEE" :
|
||||
t == 3 ? "MESSAGE" : "RIEN",
|
||||
f);
|
||||
#endif
|
||||
|
||||
pthread_mutex_unlock (&mutex_broadcast);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int new_message (long cid) {
|
||||
int res;
|
||||
|
||||
pthread_mutex_lock (&mutex_broadcast);
|
||||
res = (id > cid);
|
||||
pthread_mutex_unlock (&mutex_broadcast);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int get_broadcastid () {
|
||||
int res;
|
||||
|
||||
pthread_mutex_lock (&mutex_broadcast);
|
||||
res = id;
|
||||
pthread_mutex_unlock (&mutex_broadcast);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void get_broadcastmsg (int *t, char **f, char **m) {
|
||||
char *token, *bdcast, *saveptr;
|
||||
|
||||
pthread_mutex_lock (&mutex_broadcast);
|
||||
bdcast = xstrdup (elt_number (bdcast_list, 0));
|
||||
pthread_mutex_unlock (&mutex_broadcast);
|
||||
|
||||
if (bdcast) {
|
||||
#ifdef DEBUG
|
||||
printf ("Broadcast tokenisation : %s\n", bdcast);
|
||||
#endif
|
||||
|
||||
/* id */
|
||||
token = strtok_r (bdcast, SEP, &saveptr);
|
||||
#ifdef DEBUG
|
||||
printf ("Recu : ID = %s\n", token);
|
||||
#endif
|
||||
|
||||
/* type */
|
||||
token = strtok_r (NULL, SEP, &saveptr);
|
||||
#ifdef DEBUG
|
||||
printf ("Recu : TYPE = %s\n", token);
|
||||
#endif
|
||||
*t = atoi (token);
|
||||
|
||||
/* from */
|
||||
token = strtok_r (NULL, SEP, &saveptr);
|
||||
#ifdef DEBUG
|
||||
printf ("Recu : FROM = %s\n", token);
|
||||
#endif
|
||||
*f = NULL;
|
||||
if (token) *f = xstrdup (token);
|
||||
|
||||
/* message */
|
||||
token = strtok_r (NULL, SEP, &saveptr);
|
||||
#ifdef DEBUG
|
||||
printf ("Recu : MESSAGE = %s\n", token);
|
||||
#endif
|
||||
*m = NULL;
|
||||
if (token) *m = xstrdup (token);
|
||||
|
||||
pthread_mutex_lock (&mutex_broadcast);
|
||||
if (count > 0) count--;
|
||||
#ifdef DEBUG
|
||||
printf ("count = %d\n", count);
|
||||
#endif
|
||||
|
||||
if (count == 0) {
|
||||
remove_elt_n (&bdcast_list, 0);
|
||||
#ifdef DEBUG
|
||||
printf ("Suppression du premier element. Liste = %s\n",
|
||||
bdcast_list ? "OK." : "NULL !");
|
||||
#endif
|
||||
next_broadcast (FALSE);
|
||||
}
|
||||
pthread_mutex_unlock (&mutex_broadcast);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int send_broadcast (int socket_service, userinfos *infos) {
|
||||
char datas[MAXSTRLEN];
|
||||
char head[MAXSTRLEN];
|
||||
char *from = NULL, *mesg = NULL, *breuv = NULL;
|
||||
int type, cont = TRUE;
|
||||
|
||||
memset (datas, 0, MAXSTRLEN);
|
||||
get_broadcastmsg (&type, &from, &mesg);
|
||||
|
||||
printlog (LOG_NOTIFY, "Broadcast pour [%s] : %s\n",
|
||||
infos->nom,
|
||||
type == 1 ? "QUITTER" :
|
||||
type == 2 ? "TOURNEE" :
|
||||
type == 3 ? "MESSAGE" :
|
||||
"ERREUR");
|
||||
printlog (LOG_NOTIFY, " de [%s] : %s\n", from, mesg ? mesg : "RIEN");
|
||||
|
||||
switch (type) {
|
||||
case QUITTER: /* Un utilisateur se deconnecte */
|
||||
snprintf (datas, MAXSTRLEN - 1, "Deconnexion de [%s] : %s",
|
||||
from, mesg);
|
||||
break;
|
||||
case TOURNEE: /* Tournee generale */
|
||||
if (mesg == NULL) {
|
||||
snprintf (head, MAXSTRLEN - 1,
|
||||
" -+- Tournee generale offerte par %s ! -+-",
|
||||
from);
|
||||
breuv = drinks_get (infos->prefb);
|
||||
} else {
|
||||
snprintf (head, MAXSTRLEN - 1,
|
||||
" -+- Tournee de %s offerte par %s ! -+-",
|
||||
mesg, from);
|
||||
breuv = drinks_get (mesg);
|
||||
}
|
||||
snprintf (datas, MAXSTRLEN - 1, "%s\n%s%s\n", head, breuv, head);
|
||||
free (breuv);
|
||||
break;
|
||||
case MESSAGE: /* Message */
|
||||
snprintf (datas, MAXSTRLEN - 1, "<%s> %s\n", from, mesg);
|
||||
break;
|
||||
default:
|
||||
printlog (LOG_ERROR, "Type de message broadcast non supporte.\n");
|
||||
type = -1;
|
||||
}
|
||||
|
||||
if (from) free (from);
|
||||
if (mesg) free (mesg);
|
||||
|
||||
if (type != -1) cont = send_infos (socket_service, datas);
|
||||
|
||||
return cont;
|
||||
}
|
||||
196
clients.c
Normal file
196
clients.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* clients
|
||||
* architecture clients/serveur guinness : clients list
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "defines.h"
|
||||
#include "printlog.h"
|
||||
#include "xmem.h"
|
||||
#include "guinnessd.h"
|
||||
#include "lists.h"
|
||||
#include "tools.h"
|
||||
#include "clients.h"
|
||||
|
||||
|
||||
extern Elt *clients_list;
|
||||
|
||||
void add_client (userinfos *infos) {
|
||||
char *datas;
|
||||
int size;
|
||||
|
||||
size = strlen (infos->nom);
|
||||
size += strlen (infos->prefb);
|
||||
size += strlen (infos->cxdate);
|
||||
size += strlen (infos->host);
|
||||
size += strlen (infos->ip);
|
||||
size += 5 * strlen (SEP) + 10;
|
||||
|
||||
datas = xmalloc (size + 1);
|
||||
|
||||
sprintf (datas, "%s%s%s%s%s%s%s%s%s%s%d",
|
||||
infos->nom, SEP,
|
||||
infos->prefb, SEP,
|
||||
infos->cxdate, SEP,
|
||||
infos->host, SEP,
|
||||
infos->ip, SEP,
|
||||
infos->port);
|
||||
|
||||
add_elt (&clients_list, datas);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("Taille des elements :\n"
|
||||
"nom : %d [%s]\n"
|
||||
"biere : %d [%s]\n"
|
||||
"date : %d [%s]\n"
|
||||
"hote : %d [%s]\n"
|
||||
"ip : %d [%s]\n",
|
||||
strlen (infos->nom), infos->nom,
|
||||
strlen (infos->prefb), infos->prefb,
|
||||
strlen (infos->cxdate), infos->cxdate,
|
||||
strlen (infos->host), infos->host,
|
||||
strlen (infos->ip), infos->ip);
|
||||
|
||||
printf ("Ajout des infos : size = %d -- [%s]\n", size, datas);
|
||||
#endif
|
||||
|
||||
free (datas);
|
||||
}
|
||||
|
||||
|
||||
void remove_client (userinfos *infos) {
|
||||
remove_elt (&clients_list, infos->nom);
|
||||
}
|
||||
|
||||
|
||||
int rename_client (userinfos *infos, const char *new_nick) {
|
||||
if (exist_elt (clients_list, new_nick)) return FALSE;
|
||||
remove_elt (&clients_list, infos->nom);
|
||||
snprintf (infos->nom, MAXSTRLEN, "%s", new_nick);
|
||||
add_client (infos);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
char *list_clients () {
|
||||
char *list;
|
||||
char *lstelt;
|
||||
char *rt;
|
||||
char text[MAXSTRLEN + 1];
|
||||
int size;
|
||||
int i;
|
||||
|
||||
size = strlen ("Client(s) connecte(s) :\n");
|
||||
for (i = 0 ; i < get_nb_elts (clients_list) ; i++) {
|
||||
lstelt = elt_number (clients_list, i);
|
||||
rt = strstr (lstelt, SEP);
|
||||
strncpy (text, lstelt, rt - lstelt);
|
||||
text[rt - lstelt] = 0;
|
||||
size += 1 + strlen (text);
|
||||
}
|
||||
|
||||
list = xmalloc ((size + 1) * sizeof (char));
|
||||
|
||||
strcpy (list, "Client(s) connecte(s) :\n");
|
||||
for (i = 0 ; i < get_nb_elts (clients_list) ; i++) {
|
||||
lstelt = elt_number (clients_list, i);
|
||||
rt = strstr (lstelt, SEP);
|
||||
strncpy (text, lstelt, rt - lstelt);
|
||||
text[rt - lstelt] = 0;
|
||||
strcat (list, text);
|
||||
strcat (list, "\n");
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
char *infos_client (int admin, const char *nick) {
|
||||
char *datas;
|
||||
char *infos;
|
||||
char *token, *use, *saveptr;
|
||||
char *nom = NULL, *biere = NULL, *date = NULL;
|
||||
char *host = NULL, *ip = NULL, *port = NULL;
|
||||
int size = 0;
|
||||
|
||||
infos = get_elt (clients_list, nick);
|
||||
if (! infos) {
|
||||
datas = xmalloc (strlen (nick) + strlen (" : pseudo inconnu !\n"));
|
||||
sprintf (datas, "%s : pseudo inconnu !\n", nick);
|
||||
return datas;
|
||||
}
|
||||
|
||||
use = xstrdup (infos);
|
||||
|
||||
/* nom */
|
||||
token = strtok_r (use, SEP, &saveptr);
|
||||
if (token) nom = xstrdup (token);
|
||||
|
||||
/* biere */
|
||||
token = strtok_r (NULL, SEP, &saveptr);
|
||||
if (token) biere = xstrdup (token);
|
||||
|
||||
/* date */
|
||||
token = strtok_r (NULL, SEP, &saveptr);
|
||||
if (token) date = xstrdup (token);
|
||||
|
||||
/* hote */
|
||||
token = strtok_r (NULL, SEP, &saveptr);
|
||||
if (token) host = xstrdup (token);
|
||||
|
||||
/* ip */
|
||||
token = strtok_r (NULL, SEP, &saveptr);
|
||||
if (token) ip = xstrdup (token);
|
||||
|
||||
/* port */
|
||||
token = strtok_r (NULL, SEP, &saveptr);
|
||||
if (token) port = xstrdup (token);
|
||||
|
||||
size += strlen ("Pseudo : ");
|
||||
size += strlen ("Biere : ");
|
||||
size += strlen ("Connexion : ");
|
||||
size += 1 + (nom ? strlen (nom) : 1);
|
||||
size += 1 + (biere ? strlen (biere) : 1);
|
||||
size += 1 + (date ? strlen (date) : 1);
|
||||
if (admin) {
|
||||
size += strlen ("Hote : ");
|
||||
size += strlen ("IP : ");
|
||||
size += strlen ("Port : ");
|
||||
size += 1 + (host ? strlen (host) : 1);
|
||||
size += 1 + (ip ? strlen (ip) : 1);
|
||||
size += 1 + (port ? strlen (port) : 1);
|
||||
}
|
||||
|
||||
datas = xmalloc (size + 1);
|
||||
|
||||
sprintf (datas,
|
||||
"Pseudo : %s\n"
|
||||
"Biere : %s\n"
|
||||
"Connexion : %s\n",
|
||||
nom ? nom : "-",
|
||||
biere ? biere : "-",
|
||||
date ? date : "-");
|
||||
if (admin)
|
||||
sprintf (datas, "%s"
|
||||
"Hote : %s\n"
|
||||
"IP : %s\n"
|
||||
"Port : %s\n",
|
||||
datas,
|
||||
host ? host : "-",
|
||||
ip ? ip : "-",
|
||||
port ? port : "-");
|
||||
|
||||
if (nom) free (nom);
|
||||
if (biere) free (biere);
|
||||
if (date) free (date);
|
||||
if (host) free (host);
|
||||
if (ip) free (ip);
|
||||
if (port) free (port);
|
||||
|
||||
return datas;
|
||||
}
|
||||
446
commands.c
Normal file
446
commands.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* commands
|
||||
* architecture clients/serveur guinness
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "config.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"
|
||||
|
||||
|
||||
extern FILE *logfile;
|
||||
extern int online;
|
||||
extern char *admin_passwd;
|
||||
extern char *chemin;
|
||||
extern Elt *clients_list;
|
||||
extern Elt *drinks_list;
|
||||
|
||||
|
||||
/* Signification des champs de commandes:
|
||||
* NOM AIDE ARGS ADM INTRV FCT
|
||||
*/
|
||||
cmdslst cmds_srv[] = {
|
||||
{"help", "cette page d'aide", FALSE, FALSE, FALSE, f_help},
|
||||
{"quit", "quitter", FALSE, FALSE, FALSE, f_quit},
|
||||
{"list", "liste des clients connectes", FALSE, FALSE, FALSE, f_list},
|
||||
{"blist", "liste des boissons disponibles", FALSE, FALSE, FALSE, f_bevr},
|
||||
{"round", "tournee generale (boisson en option ou preferee)",
|
||||
TRUE, FALSE, FALSE, f_turn},
|
||||
{"cold", "la guinness est servie a - de 10C, sinon entre 12 et 15",
|
||||
FALSE, FALSE, FALSE, f_cold},
|
||||
{"msg", "message a tous les clients", TRUE, FALSE, FALSE, f_mesg},
|
||||
{"infos", "renvoie les infos du serveur", TRUE, FALSE, FALSE, f_info},
|
||||
{"nick", "change de pseudo", TRUE, FALSE, FALSE, f_nick},
|
||||
{"123456789", "nombre de verres a recevoir (boisson en option ou "
|
||||
"preferee)", FALSE, FALSE, TRUE, f_glas},
|
||||
{"admin", "passer en mode administration", TRUE, FALSE, FALSE, f_sadm},
|
||||
{"33", "arreter le serveur", FALSE, TRUE, FALSE, f_shut},
|
||||
{"add", "ajoute un utilisateur dans la liste des habitues",
|
||||
TRUE, TRUE, FALSE, f_addu},
|
||||
{"del", "enleve un utilisateur de la liste des habitues",
|
||||
TRUE, TRUE, FALSE, f_delu},
|
||||
{"rldb", "recharge la liste des boissons", FALSE, TRUE, FALSE, f_rldb},
|
||||
{"save", "sauve la liste des habitues", FALSE, TRUE, FALSE, f_save},
|
||||
{"load", "charge la liste des habitues", FALSE, TRUE, FALSE, f_load},
|
||||
{NULL, NULL, FALSE, FALSE, FALSE, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int security_ok (cmdslst cmd, userinfos infos) {
|
||||
return ( (cmd.adm == FALSE) ||
|
||||
( (cmd.adm == TRUE) && (infos.admin == TRUE) ) );
|
||||
}
|
||||
|
||||
|
||||
int reply (int socket_service, char *commande, userinfos *infos) {
|
||||
int i, cont = TRUE, found = FALSE;
|
||||
|
||||
|
||||
/* Tout d'abord, on remplace \n par \0 ! */
|
||||
for (i = 0 ; i <= strlen (commande) ; i++)
|
||||
if ( (commande[i] == '\n') || (commande[i] == '\r') ) {
|
||||
commande[i] = 0;
|
||||
}
|
||||
|
||||
if (strncmp (commande, "admin ", 6) != 0)
|
||||
printlog (LOG_NOTIFY, "Commande de %s : [%s] (%d)\n",
|
||||
infos->nom,
|
||||
commande,
|
||||
strlen (commande) );
|
||||
else {
|
||||
#ifdef DEBUG
|
||||
printlog (LOG_NOTIFY, "Commande de %s : [%s]\n", infos->nom, commande);
|
||||
#else
|
||||
printlog (LOG_NOTIFY, "Commande de %s : admin XXXXXX\n", infos->nom);
|
||||
#endif
|
||||
}
|
||||
|
||||
fflush (logfile);
|
||||
|
||||
for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
|
||||
int cmp = -1;
|
||||
cmdslst cmd = cmds_srv[i];
|
||||
|
||||
if ( (cmd.interv) &&
|
||||
( (strlen (commande) == 1) ||
|
||||
(commande[1] == ' ') ) ) {
|
||||
cmp = strchr (cmd.nom, commande[0]) == NULL ? -1 : 0;
|
||||
} else {
|
||||
if (cmd.args)
|
||||
cmp = strncmp (commande, cmd.nom, strlen (cmd.nom) );
|
||||
else
|
||||
cmp = strcmp (commande, cmd.nom);
|
||||
}
|
||||
|
||||
if ( (cmp == 0) && (security_ok (cmd, *infos) == TRUE ) ) {
|
||||
found = TRUE;
|
||||
printlog (LOG_NOTIFY, "Commande reconnue : %s\n", cmd.nom);
|
||||
cont = cmd.fct (socket_service, commande, infos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! found)
|
||||
send_infos (socket_service, "Don't flood me with stupidities !\n");
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int send_servercmds (int socket_service) {
|
||||
char *data;
|
||||
char cmd[MAXSTRLEN];
|
||||
int size = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
|
||||
memset (cmd, 0, MAXSTRLEN);
|
||||
if (cmds_srv[i].adm)
|
||||
snprintf (cmd, MAXSTRLEN - 1, "*%s\n", cmds_srv[i].nom);
|
||||
else if (cmds_srv[i].interv)
|
||||
snprintf (cmd, MAXSTRLEN - 1, "+%s\n", cmds_srv[i].nom);
|
||||
else
|
||||
snprintf (cmd, MAXSTRLEN - 1, "%s\n", cmds_srv[i].nom);
|
||||
size += strlen (cmd);
|
||||
}
|
||||
|
||||
data = xmalloc ((size + 1) * sizeof (char));
|
||||
strcpy (data, "");
|
||||
for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
|
||||
memset (cmd, 0, MAXSTRLEN);
|
||||
if (cmds_srv[i].adm)
|
||||
snprintf (cmd, MAXSTRLEN - 1, "*%s\n", cmds_srv[i].nom);
|
||||
else if (cmds_srv[i].interv)
|
||||
snprintf (cmd, MAXSTRLEN - 1, "+%s\n", cmds_srv[i].nom);
|
||||
else
|
||||
snprintf (cmd, MAXSTRLEN - 1, "%s\n", cmds_srv[i].nom);
|
||||
strcat (data, cmd);
|
||||
}
|
||||
|
||||
return send_infos (socket_service, data);
|
||||
}
|
||||
|
||||
|
||||
int f_help (int socket_service, const char *commande, userinfos *infos) {
|
||||
char *data;
|
||||
char ligne[MAXSTRLEN];
|
||||
int size = 0;
|
||||
int i;
|
||||
|
||||
memset (ligne, 0, MAXSTRLEN);
|
||||
size = strlen ("Commandes (precedees du caractere de commande) :\n");
|
||||
for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
|
||||
if (security_ok (cmds_srv[i], *infos) == TRUE) {
|
||||
if (cmds_srv[i].args)
|
||||
snprintf (ligne, MAXSTRLEN - 1, " %s [opts]\t: %s\n",
|
||||
cmds_srv[i].nom, cmds_srv[i].aide);
|
||||
else
|
||||
snprintf (ligne, MAXSTRLEN - 1, " %s%s: %s\n",
|
||||
cmds_srv[i].nom,
|
||||
strlen (cmds_srv[i].nom) < 5 ? "\t\t" : "\t",
|
||||
cmds_srv[i].aide);
|
||||
size += strlen (ligne);
|
||||
}
|
||||
}
|
||||
|
||||
data = xmalloc ((size + 1) * sizeof (char));
|
||||
|
||||
strcpy (data, "Commandes (precedees du caractere de commande) :\n");
|
||||
for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
|
||||
if (security_ok (cmds_srv[i], *infos) == TRUE) {
|
||||
if (cmds_srv[i].args)
|
||||
snprintf (ligne, MAXSTRLEN - 1, " %s [opts]\t: %s\n",
|
||||
cmds_srv[i].nom, cmds_srv[i].aide);
|
||||
else
|
||||
snprintf (ligne, MAXSTRLEN - 1, " %s%s: %s\n",
|
||||
cmds_srv[i].nom,
|
||||
strlen (cmds_srv[i].nom) < 5 ? "\t\t" : "\t",
|
||||
cmds_srv[i].aide);
|
||||
strcat (data, ligne);
|
||||
}
|
||||
}
|
||||
|
||||
return send_infos (socket_service, data);
|
||||
}
|
||||
|
||||
|
||||
int f_quit (int socket_service, const char *commande, userinfos *infos) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int f_list (int socket_service, const char *commande, userinfos *infos) {
|
||||
char *data;
|
||||
int cont;
|
||||
|
||||
pthread_mutex_lock (&mutex_clients);
|
||||
data = list_clients ();
|
||||
pthread_mutex_unlock (&mutex_clients);
|
||||
|
||||
cont = send_infos (socket_service, data);
|
||||
free (data);
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int f_bevr (int socket_service, const char *commande, userinfos *infos) {
|
||||
char *data;
|
||||
int size = 0;
|
||||
int i;
|
||||
int cont;
|
||||
|
||||
size = strlen ("Boissons disponibles :\n");
|
||||
for (i = 0 ; i < get_nb_elts (drinks_list) ; i++) {
|
||||
size += strlen (elt_number (drinks_list, i) );
|
||||
size += strlen ("\n");
|
||||
}
|
||||
|
||||
data = xmalloc ((size + 1) * sizeof (char));
|
||||
|
||||
strcpy (data, "Boissons disponibles :\n");
|
||||
for (i = 0 ; i < get_nb_elts (drinks_list) ; i++) {
|
||||
strcat (data, elt_number (drinks_list, i) );
|
||||
strcat (data, "\n");
|
||||
}
|
||||
|
||||
cont = send_infos (socket_service, data);
|
||||
free (data);
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int f_cold (int socket_service, const char *commande, userinfos *infos) {
|
||||
int cont;
|
||||
|
||||
if (infos->cold == TRUE) {
|
||||
infos->cold = FALSE;
|
||||
cont = send_infos (socket_service, "Temperature normale.\n");
|
||||
} else {
|
||||
infos->cold = TRUE;
|
||||
cont = send_infos (socket_service, "Temperature fraiche (10C).\n");
|
||||
}
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int f_turn (int socket_service, const char *commande, userinfos *infos) {
|
||||
int cont = TRUE;
|
||||
char *breuv = NULL;
|
||||
|
||||
if (strlen (commande) > 5) breuv = xstrdup (commande+6);
|
||||
|
||||
printlog (LOG_NOTIFY, "Breuvage pour tournee : %s\n",
|
||||
breuv ? breuv : "prefere");
|
||||
|
||||
if ( ( (breuv != NULL) && (exist_elt (drinks_list, breuv) == TRUE) ) ||
|
||||
(breuv == NULL) ) {
|
||||
if (! broadcast (TOURNEE, infos->nom, breuv) )
|
||||
cont = send_infos (socket_service, "Erreur de transmission !\n");
|
||||
} else
|
||||
cont = send_infos (socket_service, "Boisson non disponible !\n");
|
||||
|
||||
free (breuv);
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int f_mesg (int socket_service, const char *commande, userinfos *infos) {
|
||||
int cont = TRUE;
|
||||
|
||||
if (! broadcast (MESSAGE, infos->nom, commande + 4) )
|
||||
cont = send_infos (socket_service, "Erreur de transmission !\n");
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int f_info (int socket_service, const char *commande, userinfos *infos) {
|
||||
int cont = TRUE;
|
||||
char *data;
|
||||
|
||||
if (strlen (commande) == 5) {
|
||||
data = xmalloc (MAXSTRLEN + 1);
|
||||
snprintf (data, MAXSTRLEN, "guinnessd - v %s (compilation %s : %s)\n",
|
||||
VERSION, OS_TYPE, COMPIL_DATE);
|
||||
} else
|
||||
data = infos_client (infos->admin, commande + 6);
|
||||
|
||||
cont = send_infos (socket_service, data);
|
||||
|
||||
free (data);
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int f_nick (int socket_service, const char *commande, userinfos *infos) {
|
||||
int cont = TRUE, rename_ok;
|
||||
char *new_nick, *old_nick;
|
||||
|
||||
old_nick = xstrdup (infos->nom);
|
||||
new_nick = xstrdup (commande + 5);
|
||||
|
||||
pthread_mutex_lock (&mutex_clients);
|
||||
rename_ok = rename_client (infos, new_nick);
|
||||
pthread_mutex_unlock (&mutex_clients);
|
||||
|
||||
if (rename_ok) {
|
||||
char texte[MAXSTRLEN + 1];
|
||||
snprintf (texte, MAXSTRLEN, "%s s'appelle maintenant %s.\n",
|
||||
old_nick, new_nick);
|
||||
if (! broadcast (MESSAGE, NULL, texte) )
|
||||
cont = send_infos (socket_service, "Erreur de transmission !\n");
|
||||
} else {
|
||||
cont = send_infos (socket_service, "Pseudo deja utilise !\n");
|
||||
}
|
||||
|
||||
free (old_nick);
|
||||
free (new_nick);
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int f_glas (int socket_service, const char *commande, userinfos *infos) {
|
||||
int i, nb, cont = TRUE;
|
||||
char *breuv;
|
||||
char *data;
|
||||
|
||||
if (strlen (commande) > 2)
|
||||
breuv = xstrdup (commande + 2);
|
||||
else
|
||||
breuv = xstrdup (infos->prefb);
|
||||
|
||||
printlog (LOG_NOTIFY, "Breuvage desire : %s\n", breuv);
|
||||
|
||||
data = drinks_get (breuv);
|
||||
nb = atoi (commande);
|
||||
for (i = 0 ; i < nb ; i++)
|
||||
if ( (cont = send_infos (socket_service, data) ) == FALSE) break;
|
||||
free (data);
|
||||
free (breuv);
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int f_sadm (int socket_service, const char *commande, userinfos *infos) {
|
||||
int cont = TRUE;
|
||||
|
||||
if ( (admin_passwd) && (strcmp (admin_passwd, commande + 6) == 0) ) {
|
||||
char message[] = "Vous etes maintenant ADMINISTRATEUR.\n"
|
||||
"Nouvelles commandes :";
|
||||
char *data;
|
||||
int size = 0, i;
|
||||
|
||||
infos->admin = TRUE;
|
||||
for (i = 0 ; cmds_srv[i].nom != NULL ; i++)
|
||||
if (cmds_srv[i].adm) size += 1 + strlen (cmds_srv[i].nom);
|
||||
|
||||
size += strlen (message);
|
||||
data = xmalloc ((size + 1) * sizeof (char));
|
||||
memset (data, 0, size);
|
||||
|
||||
strcpy (data, message);
|
||||
for (i = 0 ; cmds_srv[i].nom != NULL ; i++)
|
||||
if (cmds_srv[i].adm) {
|
||||
strcat (data, " ");
|
||||
strcat (data, cmds_srv[i].nom);
|
||||
}
|
||||
|
||||
cont = send_infos (socket_service, data);
|
||||
free (data);
|
||||
} else {
|
||||
infos->admin = FALSE;
|
||||
cont = send_infos (socket_service,
|
||||
"Vous n'etes PLUS administrateur.\n");
|
||||
}
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
int f_shut (int socket_service, const char *commande, userinfos *infos) {
|
||||
|
||||
online = FALSE;
|
||||
send_infos (socket_service, "Arret en cours...\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int f_rldb (int socket_service, const char *commande, userinfos *infos) {
|
||||
|
||||
free_list (&drinks_list);
|
||||
add_elt (&drinks_list, "guinness");
|
||||
if (! chemin) chemin = xstrdup (DRINKS_DIR);
|
||||
drinks_list_files (chemin);
|
||||
drinks_display_list ();
|
||||
|
||||
return send_infos (socket_service, "Liste des boissons rechargee...\n");
|
||||
}
|
||||
|
||||
|
||||
int f_addu (int socket_service, const char *commande, userinfos *infos) {
|
||||
return send_infos (socket_service, "Fonction non implementee...\n");
|
||||
}
|
||||
|
||||
int f_delu (int socket_service, const char *commande, userinfos *infos) {
|
||||
return send_infos (socket_service, "Fonction non implementee...\n");
|
||||
}
|
||||
|
||||
int f_save (int socket_service, const char *commande, userinfos *infos) {
|
||||
return send_infos (socket_service, "Fonction non implementee...\n");
|
||||
}
|
||||
|
||||
int f_load (int socket_service, const char *commande, userinfos *infos) {
|
||||
return send_infos (socket_service, "Fonction non implementee...\n");
|
||||
}
|
||||
@@ -24,7 +24,7 @@ typedef struct cmdslst {
|
||||
int reply (int socket_service, char *commande, userinfos *infos);
|
||||
int send_servercmds (int socket_service);
|
||||
|
||||
/* Fonctions associées aux commandes */
|
||||
/* Fonctions associees 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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* defines
|
||||
* Création et manipulation de sockets
|
||||
* Creation et manipulation de sockets
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
126
drinks.c
Normal file
126
drinks.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* drinks
|
||||
* architecture clients/serveur guinness
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "defines.h"
|
||||
#include "xmem.h"
|
||||
#include "printlog.h"
|
||||
#include "lists.h"
|
||||
#include "drinks.h"
|
||||
#include "pint.h"
|
||||
|
||||
extern char *pinte;
|
||||
extern char *chemin;
|
||||
extern Elt *drinks_list;
|
||||
extern FILE *logfile;
|
||||
extern FILE *outerr;
|
||||
|
||||
|
||||
char *drinks_get_from_file (const char *nom) {
|
||||
struct stat fileinfos;
|
||||
char filename[MAXSTRLEN + 1];
|
||||
char *datas;
|
||||
FILE *fichier;
|
||||
|
||||
snprintf (filename, MAXSTRLEN, "%s/%s", chemin, nom);
|
||||
if (stat (filename, &fileinfos) == -1) {
|
||||
printlog (LOG_ERROR, "Acces impossible au fichier [%s]\n",
|
||||
filename);
|
||||
perror ("stat ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( (fichier = fopen (filename, "r")) == NULL) return NULL;
|
||||
datas = xmalloc ((fileinfos.st_size + 3) * sizeof (char));
|
||||
memset (datas, 0, fileinfos.st_size + 3);
|
||||
fread (datas, sizeof (char), fileinfos.st_size, fichier);
|
||||
fclose (fichier);
|
||||
|
||||
return datas;
|
||||
}
|
||||
|
||||
|
||||
char *drinks_get (const char *nom) {
|
||||
char *breuvage = NULL;
|
||||
int i;
|
||||
|
||||
if (nom == NULL) return NULL;
|
||||
|
||||
/* Element 0 (Guinness) disponible par defaut */
|
||||
if (strcmp (nom, "guinness") == 0) breuvage = xstrdup (pinte);
|
||||
|
||||
/* Sinon on cherche dans la liste des fichiers :
|
||||
* on commence a 1 pour eviter la pinte de Guinness qui est traitee
|
||||
* juste avant.
|
||||
*/
|
||||
if (! breuvage) {
|
||||
for (i = 1 ; i < get_nb_elts (drinks_list) ; i++)
|
||||
if (strcmp (nom, elt_number (drinks_list, i)) == 0)
|
||||
breuvage = drinks_get_from_file (nom);
|
||||
}
|
||||
|
||||
/* Dernier cas : on n'a rien trouve => pinte par defaut */
|
||||
if (! breuvage) breuvage = xstrdup (pinte);
|
||||
|
||||
return breuvage;
|
||||
}
|
||||
|
||||
void drinks_list_files (const char *path) {
|
||||
DIR *rep;
|
||||
struct dirent *dirinfos;
|
||||
struct stat fileinfos;
|
||||
int nbfiles = 0;
|
||||
char filename[MAXSTRLEN + 1];
|
||||
|
||||
if ( (rep = opendir (path)) == NULL) {
|
||||
printlog (LOG_ERROR, "Impossible d'ouvrir le repertoire [%s]\n", path);
|
||||
#ifdef DEBUG
|
||||
perror ("opendir ");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
printlog (LOG_NOTIFY, "Liste des fichiers a integrer :\n");
|
||||
while ((dirinfos = readdir (rep)) != NULL) {
|
||||
snprintf (filename, MAXSTRLEN, "%s/%s", path, dirinfos->d_name);
|
||||
if (stat (filename, &fileinfos) == -1) {
|
||||
printlog (LOG_ERROR, "Acces impossible au fichier [%s]\n",
|
||||
filename);
|
||||
#ifdef DEBUG
|
||||
perror ("stat ");
|
||||
#endif
|
||||
}
|
||||
if ( (dirinfos->d_name[0] != '.') &&
|
||||
( (fileinfos.st_mode & S_IFMT) == S_IFREG) ) {
|
||||
printlog (LOG_NOTIFY, " fichier : [%s]\n",
|
||||
dirinfos->d_name);
|
||||
add_elt (&drinks_list, dirinfos->d_name);
|
||||
nbfiles++;
|
||||
}
|
||||
}
|
||||
printlog (LOG_NOTIFY, "Fin de la liste : %d fichier%s.\n",
|
||||
nbfiles, nbfiles > 1 ? "s" : "");
|
||||
closedir (rep);
|
||||
}
|
||||
|
||||
|
||||
void drinks_display_list () {
|
||||
int i;
|
||||
char *breuvage;
|
||||
|
||||
printlog (LOG_NOTIFY, "Boissons disponibles :\n");
|
||||
for (i = 0 ; i < get_nb_elts (drinks_list) ; i++) {
|
||||
breuvage = elt_number (drinks_list, i);
|
||||
printlog (LOG_NOTIFY, "%d\t: %s\n", i, breuvage);
|
||||
}
|
||||
}
|
||||
529
guinness.c
Normal file
529
guinness.c
Normal file
@@ -0,0 +1,529 @@
|
||||
/*
|
||||
* guinness
|
||||
* architecture clients/serveur guinness.
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "defines.h"
|
||||
#include "xmem.h"
|
||||
#include "guinness.h"
|
||||
#include "tools.h"
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#ifdef SunOS
|
||||
char *crypt(const char *key, const char *salt);
|
||||
#else
|
||||
extern char *crypt __P ((__const char *__key, __const char *__salt));
|
||||
#endif
|
||||
|
||||
|
||||
/* VARIABLES GLOBALES */
|
||||
char **commandes = NULL;
|
||||
char *utilisateur = NULL;
|
||||
char *boisson = NULL;
|
||||
char *serveur = NULL;
|
||||
char *prompt = NULL;
|
||||
char *logout = NULL;
|
||||
char cmdchr = 0;
|
||||
int port = 0;
|
||||
int nb_cmd = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Lecture du fichier de config : recuperation 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 *configfile;
|
||||
char tmpstr[MAXSTRLEN + 1];
|
||||
char *Home;
|
||||
char *value;
|
||||
|
||||
Home = getenv ("HOME");
|
||||
configfile = xmalloc ((strlen (Home) +
|
||||
strlen (CONFIG_FILE) + 2) * sizeof (char));
|
||||
snprintf (configfile, MAXSTRLEN, "%s/%s", Home, CONFIG_FILE);
|
||||
|
||||
/* Ouverture du fichier */
|
||||
if ( (file = fopen (configfile, "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, "user=", 5) == 0) && (utilisateur == NULL) )
|
||||
utilisateur = xstrdup (value);
|
||||
if ( (strncmp (tmpstr, "server=", 7) == 0) && (serveur == NULL) )
|
||||
serveur = xstrdup (value);
|
||||
if ( (strncmp (tmpstr, "port=", 5) == 0) && (port == 0) )
|
||||
port = atoi (value);
|
||||
if ( (strncmp (tmpstr, "prompt=", 7) == 0) && (prompt == NULL) )
|
||||
prompt = xstrdup (value);
|
||||
if ( (strncmp (tmpstr, "pref=", 5) == 0) && (boisson == NULL) )
|
||||
boisson = xstrdup (value);
|
||||
if ( (strncmp (tmpstr, "cmdchr=", 7) == 0) && (cmdchr == 0) )
|
||||
cmdchr = value[0];
|
||||
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", configfile);
|
||||
#endif
|
||||
}
|
||||
free (configfile);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fonction de nettoyage
|
||||
*
|
||||
*/
|
||||
void libere () {
|
||||
if (utilisateur) free (utilisateur);
|
||||
if (serveur) free (serveur);
|
||||
if (boisson) free (boisson);
|
||||
if (logout) free (logout);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Aide
|
||||
*
|
||||
*/
|
||||
void Usage (int help) {
|
||||
printf ("guinness by Thomas Nemeth - v %s (compilation %s : %s)\n",
|
||||
VERSION, OS_TYPE, COMPIL_DATE);
|
||||
if (help)
|
||||
printf ("Usage : guinness [-h] [-v] [-m machine] "
|
||||
"[-p port] [-u utilisateur] [-b boisson] [-q msgdx]\n"
|
||||
" -h : aide sur les parametres\n"
|
||||
" -v : affiche la version\n"
|
||||
" -m machine : speficie le nom du serveur\n"
|
||||
" -p port : specifie le numero du port\n"
|
||||
" -u utilisateur : nom d'utilisateur\n"
|
||||
" -b boisson : boisson preferee\n"
|
||||
" -q msgdx : message d'au-revoir a la deconnexion\n"
|
||||
" Online (precede du caractere de commande \"/\") :\n"
|
||||
" help : affiche l'aide sur les commandes\n"
|
||||
" quit : quitte\n\n");
|
||||
libere ();
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Traitement des arguments
|
||||
*
|
||||
*/
|
||||
void traite_argv (int argc, char *argv[]) {
|
||||
int option;
|
||||
|
||||
/* Verification des parametres */
|
||||
while ((option = getopt (argc, argv, "hvm:p:u:b:q:")) != -1) {
|
||||
switch (option) {
|
||||
case 'h' :
|
||||
Usage (TRUE);
|
||||
break;
|
||||
case 'v' :
|
||||
Usage (FALSE);
|
||||
break;
|
||||
case 'm' :
|
||||
SET_STRING (serveur, optarg);
|
||||
break;
|
||||
case 'p' :
|
||||
port = atoi (optarg);
|
||||
break;
|
||||
case 'u' :
|
||||
SET_STRING (utilisateur, optarg);
|
||||
break;
|
||||
case 'b' :
|
||||
SET_STRING (boisson, optarg);
|
||||
break;
|
||||
case 'q' :
|
||||
SET_STRING (logout, 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Envoi de commande
|
||||
*
|
||||
*/
|
||||
int send_cmd (int socket_client) {
|
||||
char clavier[MAXSTRLEN + 1];
|
||||
char *commande;
|
||||
char *admin_crypt;
|
||||
int i, found = FALSE, cont = TRUE;
|
||||
|
||||
/* Lecture d'une commande au clavier */
|
||||
memset (clavier, 0, MAXSTRLEN);
|
||||
if ( (fgets (clavier, (int) MAXSTRLEN, stdin) == NULL) &&
|
||||
feof (stdin) ) {
|
||||
snprintf (clavier, MAXSTRLEN, "%cquit", cmdchr);
|
||||
}
|
||||
|
||||
/* Determination du type (commande explicite / message) */
|
||||
if (clavier[0] == cmdchr)
|
||||
commande = xstrdup (clavier + 1);
|
||||
else {
|
||||
commande = xmalloc ((strlen (clavier) + 6) * sizeof (char));
|
||||
snprintf (commande, strlen (clavier) + 6, "msg %s", clavier);
|
||||
}
|
||||
|
||||
/* Suppression des retours a la ligne pour comparaison */
|
||||
for (i = 0 ; i < strlen (commande) ; i++)
|
||||
if (commande[i] == '\n') commande[i] = '\0';
|
||||
|
||||
/* Recherche de la bonne commande */
|
||||
if (strlen (commande) > 0)
|
||||
for (i = 0 ; i < nb_cmd ; i++) {
|
||||
int cmp = -1;
|
||||
|
||||
if (commandes[i][0] == '*') /* Commandes d'administration */
|
||||
cmp = strncmp (commandes[i]+1, commande,
|
||||
strlen (commandes[i])-1);
|
||||
else if (commandes[i][0] == '+') /* Commandes a intervalle */
|
||||
cmp = ( (strchr (commandes[i]+1, commande[0]) != NULL) &&
|
||||
( (strlen (commande) == 1) ||
|
||||
(commande[1] == ' ') ) ) ? 0 : -1;
|
||||
else { /* Commande simple : verification pour la commande entiere
|
||||
* ou le premier caractere.
|
||||
*/
|
||||
cmp = (
|
||||
/* comparaison exacte entre les deux commandes
|
||||
*/
|
||||
(strncmp (commandes[i], commande,
|
||||
strlen (commandes[i]) ) == 0) ||
|
||||
/* comparaison entre les 2 premieres lettres en
|
||||
* cas de presence de parametres
|
||||
*/
|
||||
( (commandes[i][0] == commande[0]) &&
|
||||
(commande[1] == ' ') ) ||
|
||||
/* Comparaison entre les deux premieres lettres en cas
|
||||
* de presence d'une unique lettre dans la commande
|
||||
*/
|
||||
( (commandes[i][0] == commande[0]) &&
|
||||
(strlen (commande) == 1) ) ) ? 0 : -1;
|
||||
/* Commande trouvee : si un seul caractere, remplacement par
|
||||
* la commande complete.
|
||||
*/
|
||||
if ( (cmp == 0) &&
|
||||
(strncmp (commandes[i], commande,
|
||||
strlen (commandes[i]) ) != 0) ) {
|
||||
char *tmpstr;
|
||||
tmpstr = xmalloc ( (strlen (commande) +
|
||||
strlen (commandes[i]) ) *
|
||||
sizeof (char) );
|
||||
strcpy (tmpstr, commandes[i]);
|
||||
strcat (tmpstr, commande+1);
|
||||
#ifdef DEBUG
|
||||
printf ("Nouvelle commande = %s | %d\n",
|
||||
tmpstr, strlen (tmpstr) );
|
||||
#endif
|
||||
if (strlen (tmpstr) > MAXSTRLEN) {
|
||||
fprintf (stderr, "Commande trop longue !\n");
|
||||
printf (prompt);
|
||||
return TRUE; /* continue */
|
||||
}
|
||||
free (commande);
|
||||
commande = xstrdup (tmpstr);
|
||||
free (tmpstr);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf ("l = %c / c = %c ==> %d\n",
|
||||
commandes[i][0], commande[0], cmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cmp == 0) {
|
||||
#ifdef DEBUG
|
||||
int j;
|
||||
printf ("Commande reconnue : %s\n[%s (%d)] :",
|
||||
commandes[i], commande, strlen (commande) );
|
||||
for (j = 0 ; j < strlen (commande) ; j++)
|
||||
printf (" %d", commande[j]);
|
||||
printf ("\n");
|
||||
#endif
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (! found) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Commande inconnue : [%s (%d)]",
|
||||
commande, strlen (commande) );
|
||||
for (i = 0 ; i < strlen (commande) ; i++)
|
||||
fprintf (stderr, " %d", commande[i]);
|
||||
fprintf (stderr, ".\n\n");
|
||||
#else
|
||||
fprintf (stderr, "Commande inconnue : [%s]\n", commande);
|
||||
#endif
|
||||
printf (prompt);
|
||||
return TRUE; /* continue */
|
||||
}
|
||||
|
||||
/* Mode administrateur */
|
||||
if ( (strncmp (commande, "admin ", 6) == 0) && (strlen (commande) > 6) ) {
|
||||
int taille;
|
||||
admin_crypt = xstrdup (crypt (commande + 6, "Gs"));
|
||||
free (commande);
|
||||
taille = strlen ("admin ") + strlen (admin_crypt) + 1;
|
||||
commande = xmalloc (taille);
|
||||
snprintf (commande, taille, "admin %s", admin_crypt + 2);
|
||||
}
|
||||
|
||||
cont = send_infos (socket_client, commande);
|
||||
|
||||
free (commande);
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
void set_cmds (char *cmds) {
|
||||
char *tok, *save;
|
||||
int i = 0;
|
||||
#ifdef DEBUG
|
||||
int j;
|
||||
#endif
|
||||
|
||||
nb_cmd = 0;
|
||||
save = xstrdup (cmds);
|
||||
#ifdef DEBUG
|
||||
printf ("Commandes disponibles : \n");
|
||||
/* printf ("%s\n", cmds); */
|
||||
#endif
|
||||
tok = strtok (save, "\n");
|
||||
while (tok != NULL) {
|
||||
nb_cmd++;
|
||||
tok = strtok (NULL, "\n");
|
||||
}
|
||||
|
||||
commandes = xmalloc ((nb_cmd) * sizeof (char*));
|
||||
|
||||
tok = strtok (cmds, "\n");
|
||||
while (tok != NULL) {
|
||||
commandes[i] = xstrdup (tok);
|
||||
#ifdef DEBUG
|
||||
if (tok[0] == '+') {
|
||||
for (j = 1 ; j < strlen (commandes[i]) ; j++)
|
||||
printf ("%c%c ", cmdchr, commandes[i][j]);
|
||||
} else if (tok[0] != '*') {
|
||||
printf ("%c%s ", cmdchr, commandes[i]);
|
||||
}
|
||||
#endif
|
||||
i++;
|
||||
tok = strtok (NULL, "\n");
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
free (save);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fonction d'initialisation de la communication
|
||||
*
|
||||
*/
|
||||
int initiate (int socket_client) {
|
||||
char cmds[MAXSTRLEN];
|
||||
char datas[MAXSTRLEN];
|
||||
char nick_ok[MAXSTRLEN];
|
||||
int cont = TRUE;
|
||||
|
||||
memset (datas, 0, MAXSTRLEN);
|
||||
|
||||
/* Reception de la liste des commandes */
|
||||
cont = read_infos (socket_client, cmds);
|
||||
|
||||
if (cont) {
|
||||
set_cmds (cmds);
|
||||
|
||||
snprintf (datas, MAXSTRLEN - 1, "%s\n%s\n%s",
|
||||
utilisateur, boisson, logout);
|
||||
|
||||
/* Envoi des donnees utilisateur */
|
||||
cont = send_infos (socket_client, datas);
|
||||
|
||||
read_infos (socket_client, nick_ok);
|
||||
if (nick_ok[0] == '@') {
|
||||
printf ("%s", nick_ok + 1);
|
||||
return FALSE;
|
||||
}
|
||||
printf ("%s", nick_ok);
|
||||
|
||||
/* Traitement des commandes et des infos */
|
||||
printf (prompt);
|
||||
}
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Boucle de commande et de reception
|
||||
*
|
||||
*/
|
||||
void data_rw (int socket_client) {
|
||||
int cont = TRUE;
|
||||
char infos[MAXSTRLEN];
|
||||
fd_set lire;
|
||||
|
||||
cont = initiate (socket_client);
|
||||
|
||||
while (cont == TRUE) {
|
||||
fflush (stdout);
|
||||
|
||||
/* Construction de l'ensemble a scruter en lecture : */
|
||||
FD_ZERO (&lire);
|
||||
FD_SET (STDIN_FILENO, &lire);
|
||||
FD_SET (socket_client, &lire);
|
||||
|
||||
/* Attente d'un message sur la liste : */
|
||||
select (socket_client + 1, &lire, NULL, NULL, NULL);
|
||||
|
||||
if (FD_ISSET (STDIN_FILENO, &lire) ) {
|
||||
cont = send_cmd (socket_client);
|
||||
} else {
|
||||
int is;
|
||||
|
||||
cont = read_infos (socket_client, infos);
|
||||
|
||||
is = 0;
|
||||
do {
|
||||
printf ("%s\n", infos + is);
|
||||
while (is < MAXSTRLEN && infos[is]) is ++;
|
||||
/* on suppose qu'un seul '\0' separe deux messages */
|
||||
is ++;
|
||||
} while (is < MAXSTRLEN && infos[is]);
|
||||
|
||||
/* Hack pour faire afficher le message par xmessage
|
||||
* Pas tres joli lors des deconnexions.
|
||||
*/
|
||||
/* if (getenv ("DISPLAY")) { */
|
||||
/* if (! fork ()) */
|
||||
/* execlp ("xmessage", "xmessage", infos, NULL); */
|
||||
/* } */
|
||||
fflush (stdout);
|
||||
printf (prompt);
|
||||
}
|
||||
}
|
||||
|
||||
printf ("%s\n", logout);
|
||||
close (socket_client);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Gestionnaire de signal SIGPIPE
|
||||
*
|
||||
*/
|
||||
void handler_sigpipe (int sig) {
|
||||
printf ("Signal SIGPIPE recu...\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fonction principale
|
||||
*
|
||||
*/
|
||||
int main (int argc, char *argv[]) {
|
||||
int socket_client;
|
||||
char *environ_user;
|
||||
|
||||
signal (SIGPIPE, handler_sigpipe);
|
||||
|
||||
/* Verification des parametres */
|
||||
traite_argv (argc, argv);
|
||||
|
||||
/* Lecture du fichier de config */
|
||||
load_config ();
|
||||
|
||||
/* Valeurs par defaut */
|
||||
if (! utilisateur) {
|
||||
environ_user = getenv ("USER");
|
||||
if (environ_user && *environ_user)
|
||||
utilisateur = xstrdup (environ_user);
|
||||
else
|
||||
utilisateur = xstrdup ("toto");
|
||||
}
|
||||
if (IS_NOT_GOOD (serveur)) SET_STRING (serveur, DEFAULT_SERVER);
|
||||
if (IS_NOT_GOOD (prompt)) SET_STRING (prompt, DEFAULT_PROMPT);
|
||||
if (IS_NOT_GOOD (boisson)) SET_STRING (boisson, DEFAULT_DRINK);
|
||||
if (IS_NOT_GOOD (logout)) SET_STRING (logout, DEFAULT_LOGOUT);
|
||||
if (cmdchr == 0) cmdchr = '/';
|
||||
if (port == 0) port = DEFAULT_SERVER_PORT;
|
||||
|
||||
printf ("Serveur : [%s]\t", serveur);
|
||||
printf ("Port : [%d]\n", port);
|
||||
printf ("Utilisateur : [%s]\t", utilisateur);
|
||||
printf ("\tBoisson : [%s]\t", boisson);
|
||||
printf ("Logout : [%s]\n", logout);
|
||||
printf ("Prefixe : [%c]\n", cmdchr);
|
||||
|
||||
/* Connexion au serveur */
|
||||
if ( (socket_client = connect_server (serveur, port) ) == -1) {
|
||||
fprintf (stderr, "Connexion refusee...\n");
|
||||
return -1;
|
||||
}
|
||||
printf ("-+- Connexion acceptee. -+-\n");
|
||||
|
||||
data_rw (socket_client);
|
||||
|
||||
libere ();
|
||||
return 0;
|
||||
}
|
||||
17
guinness.h
Normal file
17
guinness.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* guinness
|
||||
* architecture clients/serveur guinness.
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GUINNESS_CLIENT
|
||||
#define GUINNESS_CLIENT
|
||||
|
||||
#define CONFIG_FILE ".guinnessrc"
|
||||
|
||||
#define DEFAULT_SERVER "127.0.0.1"
|
||||
#define DEFAULT_PROMPT "> "
|
||||
|
||||
|
||||
#endif
|
||||
96
guinnessd.c
96
guinnessd.c
@@ -32,7 +32,9 @@
|
||||
#include "commands.h"
|
||||
#include "config.h"
|
||||
|
||||
/* Config spécifique serveur */
|
||||
pthread_mutex_t mutex_clients;
|
||||
|
||||
/* Config specifique serveur */
|
||||
char *adr_ip = NULL;
|
||||
int port = 0;
|
||||
int online = TRUE;
|
||||
@@ -45,7 +47,7 @@ FILE *outerr = NULL;
|
||||
Elt *clients_list = NULL;
|
||||
Elt *drinks_list = NULL;
|
||||
|
||||
/* Config spécifique connexion des clients */
|
||||
/* Config specifique connexion des clients */
|
||||
char *pseudo = NULL;
|
||||
char *drink = NULL;
|
||||
char *logout = NULL;
|
||||
@@ -68,23 +70,23 @@ void install_handler ();
|
||||
void handler_signaux (int sig) {
|
||||
switch (sig) {
|
||||
case SIGPIPE:
|
||||
printlog (LOG_NOTIFY, "Signal SIGPIPE reçu...\n");
|
||||
printlog (LOG_NOTIFY, "Signal SIGPIPE recu...\n");
|
||||
install_handler ();
|
||||
break;
|
||||
case SIGTERM:
|
||||
case SIGQUIT:
|
||||
case SIGINT:
|
||||
online = FALSE;
|
||||
printlog (LOG_NOTIFY, "Signal de terminaison reçu...\n");
|
||||
printlog (LOG_NOTIFY, "Signal de terminaison recu...\n");
|
||||
break;
|
||||
default:
|
||||
printlog (LOG_NOTIFY, "Signal reçu...\n");
|
||||
printlog (LOG_NOTIFY, "Signal recu...\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Lecture du fichier de config : récupération des valeurs
|
||||
* Lecture du fichier de config : recuperation des valeurs
|
||||
*
|
||||
*/
|
||||
char *get_string_from_token (char *line) {
|
||||
@@ -154,13 +156,13 @@ void Usage (int help) {
|
||||
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"
|
||||
" -h : aide sur les parametres\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"
|
||||
" -b : detache le serveur du terminal\n"
|
||||
" -a adresse : specifie l'adresse du serveur\n"
|
||||
" -p port : specifie le numero du port\n"
|
||||
" -s passwd : specifie le mot de passe d'aministration\n"
|
||||
" -d chemin : indique le chemin ou se"
|
||||
" trouvent les ascii-arts\n"
|
||||
" -l fichier : fichier de log\n"
|
||||
" -f fichier : fichier de configuration\n\n");
|
||||
@@ -176,7 +178,7 @@ int traite_argv (int argc, char *argv[]) {
|
||||
int option;
|
||||
int detach = FALSE;
|
||||
|
||||
/* Vérification des paramètres */
|
||||
/* Verification des parametres */
|
||||
while ((option = getopt (argc, argv, "hvba:p:s:d:l:f:")) != -1) {
|
||||
switch (option) {
|
||||
case 'h' :
|
||||
@@ -260,7 +262,7 @@ int initiate (int socket_service, userinfos *infos) {
|
||||
|
||||
memset (userdatas, 0, MAXSTRLEN);
|
||||
|
||||
/* Récupération des infos sur le connecté */
|
||||
/* Recuperation des infos sur le connecte */
|
||||
get_sock_infos (socket_service,
|
||||
&nom_distant, &ip_distant,
|
||||
&port_local, &port_distant);
|
||||
@@ -284,18 +286,18 @@ int initiate (int socket_service, userinfos *infos) {
|
||||
if ( (cont = send_servercmds (socket_service)) == FALSE)
|
||||
return cont;
|
||||
|
||||
/* 2. attente des données du connecté */
|
||||
/* 2. attente des donnees du connecte */
|
||||
if ( (cont = read_infos (socket_service, userdatas)) == FALSE)
|
||||
return cont;
|
||||
|
||||
/* FIN DU PROTOCOLE : Véricifations / ajout dans la liste / affichage */
|
||||
/* FIN DU PROTOCOLE : Vericifations / 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 */
|
||||
/* Boisson preferee */
|
||||
token = strtok_r (NULL, delim, &saveptr);
|
||||
snprintf (infos->prefb, MAXSTRLEN, "%s", token ? token : drink);
|
||||
|
||||
@@ -309,17 +311,17 @@ int initiate (int socket_service, userinfos *infos) {
|
||||
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, "Boisson preferee : [%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];
|
||||
char nick_ok[MAXSTRLEN+1];
|
||||
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);
|
||||
send_infos (socket_service, "@Pseudo deja utilise !\n");
|
||||
printlog (LOG_NOTIFY, "Pseudo deje utilise => %s\n", infos->nom);
|
||||
pthread_mutex_unlock (&mutex_clients);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -329,8 +331,8 @@ int initiate (int socket_service, userinfos *infos) {
|
||||
|
||||
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");
|
||||
"Votre boisson preferee n'est pas disponible sur ce"
|
||||
" serveur !\nVous aurez des Guinness a la place.\n");
|
||||
|
||||
/* Passage en mode non bloquant */
|
||||
fcntl (socket_service, F_SETFL, O_NONBLOCK);
|
||||
@@ -369,13 +371,13 @@ void thread_service (int *sock_serv) {
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printlog (LOG_NOTIFY, "Prêt à recevoir des commandes.\n");
|
||||
printlog (LOG_NOTIFY, "Pret a recevoir des commandes.\n");
|
||||
#endif
|
||||
|
||||
while (cont == TRUE) {
|
||||
memset (commande, 0, MAXSTRLEN + 1);
|
||||
|
||||
/* Lecture des caractères reçus */
|
||||
/* Lecture des caracteres recus */
|
||||
do {
|
||||
sleep (1);
|
||||
nb = read (socket_service, commande, MAXSTRLEN);
|
||||
@@ -384,7 +386,7 @@ void thread_service (int *sock_serv) {
|
||||
if ( (errno == EPIPE) || (nb == 0) ) {
|
||||
cont = FALSE;
|
||||
} else {
|
||||
printlog (LOG_ERROR, "Erreur de connexion réception !\n");
|
||||
printlog (LOG_ERROR, "Erreur de connexion reception !\n");
|
||||
}
|
||||
}
|
||||
} while ( (cont != FALSE) &&
|
||||
@@ -392,7 +394,7 @@ void thread_service (int *sock_serv) {
|
||||
(new_message (old_id) != TRUE) );
|
||||
|
||||
#ifdef DEBUG
|
||||
printlog (LOG_NOTIFY, "Commande reçue.\n");
|
||||
printlog (LOG_NOTIFY, "Commande recue.\n");
|
||||
#endif
|
||||
if (cont == TRUE) {
|
||||
/* Traitement de la commande */
|
||||
@@ -403,7 +405,7 @@ void thread_service (int *sock_serv) {
|
||||
old_id = get_broadcastid ();
|
||||
cont = send_broadcast (socket_service, &infos);
|
||||
#ifdef DEBUG
|
||||
printlog (LOG_ERROR, "Émission broadcast pour %s (id = %ld)\n",
|
||||
printlog (LOG_ERROR, "Emission broadcast pour %s (id = %ld)\n",
|
||||
infos.nom, old_id);
|
||||
#endif
|
||||
}
|
||||
@@ -436,20 +438,30 @@ void install_handler () {
|
||||
|
||||
|
||||
/*
|
||||
* Initialisation générale
|
||||
* Initialisation generale
|
||||
*
|
||||
*/
|
||||
void guinnessd_init (int argc, char *argv[]) {
|
||||
pthread_mutexattr_t mutex_attr;
|
||||
char *cptr;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
install_handler ();
|
||||
|
||||
/* Valeurs par défaut */
|
||||
/* Valeurs par defaut */
|
||||
logfile = stdout;
|
||||
outerr = stderr;
|
||||
|
||||
/* Traitement des paramètres */
|
||||
/* est-ce bien la place pour initialiser des trucs avant le parsing de
|
||||
la ligne de commande ? Eg: la variable d'environnement DRINKS_DIR
|
||||
*/
|
||||
|
||||
if (NULL!=(cptr=getenv("DRINKS_DIR"))) {
|
||||
chemin = xstrdup(cptr);
|
||||
}
|
||||
|
||||
|
||||
/* Traitement des parametres */
|
||||
if (traite_argv (argc, argv) == TRUE) {
|
||||
switch (fork()) {
|
||||
case -1: /* erreur */
|
||||
@@ -458,7 +470,7 @@ void guinnessd_init (int argc, char *argv[]) {
|
||||
case 0: /* le fils */
|
||||
setsid ();
|
||||
break;
|
||||
default: /* le père */
|
||||
default: /* le pere */
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
@@ -466,12 +478,12 @@ void guinnessd_init (int argc, char *argv[]) {
|
||||
/* Lecture du fichier de configuration */
|
||||
load_config ();
|
||||
|
||||
/* Initialisation des sémaphores */
|
||||
/* Initialisation des semaphores */
|
||||
pthread_mutexattr_init (&mutex_attr);
|
||||
pthread_mutex_init (&mutex_broadcast, &mutex_attr);
|
||||
pthread_mutex_init (&mutex_clients, &mutex_attr);
|
||||
|
||||
/* Affectation des paramètres */
|
||||
/* Affectation des parametres */
|
||||
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);
|
||||
@@ -488,7 +500,7 @@ void guinnessd_init (int argc, char *argv[]) {
|
||||
/* Option pour le buffer de logs */
|
||||
setvbuf (logfile, NULL, _IOLBF, 0);
|
||||
|
||||
/* Création de la liste de boissons par défaut*/
|
||||
/* Creation de la liste de boissons par defaut*/
|
||||
add_elt (&drinks_list, "guinness");
|
||||
|
||||
if (! chemin) chemin = xstrdup (DRINKS_DIR);
|
||||
@@ -504,13 +516,13 @@ void guinnessd_init (int argc, char *argv[]) {
|
||||
int main (int argc, char *argv[]) {
|
||||
int socket_ecoute;
|
||||
int socket_service;
|
||||
int lg_adresse = sizeof (struct sockaddr_in);
|
||||
socklen_t lg_adresse = sizeof (struct sockaddr_in);
|
||||
struct sockaddr_in adresse;
|
||||
pthread_t pthread_id;
|
||||
|
||||
guinnessd_init (argc, argv);
|
||||
|
||||
/* Installation de l'écoute du serveur */
|
||||
/* Installation de l'ecoute du serveur */
|
||||
if ( (socket_ecoute = install_server (port, adr_ip, NULL)) == -1) {
|
||||
printlog (LOG_ERROR, "Impossible d'installer le service.\n");
|
||||
return -1;
|
||||
@@ -548,21 +560,21 @@ int main (int argc, char *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Ici connexion acceptée */
|
||||
printlog (LOG_NOTIFY, "Connexion acceptée...\n");
|
||||
/* Ici connexion acceptee */
|
||||
printlog (LOG_NOTIFY, "Connexion acceptee...\n");
|
||||
|
||||
/* Lancement d'une activité de traitement */
|
||||
/* Lancement d'une activite 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");
|
||||
printlog (LOG_ERROR, "Erreur creation thread de service.\n");
|
||||
close (socket_service);
|
||||
}
|
||||
/* fflush (logfile); */
|
||||
sleep (2);
|
||||
}
|
||||
|
||||
printlog (LOG_NOTIFY, "Arrêt du serveur demandé.\n");
|
||||
printlog (LOG_NOTIFY, "Arret du serveur demande.\n");
|
||||
/* fflush (logfile); */
|
||||
close (socket_ecoute);
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ typedef struct userinfos {
|
||||
int port;
|
||||
int admin;
|
||||
int cold;
|
||||
int comm[2]; /* Pas encore utilisé */
|
||||
int comm[2]; /* Pas encore utilise */
|
||||
} userinfos;
|
||||
|
||||
|
||||
pthread_mutex_t mutex_broadcast;
|
||||
pthread_mutex_t mutex_clients;
|
||||
extern pthread_mutex_t mutex_broadcast;
|
||||
extern pthread_mutex_t mutex_clients;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
187
lists.c
Normal file
187
lists.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* lists
|
||||
* architecture clients/serveur guinness
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "defines.h"
|
||||
#include "xmem.h"
|
||||
#include "lists.h"
|
||||
|
||||
|
||||
void add_elt (Elt **elt, const char *nom) {
|
||||
Elt *e;
|
||||
|
||||
if (*elt == NULL) {
|
||||
*elt = xmalloc ((1) * sizeof (Elt));
|
||||
(*elt)->nom = xstrdup (nom);
|
||||
(*elt)->next = NULL;
|
||||
} else {
|
||||
e = *elt;
|
||||
while (e->next != NULL) e = e->next;
|
||||
e->next = xmalloc ((1) * sizeof (Elt));
|
||||
e = e->next;
|
||||
e->nom = xstrdup (nom);
|
||||
e->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void remove_elt (Elt **elt, const char *nom) {
|
||||
Elt *e = *elt, *p = NULL;
|
||||
int res = FALSE;
|
||||
char *rt, *text ;
|
||||
|
||||
do {
|
||||
if (e != NULL) {
|
||||
if ((rt = strstr (e->nom, SEP)) != NULL) {
|
||||
text = xmalloc (rt - e->nom + 2);
|
||||
memset (text, 0, rt - e->nom + 2);
|
||||
strncpy (text, e->nom, rt - e->nom);
|
||||
#ifdef DEBUG
|
||||
printf ("Comparaison (l) de [%s] avec [%s]\n", text, nom);
|
||||
#endif
|
||||
res = (strcmp (text, nom) == 0);
|
||||
free (text);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printf ("Comparaison (c) de [%s] avec [%s]\n", e->nom, nom);
|
||||
#endif
|
||||
res = (strcmp (e->nom, nom) == 0);
|
||||
}
|
||||
if (res == FALSE) {
|
||||
p = e;
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
} while ( (e != NULL) && (res != TRUE) );
|
||||
|
||||
if (e == NULL) return;
|
||||
if (e == *elt) *elt = e->next;
|
||||
if (p) p->next = e->next;
|
||||
free (e->nom);
|
||||
free (e);
|
||||
}
|
||||
|
||||
|
||||
void remove_elt_n (Elt **elt, int i) {
|
||||
Elt *e = *elt, *p = NULL;
|
||||
int n = 0;
|
||||
|
||||
while ( (e != NULL) && (n != i) ) {
|
||||
n++;
|
||||
e = e->next;
|
||||
}
|
||||
if (e == NULL) return;
|
||||
if (e == *elt) *elt = e->next;
|
||||
if (p) p->next = e->next;
|
||||
free (e->nom);
|
||||
free (e);
|
||||
}
|
||||
|
||||
|
||||
int get_nb_elts (Elt *elt) {
|
||||
Elt *e = elt;
|
||||
int n = 0;
|
||||
|
||||
while (e != NULL) {
|
||||
n++;
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
char *elt_number (Elt *elt, int i) {
|
||||
Elt *e = elt;
|
||||
int n = 0;
|
||||
|
||||
while ( (e != NULL) && (n != i) ) {
|
||||
n++;
|
||||
e = e->next;
|
||||
}
|
||||
if (e == NULL) return NULL;
|
||||
|
||||
return e->nom;
|
||||
}
|
||||
|
||||
|
||||
int exist_elt (Elt *elt, const char *nom) {
|
||||
Elt *e = elt;
|
||||
int res = FALSE;
|
||||
char *rt, *text ;
|
||||
|
||||
do {
|
||||
if (e != NULL) {
|
||||
if ((rt = strstr (e->nom, SEP)) != NULL) {
|
||||
text = xmalloc (rt - e->nom + 2);
|
||||
memset (text, 0, rt - e->nom + 2);
|
||||
strncpy (text, e->nom, rt - e->nom);
|
||||
#ifdef DEBUG
|
||||
printf ("Comparaison (l) de [%s] avec [%s]\n", text, nom);
|
||||
#endif
|
||||
res = (strcmp (text, nom) == 0);
|
||||
free (text);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printf ("Comparaison (c) de [%s] avec [%s]\n", e->nom, nom);
|
||||
#endif
|
||||
res = (strcmp (e->nom, nom) == 0);
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
} while ( (e != NULL) && (res != TRUE) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
char *get_elt (Elt *elt, const char *nom) {
|
||||
Elt *e = elt;
|
||||
int res = FALSE;
|
||||
char *rt, *text ;
|
||||
|
||||
do {
|
||||
if (e != NULL) {
|
||||
if ((rt = strstr (e->nom, SEP)) != NULL) {
|
||||
text = xmalloc (rt - e->nom + 2);
|
||||
memset (text, 0, rt - e->nom + 2);
|
||||
strncpy (text, e->nom, rt - e->nom);
|
||||
#ifdef DEBUG
|
||||
printf ("Comparaison (l) de [%s] avec [%s]\n", text, nom);
|
||||
#endif
|
||||
res = (strcmp (text, nom) == 0);
|
||||
free (text);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
printf ("Comparaison (c) de [%s] avec [%s]\n", e->nom, nom);
|
||||
#endif
|
||||
res = (strcmp (e->nom, nom) == 0);
|
||||
}
|
||||
if (res == FALSE) e = e->next;
|
||||
}
|
||||
} while ( (e != NULL) && (res != TRUE) );
|
||||
|
||||
if (e == NULL) return NULL;
|
||||
|
||||
return e->nom;
|
||||
}
|
||||
|
||||
|
||||
void free_list (Elt **elt) {
|
||||
Elt *e = *elt, *p;
|
||||
|
||||
while (e != NULL) {
|
||||
p = e;
|
||||
e = e->next;
|
||||
free (p->nom);
|
||||
free (p);
|
||||
}
|
||||
*elt = NULL;
|
||||
}
|
||||
23
picoles/canabis
Normal file
23
picoles/canabis
Normal file
@@ -0,0 +1,23 @@
|
||||
.:.
|
||||
:|:
|
||||
.:|:.
|
||||
::|::
|
||||
:. ::|:: .:
|
||||
:|:. .::|::. .:|:
|
||||
::|:. :::|::: .:|:;
|
||||
`::|:. :::|::: .:|::'
|
||||
::|::. :::|::: .::|:;
|
||||
`::|::. :::|::: .::|::'
|
||||
:::|::. :::|::: .::|::;
|
||||
`:::|::. :::|::: .::|::;'
|
||||
`::. `:::|::. :::|::: .::|::;' .:;'
|
||||
`:::.. `:::|::. :::|::: .::|::;' ..::;'
|
||||
`::::::. `:::|::. :::|::: .::|::;' .:::::;'
|
||||
`::::::.`:::|::.:::|::;.::|::;'.:::::;'
|
||||
`::::::.`::|::.::|::.::|::'.:::::;'
|
||||
`:::::::::|:::|:::|::::::::;'
|
||||
``:::::::|:|::|:::::;''
|
||||
`::::::::::;'
|
||||
.:;'' ::: ``::.
|
||||
: : :
|
||||
':`
|
||||
25
picoles/champagne
Normal file
25
picoles/champagne
Normal file
@@ -0,0 +1,25 @@
|
||||
o oo" " "
|
||||
o o o"" "o
|
||||
o" M "
|
||||
"o " o M ""
|
||||
M "o" MoMo
|
||||
"" o o"oo
|
||||
M"o "o" M
|
||||
oMoo" Mo"
|
||||
M"o "M MM
|
||||
"o"o"o M
|
||||
"oM"oMMo
|
||||
M "M M
|
||||
"M"oM"
|
||||
M o
|
||||
o o
|
||||
o
|
||||
" o
|
||||
Mo
|
||||
o
|
||||
"o
|
||||
"o
|
||||
MMo
|
||||
oM"o o
|
||||
oo M"ooM"MoMoo
|
||||
" " "
|
||||
18
picoles/pastis
Normal file
18
picoles/pastis
Normal file
@@ -0,0 +1,18 @@
|
||||
+----------------+
|
||||
|__ _____ |
|
||||
|/~|~~|~~~/~|~~~~|
|
||||
| \| | /\ | |
|
||||
|-555555---- 1 |
|
||||
| 55 111 |
|
||||
| 55 1 11 |
|
||||
| 5555 11 |
|
||||
| 555 11 |
|
||||
| 55 11 |
|
||||
| 55 11 |
|
||||
| 555555 111111 |
|
||||
| |
|
||||
| Le Pastis |
|
||||
| |
|
||||
|================|
|
||||
| |
|
||||
+----------------+
|
||||
22
picoles/steinlager
Normal file
22
picoles/steinlager
Normal file
@@ -0,0 +1,22 @@
|
||||
.sssssssss.
|
||||
.sssssssssssssssssss
|
||||
sssssssssssssssssssssssss
|
||||
ssssssssssssssssssssssssssss
|
||||
@@sssssssssssssssssssssss@ss
|
||||
|s@@@@sssssssssssssss@@@@s|s
|
||||
_______|sssss@@@@@sssss@@@@@sssss|s
|
||||
/ sssssssss@sssss@sssssssss|s
|
||||
/ .------+.ssssssss@sssss@ssssssss.|
|
||||
/ / |...sssssss@sss@sssssss...|
|
||||
| | |.......sss@sss@ssss......|
|
||||
| | |..........s@ss@sss.......|
|
||||
| | |...........@ss@..........|
|
||||
\ \ |............ss@..........|
|
||||
\ '------+...........ss@...........|
|
||||
\________ .........................|
|
||||
|.........................|
|
||||
/...........................\
|
||||
|.............................|
|
||||
|.......................|
|
||||
|...............|
|
||||
|
||||
41
pint.h
Normal file
41
pint.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* pint
|
||||
* architecture clients/serveur guinness
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GUINNESS_SERVER_PINT
|
||||
#define GUINNESS_SERVER_PINT
|
||||
|
||||
char *pinte =
|
||||
" .____,ooo____.\n"
|
||||
" ,d#MMMMMMMMMMMMMMMMMM#o.\n"
|
||||
" |MMMMMMMMMMMMMMMMMMMMMMMM\n"
|
||||
" |MMMMMMMMMMMMMMMMMMMMMMMM\n"
|
||||
" |MMMMMMMMMMMMMMMMMMH#*#**\n"
|
||||
" |M'\"\"\"\"\"\"\"\"\"\"\"\"\"'`\n"
|
||||
" |M.\n"
|
||||
" `ML\n"
|
||||
" HP ##o#\n"
|
||||
" |L TMP]\n"
|
||||
" M . *&' . `\n"
|
||||
" |, |dL.?-\\.~b \\:^ |\n"
|
||||
" `| ` ` ' `` ,\n"
|
||||
" H `\n"
|
||||
" |.\n"
|
||||
" `| |\n"
|
||||
" M ,'\n"
|
||||
" | |\n"
|
||||
" |, |\n"
|
||||
" || |\n"
|
||||
" J' |\n"
|
||||
" M. J|\n"
|
||||
" HM\\\\ -':|\n"
|
||||
" `\"=+\\&#HMH#*??v/''\n"
|
||||
" `\"\"\"\"`\"\"\n";
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
54
printlog.c
Normal file
54
printlog.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* printlog
|
||||
* architecture clients/serveur guinness
|
||||
* Thomas Nemeth / Arnaud Giersch -- le 23 aout 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#ifdef SunOS
|
||||
#include <sys/varargs.h>
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "defines.h"
|
||||
#include "printlog.h"
|
||||
|
||||
|
||||
extern FILE *outerr;
|
||||
extern FILE *logfile;
|
||||
|
||||
|
||||
void printlog (log_level loglevel, const char *format, ...) {
|
||||
va_list ap;
|
||||
FILE *stream = logfile;
|
||||
time_t now;
|
||||
struct tm *today;
|
||||
char date_time[MAXSTRLEN];
|
||||
|
||||
va_start (ap, format);
|
||||
|
||||
switch (loglevel) {
|
||||
case LOG_NOTIFY:
|
||||
stream = logfile;
|
||||
break;
|
||||
case LOG_ERROR:
|
||||
stream = outerr;
|
||||
break;
|
||||
default:
|
||||
stream = outerr;
|
||||
break;
|
||||
}
|
||||
|
||||
time (&now);
|
||||
today = localtime (&now);
|
||||
memset (date_time, 0, MAXSTRLEN);
|
||||
strftime (date_time, MAXSTRLEN - 1, "%a %d %b %Y %T", today);
|
||||
fprintf (stream, "guinnessd: %s - ", date_time);
|
||||
vfprintf (stream, format, ap);
|
||||
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* printlog
|
||||
* architecture clients/serveur guinness
|
||||
* Thomas Nemeth / Arnaud Giersch -- le 23 août 2001
|
||||
* Thomas Nemeth / Arnaud Giersch -- le 23 aout 2001
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
297
tools.c
Normal file
297
tools.c
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* tools
|
||||
* Creation et manipulation de sockets
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "defines.h"
|
||||
#include "xmem.h"
|
||||
#include "tools.h"
|
||||
|
||||
/*
|
||||
* Ouverture d'une socket de type flot de donnees
|
||||
*
|
||||
* creation d'une socket serveur : port != 0
|
||||
*
|
||||
*/
|
||||
int ouvre_socket (int port, char *adr_ip, struct sockaddr_in *ptr_adresse) {
|
||||
int desc_soc;
|
||||
int lg_adresse = sizeof (struct sockaddr_in);
|
||||
int lg_linger = sizeof (struct linger);
|
||||
struct sockaddr_in adresse;
|
||||
struct linger ling;
|
||||
|
||||
/*
|
||||
* Creation de la socket
|
||||
*
|
||||
*/
|
||||
if ( (desc_soc = socket (AF_INET, SOCK_STREAM, 0) ) == -1) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Ne peut pas ouvrir la socket de connexion.\n");
|
||||
#endif
|
||||
perror (__FILE__ " socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Affectation des options
|
||||
*
|
||||
*/
|
||||
if (port != 0) {
|
||||
int opt = 1;
|
||||
if (setsockopt (desc_soc, SOL_SOCKET,
|
||||
SO_REUSEADDR, &opt, sizeof (int) ) == -1) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Impossible de positionner REUSEADDR.\n");
|
||||
#endif
|
||||
perror (__FILE__ " setsockopt -- REUSEADDR");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ling.l_onoff = 0;
|
||||
ling.l_linger = 0;
|
||||
if (setsockopt (desc_soc, SOL_SOCKET, SO_LINGER, &ling, lg_linger) == -1) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Impossible de positionner LINGER.\n");
|
||||
#endif
|
||||
perror (__FILE__ " setsockopt -- LINGER");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preparation de l'adresse d'attachement
|
||||
*
|
||||
*/
|
||||
memset (&adresse, 0, sizeof (adresse) );
|
||||
adresse.sin_family = AF_INET;
|
||||
if (adr_ip) {
|
||||
struct in_addr ia;
|
||||
|
||||
if (inet_aton(adr_ip, &ia)) {
|
||||
adresse.sin_addr = ia;
|
||||
} else {
|
||||
struct hostent *h;
|
||||
|
||||
h = gethostbyname(adr_ip);
|
||||
if (!h) {
|
||||
fprintf (stderr, "Adresse %s inconnue.\n", adr_ip);
|
||||
return -1;
|
||||
}
|
||||
memcpy (&adresse.sin_addr.s_addr, h->h_addr, h->h_length);
|
||||
}
|
||||
} else
|
||||
adresse.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
adresse.sin_port = htons (port);
|
||||
|
||||
/*
|
||||
* Demande d'attachement de la socket
|
||||
*
|
||||
*/
|
||||
if (bind (desc_soc, (struct sockaddr*) &adresse, lg_adresse) == -1) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr,
|
||||
"Ne peut donner de nom a la socket de connexion.\n"
|
||||
"Attendez quelques minutes avant de relancer.\n");
|
||||
#endif
|
||||
perror (__FILE__ " bind");
|
||||
close (desc_soc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recuperation de l'adresse effective d'attachement
|
||||
*
|
||||
*/
|
||||
if (ptr_adresse != NULL)
|
||||
getsockname (desc_soc, (struct sockaddr *) ptr_adresse, &lg_adresse);
|
||||
|
||||
return desc_soc;
|
||||
}
|
||||
|
||||
|
||||
int connect_server (const char *machine, int port) {
|
||||
struct hostent *serveur;
|
||||
struct sockaddr_in adresse_serveur, adresse_client;
|
||||
int socket_client;
|
||||
|
||||
/* Recherche de la machine ou se trouve le serveur */
|
||||
if ( (serveur = gethostbyname (machine) ) == NULL) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Machine %s inconnue...\n", machine);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Creation et attachement de la socket du client --
|
||||
* port quelconque => 0
|
||||
*/
|
||||
if ( (socket_client = ouvre_socket
|
||||
(0, NULL, (struct sockaddr_in *) &adresse_client)) == -1) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Creation de la socket du client impossible.\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Preparation de l'adresse du serveur */
|
||||
adresse_serveur.sin_family = AF_INET;
|
||||
adresse_serveur.sin_port = htons (port);
|
||||
memcpy (&adresse_serveur.sin_addr.s_addr,
|
||||
serveur->h_addr, serveur->h_length);
|
||||
|
||||
/* Demande de connexion au serveur */
|
||||
if (connect (socket_client, (struct sockaddr *) &adresse_serveur,
|
||||
sizeof (adresse_serveur) ) == -1) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Impossible de se connecter au serveur.\n");
|
||||
#endif
|
||||
perror (__FILE__ " connect");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return socket_client;
|
||||
}
|
||||
|
||||
|
||||
int install_server (int port, char *adr_ip, struct sockaddr_in *ecoute) {
|
||||
int socket_ecoute;
|
||||
|
||||
/* Ouverture de la socket */
|
||||
if ( (socket_ecoute = ouvre_socket (port, adr_ip, ecoute)) == -1) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Creation de la socket du serveur impossible.\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Declaration d'ouverture du service */
|
||||
if (listen (socket_ecoute, 10) == -1) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Impossible d'enregistrer le service.\n");
|
||||
#endif
|
||||
perror (__FILE__ " listen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return socket_ecoute;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fonction de reception de donnees
|
||||
*
|
||||
*/
|
||||
int read_infos (int socket_data, char *infos) {
|
||||
int nb;
|
||||
|
||||
/* SSIZE_MAX = 2147483647 */
|
||||
memset (infos, 0, MAXSTRLEN);
|
||||
nb = read (socket_data, infos, MAXSTRLEN - 1);
|
||||
|
||||
if ( (nb == -1) || (nb == 0) ) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Erreur de connexion reception !\n");
|
||||
#endif
|
||||
if ( (errno == EPIPE) || (nb == 0) ) return FALSE; /* cont = FALSE; */
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("Recu : [%s] lg = %d/%d\n", infos, strlen (infos), nb);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fonction d'emisson de donnees
|
||||
*
|
||||
*/
|
||||
int send_infos (int socket_data, const char *infos) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("Emission de : %s [%d]\n", infos, strlen (infos));
|
||||
#endif
|
||||
|
||||
if (write (socket_data, (void *) infos, strlen (infos) + 1) == -1) {
|
||||
/* Erreur : plus de socket ! */
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Erreur de connexion emission !\n");
|
||||
#endif
|
||||
if (errno == EPIPE) return FALSE; /*cont = FALSE;*/
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Emission ok !\n");
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void get_sock_infos (int sock, char **nom, char **adr, int *prl, int *prd) {
|
||||
struct sockaddr_in name;
|
||||
#ifdef OpenBSD
|
||||
int namelen;
|
||||
#else
|
||||
socklen_t namelen;
|
||||
#endif
|
||||
struct hostent *machine;
|
||||
|
||||
/* Initialisations en cas d'echecs */
|
||||
*nom = NULL;
|
||||
*adr = NULL;
|
||||
*prd = 0;
|
||||
|
||||
/* Infos locales (port) */
|
||||
namelen = sizeof (name);
|
||||
if (getsockname (sock, (struct sockaddr *) &name, &namelen) == 0)
|
||||
*prl = ntohs (name.sin_port);
|
||||
else {
|
||||
perror ("getsockname() ");
|
||||
*prl = 0;
|
||||
}
|
||||
|
||||
/* Port et adresse IP distants */
|
||||
namelen = sizeof (name);
|
||||
if (getpeername (sock, (struct sockaddr *) &name, &namelen) != 0) {
|
||||
#ifdef DEBUG
|
||||
perror ("Erreur de recuperation d'information sur pair !\n"
|
||||
"getpeername() ");
|
||||
#else
|
||||
perror ("Impossible d'obtenir les infos distantes ");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
*adr = xstrdup (inet_ntoa (name.sin_addr));
|
||||
*prd = ntohs (name.sin_port);
|
||||
|
||||
/* Nom de machine distante */
|
||||
machine = gethostbyaddr ((char *)&name.sin_addr,
|
||||
sizeof name.sin_addr, name.sin_family);
|
||||
if (machine == NULL) {
|
||||
#ifdef DEBUG
|
||||
perror ("Erreur de recuperation de nom de pair.\n"
|
||||
"gethostbyaddr() ");
|
||||
fprintf (stderr, "Adresse : %s (%s)\tFamille : %d (2 == AF_INET)\n",
|
||||
*adr, (char *)&name.sin_addr, name.sin_family);
|
||||
#else
|
||||
perror ("Impossible d'obtenir le nom d'hote distant ");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
*nom = xstrdup (machine->h_name);
|
||||
}
|
||||
2
tools.h
2
tools.h
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* tools
|
||||
* Création et manipulation de sockets
|
||||
* Creation et manipulation de sockets
|
||||
* Thomas Nemeth -- le 15 juin 2001
|
||||
*
|
||||
*/
|
||||
|
||||
31
xmem.c
Normal file
31
xmem.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* xmem
|
||||
* architecture clients/serveur guinness : gestion memoire
|
||||
* Thomas Nemeth -- le 24 aout 2001
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "xmem.h"
|
||||
|
||||
|
||||
void *xmalloc (size_t taille) {
|
||||
void *ret = malloc (taille);
|
||||
if (ret == NULL) {
|
||||
perror ("malloc() ");
|
||||
exit (-1);
|
||||
} else
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *xstrdup (const char *chaine) {
|
||||
char *ret = strdup (chaine);
|
||||
if (ret == NULL) {
|
||||
perror ("strdup() ");
|
||||
exit (-1);
|
||||
} else
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user