447 lines
13 KiB
C
447 lines
13 KiB
C
/*
|
|
* 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");
|
|
}
|