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.

commands.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. * commands
  3. * architecture clients/serveur guinness
  4. * Thomas Nemeth -- le 15 juin 2001
  5. *
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <errno.h>
  11. #include <signal.h>
  12. #include <pthread.h>
  13. #include <fcntl.h>
  14. #include <sys/types.h>
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. #include <string.h>
  18. #include <strings.h>
  19. #include "config.h"
  20. #include "defines.h"
  21. #include "xmem.h"
  22. #include "tools.h"
  23. #include "printlog.h"
  24. #include "lists.h"
  25. #include "broadcast.h"
  26. #include "drinks.h"
  27. #include "clients.h"
  28. #include "guinnessd.h"
  29. #include "commands.h"
  30. extern FILE *logfile;
  31. extern int online;
  32. extern char *admin_passwd;
  33. extern char *chemin;
  34. extern Elt *clients_list;
  35. extern Elt *drinks_list;
  36. /* Signification des champs de commandes:
  37. * NOM AIDE ARGS ADM INTRV FCT
  38. */
  39. cmdslst cmds_srv[] = {
  40. {"help", "cette page d'aide", FALSE, FALSE, FALSE, f_help},
  41. {"quit", "quitter", FALSE, FALSE, FALSE, f_quit},
  42. {"list", "liste des clients connectes", FALSE, FALSE, FALSE, f_list},
  43. {"blist", "liste des boissons disponibles", FALSE, FALSE, FALSE, f_bevr},
  44. {"round", "tournee generale (boisson en option ou preferee)",
  45. TRUE, FALSE, FALSE, f_turn},
  46. {"cold", "la guinness est servie a - de 10C, sinon entre 12 et 15",
  47. FALSE, FALSE, FALSE, f_cold},
  48. {"msg", "message a tous les clients", TRUE, FALSE, FALSE, f_mesg},
  49. {"infos", "renvoie les infos du serveur", TRUE, FALSE, FALSE, f_info},
  50. {"nick", "change de pseudo", TRUE, FALSE, FALSE, f_nick},
  51. {"123456789", "nombre de verres a recevoir (boisson en option ou "
  52. "preferee)", FALSE, FALSE, TRUE, f_glas},
  53. {"admin", "passer en mode administration", TRUE, FALSE, FALSE, f_sadm},
  54. {"33", "arreter le serveur", FALSE, TRUE, FALSE, f_shut},
  55. {"add", "ajoute un utilisateur dans la liste des habitues",
  56. TRUE, TRUE, FALSE, f_addu},
  57. {"del", "enleve un utilisateur de la liste des habitues",
  58. TRUE, TRUE, FALSE, f_delu},
  59. {"rldb", "recharge la liste des boissons", FALSE, TRUE, FALSE, f_rldb},
  60. {"save", "sauve la liste des habitues", FALSE, TRUE, FALSE, f_save},
  61. {"load", "charge la liste des habitues", FALSE, TRUE, FALSE, f_load},
  62. {NULL, NULL, FALSE, FALSE, FALSE, NULL}
  63. };
  64. int security_ok (cmdslst cmd, userinfos infos) {
  65. return ( (cmd.adm == FALSE) ||
  66. ( (cmd.adm == TRUE) && (infos.admin == TRUE) ) );
  67. }
  68. int reply (int socket_service, char *commande, userinfos *infos) {
  69. int i, cont = TRUE, found = FALSE;
  70. /* Tout d'abord, on remplace \n par \0 ! */
  71. for (i = 0 ; i <= strlen (commande) ; i++)
  72. if ( (commande[i] == '\n') || (commande[i] == '\r') ) {
  73. commande[i] = 0;
  74. }
  75. if (strncmp (commande, "admin ", 6) != 0)
  76. printlog (LOG_NOTIFY, "Commande de %s : [%s] (%d)\n",
  77. infos->nom,
  78. commande,
  79. strlen (commande) );
  80. else {
  81. #ifdef DEBUG
  82. printlog (LOG_NOTIFY, "Commande de %s : [%s]\n", infos->nom, commande);
  83. #else
  84. printlog (LOG_NOTIFY, "Commande de %s : admin XXXXXX\n", infos->nom);
  85. #endif
  86. }
  87. fflush (logfile);
  88. for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
  89. int cmp = -1;
  90. cmdslst cmd = cmds_srv[i];
  91. if ( (cmd.interv) &&
  92. ( (strlen (commande) == 1) ||
  93. (commande[1] == ' ') ) ) {
  94. cmp = strchr (cmd.nom, commande[0]) == NULL ? -1 : 0;
  95. } else {
  96. if (cmd.args)
  97. cmp = strncmp (commande, cmd.nom, strlen (cmd.nom) );
  98. else
  99. cmp = strcmp (commande, cmd.nom);
  100. }
  101. if ( (cmp == 0) && (security_ok (cmd, *infos) == TRUE ) ) {
  102. found = TRUE;
  103. printlog (LOG_NOTIFY, "Commande reconnue : %s\n", cmd.nom);
  104. cont = cmd.fct (socket_service, commande, infos);
  105. break;
  106. }
  107. }
  108. if (! found)
  109. send_infos (socket_service, "Don't flood me with stupidities !\n");
  110. return cont;
  111. }
  112. int send_servercmds (int socket_service) {
  113. char *data;
  114. char cmd[MAXSTRLEN];
  115. int size = 0;
  116. int i;
  117. for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
  118. memset (cmd, 0, MAXSTRLEN);
  119. if (cmds_srv[i].adm)
  120. snprintf (cmd, MAXSTRLEN - 1, "*%s\n", cmds_srv[i].nom);
  121. else if (cmds_srv[i].interv)
  122. snprintf (cmd, MAXSTRLEN - 1, "+%s\n", cmds_srv[i].nom);
  123. else
  124. snprintf (cmd, MAXSTRLEN - 1, "%s\n", cmds_srv[i].nom);
  125. size += strlen (cmd);
  126. }
  127. data = xmalloc ((size + 1) * sizeof (char));
  128. strcpy (data, "");
  129. for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
  130. memset (cmd, 0, MAXSTRLEN);
  131. if (cmds_srv[i].adm)
  132. snprintf (cmd, MAXSTRLEN - 1, "*%s\n", cmds_srv[i].nom);
  133. else if (cmds_srv[i].interv)
  134. snprintf (cmd, MAXSTRLEN - 1, "+%s\n", cmds_srv[i].nom);
  135. else
  136. snprintf (cmd, MAXSTRLEN - 1, "%s\n", cmds_srv[i].nom);
  137. strcat (data, cmd);
  138. }
  139. return send_infos (socket_service, data);
  140. }
  141. int f_help (int socket_service, const char *commande, userinfos *infos) {
  142. char *data;
  143. char ligne[MAXSTRLEN];
  144. int size = 0;
  145. int i;
  146. memset (ligne, 0, MAXSTRLEN);
  147. size = strlen ("Commandes (precedees du caractere de commande) :\n");
  148. for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
  149. if (security_ok (cmds_srv[i], *infos) == TRUE) {
  150. if (cmds_srv[i].args)
  151. snprintf (ligne, MAXSTRLEN - 1, " %s [opts]\t: %s\n",
  152. cmds_srv[i].nom, cmds_srv[i].aide);
  153. else
  154. snprintf (ligne, MAXSTRLEN - 1, " %s%s: %s\n",
  155. cmds_srv[i].nom,
  156. strlen (cmds_srv[i].nom) < 5 ? "\t\t" : "\t",
  157. cmds_srv[i].aide);
  158. size += strlen (ligne);
  159. }
  160. }
  161. data = xmalloc ((size + 1) * sizeof (char));
  162. strcpy (data, "Commandes (precedees du caractere de commande) :\n");
  163. for (i = 0 ; cmds_srv[i].nom != NULL ; i++) {
  164. if (security_ok (cmds_srv[i], *infos) == TRUE) {
  165. if (cmds_srv[i].args)
  166. snprintf (ligne, MAXSTRLEN - 1, " %s [opts]\t: %s\n",
  167. cmds_srv[i].nom, cmds_srv[i].aide);
  168. else
  169. snprintf (ligne, MAXSTRLEN - 1, " %s%s: %s\n",
  170. cmds_srv[i].nom,
  171. strlen (cmds_srv[i].nom) < 5 ? "\t\t" : "\t",
  172. cmds_srv[i].aide);
  173. strcat (data, ligne);
  174. }
  175. }
  176. return send_infos (socket_service, data);
  177. }
  178. int f_quit (int socket_service, const char *commande, userinfos *infos) {
  179. return FALSE;
  180. }
  181. int f_list (int socket_service, const char *commande, userinfos *infos) {
  182. char *data;
  183. int cont;
  184. pthread_mutex_lock (&mutex_clients);
  185. data = list_clients ();
  186. pthread_mutex_unlock (&mutex_clients);
  187. cont = send_infos (socket_service, data);
  188. free (data);
  189. return cont;
  190. }
  191. int f_bevr (int socket_service, const char *commande, userinfos *infos) {
  192. char *data;
  193. int size = 0;
  194. int i;
  195. int cont;
  196. size = strlen ("Boissons disponibles :\n");
  197. for (i = 0 ; i < get_nb_elts (drinks_list) ; i++) {
  198. size += strlen (elt_number (drinks_list, i) );
  199. size += strlen ("\n");
  200. }
  201. data = xmalloc ((size + 1) * sizeof (char));
  202. strcpy (data, "Boissons disponibles :\n");
  203. for (i = 0 ; i < get_nb_elts (drinks_list) ; i++) {
  204. strcat (data, elt_number (drinks_list, i) );
  205. strcat (data, "\n");
  206. }
  207. cont = send_infos (socket_service, data);
  208. free (data);
  209. return cont;
  210. }
  211. int f_cold (int socket_service, const char *commande, userinfos *infos) {
  212. int cont;
  213. if (infos->cold == TRUE) {
  214. infos->cold = FALSE;
  215. cont = send_infos (socket_service, "Temperature normale.\n");
  216. } else {
  217. infos->cold = TRUE;
  218. cont = send_infos (socket_service, "Temperature fraiche (10C).\n");
  219. }
  220. return cont;
  221. }
  222. int f_turn (int socket_service, const char *commande, userinfos *infos) {
  223. int cont = TRUE;
  224. char *breuv = NULL;
  225. if (strlen (commande) > 5) breuv = xstrdup (commande+6);
  226. printlog (LOG_NOTIFY, "Breuvage pour tournee : %s\n",
  227. breuv ? breuv : "prefere");
  228. if ( ( (breuv != NULL) && (exist_elt (drinks_list, breuv) == TRUE) ) ||
  229. (breuv == NULL) ) {
  230. if (! broadcast (TOURNEE, infos->nom, breuv) )
  231. cont = send_infos (socket_service, "Erreur de transmission !\n");
  232. } else
  233. cont = send_infos (socket_service, "Boisson non disponible !\n");
  234. free (breuv);
  235. return cont;
  236. }
  237. int f_mesg (int socket_service, const char *commande, userinfos *infos) {
  238. int cont = TRUE;
  239. if (! broadcast (MESSAGE, infos->nom, commande + 4) )
  240. cont = send_infos (socket_service, "Erreur de transmission !\n");
  241. return cont;
  242. }
  243. int f_info (int socket_service, const char *commande, userinfos *infos) {
  244. int cont = TRUE;
  245. char *data;
  246. if (strlen (commande) == 5) {
  247. data = xmalloc (MAXSTRLEN + 1);
  248. snprintf (data, MAXSTRLEN, "guinnessd - v %s (compilation %s : %s)\n",
  249. VERSION, OS_TYPE, COMPIL_DATE);
  250. } else
  251. data = infos_client (infos->admin, commande + 6);
  252. cont = send_infos (socket_service, data);
  253. free (data);
  254. return cont;
  255. }
  256. int f_nick (int socket_service, const char *commande, userinfos *infos) {
  257. int cont = TRUE, rename_ok;
  258. char *new_nick, *old_nick;
  259. old_nick = xstrdup (infos->nom);
  260. new_nick = xstrdup (commande + 5);
  261. pthread_mutex_lock (&mutex_clients);
  262. rename_ok = rename_client (infos, new_nick);
  263. pthread_mutex_unlock (&mutex_clients);
  264. if (rename_ok) {
  265. char texte[MAXSTRLEN + 1];
  266. snprintf (texte, MAXSTRLEN, "%s s'appelle maintenant %s.\n",
  267. old_nick, new_nick);
  268. if (! broadcast (MESSAGE, NULL, texte) )
  269. cont = send_infos (socket_service, "Erreur de transmission !\n");
  270. } else {
  271. cont = send_infos (socket_service, "Pseudo deja utilise !\n");
  272. }
  273. free (old_nick);
  274. free (new_nick);
  275. return cont;
  276. }
  277. int f_glas (int socket_service, const char *commande, userinfos *infos) {
  278. int i, nb, cont = TRUE;
  279. char *breuv;
  280. char *data;
  281. if (strlen (commande) > 2)
  282. breuv = xstrdup (commande + 2);
  283. else
  284. breuv = xstrdup (infos->prefb);
  285. printlog (LOG_NOTIFY, "Breuvage desire : %s\n", breuv);
  286. data = drinks_get (breuv);
  287. nb = atoi (commande);
  288. for (i = 0 ; i < nb ; i++)
  289. if ( (cont = send_infos (socket_service, data) ) == FALSE) break;
  290. free (data);
  291. free (breuv);
  292. return cont;
  293. }
  294. int f_sadm (int socket_service, const char *commande, userinfos *infos) {
  295. int cont = TRUE;
  296. if ( (admin_passwd) && (strcmp (admin_passwd, commande + 6) == 0) ) {
  297. char message[] = "Vous etes maintenant ADMINISTRATEUR.\n"
  298. "Nouvelles commandes :";
  299. char *data;
  300. int size = 0, i;
  301. infos->admin = TRUE;
  302. for (i = 0 ; cmds_srv[i].nom != NULL ; i++)
  303. if (cmds_srv[i].adm) size += 1 + strlen (cmds_srv[i].nom);
  304. size += strlen (message);
  305. data = xmalloc ((size + 1) * sizeof (char));
  306. memset (data, 0, size);
  307. strcpy (data, message);
  308. for (i = 0 ; cmds_srv[i].nom != NULL ; i++)
  309. if (cmds_srv[i].adm) {
  310. strcat (data, " ");
  311. strcat (data, cmds_srv[i].nom);
  312. }
  313. cont = send_infos (socket_service, data);
  314. free (data);
  315. } else {
  316. infos->admin = FALSE;
  317. cont = send_infos (socket_service,
  318. "Vous n'etes PLUS administrateur.\n");
  319. }
  320. return cont;
  321. }
  322. int f_shut (int socket_service, const char *commande, userinfos *infos) {
  323. online = FALSE;
  324. send_infos (socket_service, "Arret en cours...\n");
  325. return FALSE;
  326. }
  327. int f_rldb (int socket_service, const char *commande, userinfos *infos) {
  328. free_list (&drinks_list);
  329. add_elt (&drinks_list, "guinness");
  330. if (! chemin) chemin = xstrdup (DRINKS_DIR);
  331. drinks_list_files (chemin);
  332. drinks_display_list ();
  333. return send_infos (socket_service, "Liste des boissons rechargee...\n");
  334. }
  335. int f_addu (int socket_service, const char *commande, userinfos *infos) {
  336. return send_infos (socket_service, "Fonction non implementee...\n");
  337. }
  338. int f_delu (int socket_service, const char *commande, userinfos *infos) {
  339. return send_infos (socket_service, "Fonction non implementee...\n");
  340. }
  341. int f_save (int socket_service, const char *commande, userinfos *infos) {
  342. return send_infos (socket_service, "Fonction non implementee...\n");
  343. }
  344. int f_load (int socket_service, const char *commande, userinfos *infos) {
  345. return send_infos (socket_service, "Fonction non implementee...\n");
  346. }