2021-02-17 22:23:13 +00:00
|
|
|
|
/**
|
|
|
|
|
* @file essential_shell.c
|
|
|
|
|
* @author rick <rick@gnous.eu>
|
|
|
|
|
* @date 2021
|
|
|
|
|
*/
|
|
|
|
|
|
2021-02-20 17:34:43 +00:00
|
|
|
|
#include "vars.h"
|
2021-02-17 22:23:13 +00:00
|
|
|
|
#include "essential_shell.h"
|
2021-02-20 17:34:43 +00:00
|
|
|
|
#include "oui-dire.h"
|
2021-02-17 22:23:13 +00:00
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2021-02-18 16:20:46 +00:00
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
2021-02-21 18:12:12 +00:00
|
|
|
|
#include <errno.h>
|
2021-02-22 14:48:35 +00:00
|
|
|
|
//#include <sys/types.h>
|
|
|
|
|
#include <signal.h>
|
2021-03-05 19:24:28 +00:00
|
|
|
|
#include <sys/wait.h>
|
2021-02-22 14:48:35 +00:00
|
|
|
|
|
2021-03-05 19:24:28 +00:00
|
|
|
|
pid_t pid = 0;
|
2021-02-23 17:23:36 +00:00
|
|
|
|
int exit_code = 0;
|
|
|
|
|
int need_exit = 0;
|
2021-02-17 22:23:13 +00:00
|
|
|
|
|
2021-02-18 16:20:46 +00:00
|
|
|
|
/**
|
2021-02-20 15:53:46 +00:00
|
|
|
|
* native_command(): vérifie si la commande entrée par l’utilisateur
|
|
|
|
|
* est implémenté dans le terminal
|
|
|
|
|
* @command: la commande et ses arguments à vérifier
|
2021-02-18 16:20:46 +00:00
|
|
|
|
*
|
2021-02-20 15:53:46 +00:00
|
|
|
|
* Vérifie si la commande entrée par l’utilisateur est native.
|
|
|
|
|
* Si elle l’est, le programme appelle la fonction pour exécuter la commande
|
|
|
|
|
* en lui passant en paramètre les arguments de la commande.
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 si la commande n’est pas native
|
|
|
|
|
* 1 si la commande est native
|
2021-02-18 16:20:46 +00:00
|
|
|
|
*/
|
2021-02-20 15:53:46 +00:00
|
|
|
|
int native_command(char *command[])
|
2021-02-18 16:20:46 +00:00
|
|
|
|
{
|
2021-02-20 15:53:46 +00:00
|
|
|
|
int ret = 1; /* 0 si commande non native */
|
2021-02-23 17:23:36 +00:00
|
|
|
|
|
2021-02-20 15:55:30 +00:00
|
|
|
|
if (!strcmp(command[0], "cd"))
|
2021-02-23 16:23:02 +00:00
|
|
|
|
change_dir(command);
|
2021-02-23 17:23:36 +00:00
|
|
|
|
else if (!strcmp(command[0], "exit"))
|
|
|
|
|
thus_exit(command);
|
2021-02-24 01:23:21 +00:00
|
|
|
|
else if (!strcmp(command[0], "export"))
|
|
|
|
|
thus_export(command);
|
2021-02-23 17:23:36 +00:00
|
|
|
|
else if (!strcmp(command[0], "ouï-dire") || !strcmp(command[0], "oui-dire")
|
2021-02-20 17:34:43 +00:00
|
|
|
|
|| !strcmp(command[0], "echo"))
|
|
|
|
|
{
|
|
|
|
|
char *tmp = calloc(MAX_LENGTH, sizeof(char));
|
|
|
|
|
int i = 1;
|
|
|
|
|
while (command[i] != NULL)
|
|
|
|
|
{
|
|
|
|
|
strcat(tmp, command[i]);
|
|
|
|
|
*(tmp + strlen(tmp)) = ' ';
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
if (i == 2)
|
|
|
|
|
*(tmp + strlen(tmp) - 1) = '\0';
|
|
|
|
|
echo(tmp);
|
2021-02-24 01:01:22 +00:00
|
|
|
|
free(tmp);
|
2021-02-20 17:34:43 +00:00
|
|
|
|
}
|
2021-02-20 15:53:46 +00:00
|
|
|
|
else
|
|
|
|
|
ret = 0;
|
2021-02-18 16:20:46 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
2021-02-20 15:53:46 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* change_dir(): fonction pour implémenter la commande cd
|
2021-02-23 17:23:36 +00:00
|
|
|
|
* @command: la commande passée avec ses arguments
|
|
|
|
|
*
|
|
|
|
|
* Structure de la commande cd : cd dossier
|
2021-02-20 15:53:46 +00:00
|
|
|
|
*/
|
2021-02-23 16:23:02 +00:00
|
|
|
|
void change_dir(char *command[])
|
2021-02-20 15:53:46 +00:00
|
|
|
|
{
|
2021-02-23 16:23:02 +00:00
|
|
|
|
char *dir = command[1];
|
2021-02-21 18:12:12 +00:00
|
|
|
|
if (chdir(dir) < 0)
|
|
|
|
|
{
|
2021-02-21 19:42:54 +00:00
|
|
|
|
int code = errno;
|
2021-02-23 16:23:02 +00:00
|
|
|
|
char *txt_error = calloc(MAX_LENGTH, sizeof(char));
|
|
|
|
|
strcat(txt_error, command[0]);
|
|
|
|
|
strcat(txt_error, ": ");
|
2021-02-21 18:12:12 +00:00
|
|
|
|
strcat(txt_error, dir);
|
2021-02-21 19:42:54 +00:00
|
|
|
|
error(code, NON_FATAL_ERROR, txt_error);
|
2021-02-23 16:23:02 +00:00
|
|
|
|
free(txt_error);
|
2021-02-21 18:12:12 +00:00
|
|
|
|
}
|
2021-02-20 15:53:46 +00:00
|
|
|
|
}
|
2021-02-21 19:42:54 +00:00
|
|
|
|
|
2021-02-23 17:23:36 +00:00
|
|
|
|
/**
|
|
|
|
|
* thus_exit(): fonction pour implémenter la commande exit
|
|
|
|
|
* @command: la commande passée avec ses arguments
|
|
|
|
|
*
|
|
|
|
|
* Si l’utilisateur ne met pas d’arguments,
|
|
|
|
|
* la valeur 0 sera utilisé par défaut.
|
|
|
|
|
* Cette valeur sera utilisée pour exit_code et
|
|
|
|
|
* need_exit sera mit à 1.
|
|
|
|
|
*/
|
|
|
|
|
void thus_exit(char *command[])
|
|
|
|
|
{
|
|
|
|
|
if (command[1] != NULL)
|
|
|
|
|
exit_code = atoi(command[1]);
|
|
|
|
|
need_exit = 1;
|
|
|
|
|
}
|
2021-02-23 16:23:02 +00:00
|
|
|
|
|
2021-02-24 01:23:21 +00:00
|
|
|
|
void thus_export(char *command[])
|
|
|
|
|
{
|
|
|
|
|
char f = '=';
|
|
|
|
|
char *token = strtok(command[1], &f);
|
|
|
|
|
char *var = token;
|
|
|
|
|
token = strtok(NULL, &f);
|
|
|
|
|
char *val;
|
|
|
|
|
if (token == NULL)
|
|
|
|
|
val = "";
|
|
|
|
|
else
|
|
|
|
|
val = token;
|
|
|
|
|
setenv(var, val, 1);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-05 19:24:28 +00:00
|
|
|
|
void ctrl_c_handler(int signum)
|
2021-02-22 14:48:35 +00:00
|
|
|
|
{
|
2021-03-05 19:24:28 +00:00
|
|
|
|
while (!waitpid(pid, NULL, WNOHANG)) {}
|
|
|
|
|
putchar('\n');
|
2021-02-22 14:48:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-21 19:42:54 +00:00
|
|
|
|
/**
|
|
|
|
|
* error(): gère les erreurs selon leur code et leur type
|
|
|
|
|
* @code: code de l’erreur, voir les différents codes dans le fichier .h
|
|
|
|
|
* @type: NON_FATAL_ERROR pour continuer l’exécution
|
|
|
|
|
* FATAL_ERROR pour stoper le programme
|
|
|
|
|
* @message: message à afficher pour + d’infos ou erreur non implémentée
|
2021-02-23 17:23:36 +00:00
|
|
|
|
*
|
|
|
|
|
* En cas d’erreur fatale, le code d’erreur sera mit dans exit_code
|
|
|
|
|
* et need_exit sera mit à 1.
|
2021-02-21 19:42:54 +00:00
|
|
|
|
*/
|
|
|
|
|
void error(int code, int type, char *message)
|
|
|
|
|
{
|
|
|
|
|
if (code == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* const char *txt_error = strerror(code); */
|
|
|
|
|
if (errno == EINVAL)
|
|
|
|
|
{
|
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case ERR_PIPE_CREATION:
|
|
|
|
|
fprintf(stderr, "Erreur lors de la création des pipes.\n");
|
|
|
|
|
break;
|
|
|
|
|
case ERR_FORK:
|
|
|
|
|
fprintf(stderr, "Le fork a échoué, le processus enfant a été avorté.\n");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if (message == NULL)
|
|
|
|
|
fprintf(stderr, "Erreur inconnue.\n");
|
|
|
|
|
else
|
|
|
|
|
fprintf(stderr, "%s\n", message);
|
|
|
|
|
}
|
|
|
|
|
if (message != NULL)
|
|
|
|
|
fprintf(stderr, "Message complémentaire :\n%s\n", message);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (message != NULL)
|
|
|
|
|
{
|
|
|
|
|
errno = code;
|
|
|
|
|
perror(message);
|
|
|
|
|
}
|
|
|
|
|
/* else
|
|
|
|
|
fprintf(stderr, "%s\n", txt_error); */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == FATAL_ERROR)
|
2021-02-23 17:23:36 +00:00
|
|
|
|
{
|
|
|
|
|
need_exit = 1;
|
|
|
|
|
exit_code = code;
|
|
|
|
|
}
|
2021-02-21 19:42:54 +00:00
|
|
|
|
}
|