/* * commands * architecture clients/serveur guinness * Thomas Nemeth -- le 15 juin 2001 * */ #include #include #include #include #include #include #include #include #include #include #include #include #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"); }