Comment servir des pintes de Guinness "over Internet" ;)
Reprise/Fork d'un très ancien code d'un pilier de f.m.b.l : http://tnemeth.free.fr/projets/guinness-server.html
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
446 lines
13 KiB
446 lines
13 KiB
/* |
|
* 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"); |
|
}
|
|
|