Skip to content
Extraits de code Groupes Projets

ReadPassword

  • Cloner avec SSH
  • Cloner avec HTTPS
  • Intégrer
  • Partager
    L'extrait de code peut être consulté sans aucune authentification.
    Rédigé par Thomas "Oxymore" Kowalski
    readpasswd.c 3,80 Kio
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #include <string.h>
    #include <errno.h>
    
    /*
    @requires pwd, un tableau de char de 17 éléments (16 caractères max + caractère nul)
    @assigns  modifie pwd pour le remplir avec le mot de passe entré
    @ensures  récupère le mot de passe entré par l'utilisateur sur stdin
    		  le mot de passe fait au plus 16 caractères
    		  si une erreur apparaît, la fonction renvoie -1, sinon elle renvoie la taille du mot de passe
    */
    int readpasswd(char pwd[17])
    {
    	char* ttypath = 
    			ttyname(0) ? ttyname (0) :
    			ttyname(1) ? ttyname (1) : 
    			ttyname(2);
    
    	int j;
    	for (j = 0; j < 17; j++)
    		pwd[j] = '\0';
    
    	printf("Mot de passe : ");
    
    	/* On desactive la sortie */
    	system("stty raw -echo");
    
    	int i = 0;
    	char c[1];
    
    	FILE *f;
    
    	if(!(f = fopen(ttypath, "w+")))
    	{
    		printf("Impossible d'ouvrir le terminal en lecture et ecriture : %s\n", strerror(errno));
    		system("stty raw -echo");
    		return -1;
    	}
    
    	int tronque = 1;
    	/* 
    		Ce serait plus naturel de faire "tant que vrai" et de faire break si i >= 15, mais on a dit qu'on voulait pas l'utiliser. 
    		On va bien jusqu'à i = 16 et pas i = 15, parce que sinon on ne peut pas entrer un mot de passe de 16 caractères et le modifier (dès que le seizième caractère est entré, on sort de la boucle)
    		Donc on autorise jusqu'à i = 16, mais si on entre un caractère quand i = 16, on sort de la boucle
    	*/
    	while (i <= 16)
    	{
    		/* On vérifie qu'on peut lire un caractère sur le terminal. */
    		if(!fread(&c, sizeof(char), 1, f))
    		{
    			printf("Impossible de lire un caractere sur le terminal : %s\n", strerror(errno));
    			system("stty raw -echo");
    			return -1;
    		}
    
    		/* Si jamais on a fait nouvelle ligne ou retour chariot, on sort */
    		if (c[0] == '\r' || c[0] == '\n')
    		{
    			tronque = 0;
    			break;
    		}
    
    		/* Si on a fait backspace, on efface un caractere */
    		if (c[0] == 127)
    		{
    			/* On vérifie quand même qu'on a au moins déjà tapé un caractère, sinon on va avoir du mal à effacer quoi que ce soit. */
    			if (i > 0)
    			{
    				/* 
    					On efface le dernier caractère de la chaine. 
    					Comme i donne l'indice du prochain caractère, on doit bien assigner pwd[i - 1] et pas pwd[i] ! 
    				*/				
    				pwd[i - 1] = '\0';
    
    				/* On fait revenir "le curseur dans la chaîne" au caractère d'avant */
    				i--;
    
    				/* 
    					Ecrire \b \b permet de 
    					- Placer le curseur à gauche
    					- Remplacer le dernier caractère (donc un X ici) par un espace
    					- Replacer le curseur à gauche de l'espace pour que le prochain X prenne la place de celui qu'on a effacé.
    				*/
    				if(!fprintf(f, "\b \b"))
    				{
    					printf("Impossible d'effacer le dernier caractère : %s\n", strerror(errno));
    					system("stty raw -echo");
    					return -1;
    				}
    			}
    		}
    		/* Sinon, on ajoute un caractere dans notre chaine mot de passe */
    		else
    		{
    			/* Si on le tableau est rempli, alors on sort. */
    			if (i == 16)
    				break;
    
    			/* On affiche un X quand l'utilisateur tape un caractere. */
    			if(!fprintf(f, "X"))
    			{
    				printf("Impossible d'écrire X sur le terminal : %s\n", strerror(errno));
    				system("stty raw -echo");
    				return -1;
    			}
    			pwd[i] = c[0];
    			i++;	
    		}
    	}
    
    	/* On a fini de lire le mot de passe, on affiche un retour à la ligne dans le terminal. */
    	fprintf(f, "\r\n");
    
    	/* On reactive l'affichage des caracteres tapes */
    	system("stty -raw echo");
    	if (tronque)
    		return 17;
    	else
    		return i;
    }
    
    int main(void)
    {
    	char pass[17];
    	int taille = readpasswd(pass);
    	if(taille == -1)
    	{
    		printf("Erreur lors de la lecture du mot de passe !\n");
    		return EXIT_FAILURE;
    	}
    	else
    	{
    		if (taille == 17)
    		{
    			printf("Attention : le mot de passe a été tronqué !\n");
    			taille = 16;
    		}
    		
    		printf("Mot de passe lu (%d caracteres) :\n", taille);
    		printf("%s", pass);
    		printf("\n");
    	}
    
    	return 0;
    }
    0% Chargement en cours ou .
    You are about to add 0 people to the discussion. Proceed with caution.
    Terminez d'abord l'édition de ce message.
    Veuillez vous inscrire ou vous pour commenter