123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- /*
- * 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;
- }
|