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.

223 lines
4.5 KiB

/* Copyright (C) 2012 Fabien Givors <fabien.givors@chezlefab.net>
* Copyright (C) 2012 Debian Facile
*
* Ce programme est un logiciel libre ; vous pouvez le redistribuer ou le
* modifier suivant les termes de la GNU General Public License telle que
* publiée par la Free Software Foundation ; soit la version 3 de la licence,
* soit (à votre gré) toute version ultérieure.
*
* Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE
* GARANTIE ; pas même la garantie implicite de COMMERCIABILISABILITÉ ni
* d'ADÉQUATION à UN OBJECTIF PARTICULIER. Consultez la GNU General Public
* License pour plus de détails.
*
* Vous devriez avoir reçu une copie de la GNU General Public License en même
* temps que ce programme ; si ce n'est pas le cas, consultez
* <http://www.gnu.org/licenses>.
*
*/
#define _BSD_SOURCE
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
enum cmd_types {
CMD_NULL,
CMD_EXIT,
CMD_CD,
CMD_EXEC,
CMD_FORKANDWAIT,
CMD_FORKANDCONTINUE
};
enum cmd_types get_cmd_type(char* cmd[])
{
if(!cmd[0])
return CMD_NULL;
if(strcmp(cmd[0],"cd")==0)
return CMD_CD;
if(strcmp(cmd[0],"exit")==0)
return CMD_EXIT;
if(strcmp(cmd[0],"exec")==0)
return CMD_EXEC;
{
int i=0;
while(cmd[++i]);
i--;
if(strlen(cmd[i])==1 && cmd[i][0] == '&')
{
free(cmd[i]);
cmd[i]=NULL;
return CMD_FORKANDCONTINUE;
}
}
return CMD_FORKANDWAIT;
}
char** parse_cmd(char* cmd)
{
char** argv = (char**)malloc(128*sizeof(char*));
int np = 0;
for(char* arg = NULL; (arg = strtok_r(cmd, " ",&cmd)); np++)
{
argv[np] = (char*)malloc(sizeof(arg));
strcpy(argv[np], arg);
}
argv[np]=NULL;
return argv;
}
void free_cmd(char** argv)
{
for(int np = 0; argv[np]; np++)
free(argv[np]);
free(argv);
}
void print_prompt(void)
{
char* user = getenv("USER");
char hostname[64];
gethostname(hostname,sizeof(hostname));
char* cwd = get_current_dir_name();
char* home = getenv("HOME");
char* cwd2 = cwd;
if(strstr(cwd,home) == cwd)
{
cwd2+=strlen(home)-1;
cwd2[0]='~';
}
printf("%s@%s:%s$ ", user, hostname, cwd2);
free(cwd);
}
int main(void)
{
char buf[256];
print_prompt();
while(gets(buf))
{
char* buf_temp = buf;
char* cmd = NULL;
while((cmd = strtok_r(buf_temp, ";", &buf_temp)))
{
char** cmd_argv = parse_cmd(cmd);
int cmd_type = get_cmd_type(cmd_argv);
switch(cmd_type)
{
case CMD_NULL:
break;
case CMD_EXIT:
return 0;
case CMD_CD:
{
int r;
if(cmd_argv[1])
r = chdir(cmd_argv[1]);
else
r = chdir(getenv("HOME"));
if(r)
{
printf("cd: ");
switch(errno)
{
case EACCES:
printf("Pas le droit d'aller ici !\n");
break;
case ENOENT:
printf("La destination n'existe pas !\n");
break;
default:
printf("Erreur n°%d.\n", errno);
break;
}
}
}
break;
case CMD_FORKANDWAIT:
{
int f = 0;
int status;
switch(f = fork())
{
case 0:
execvp(cmd_argv[0],cmd_argv);
printf("Échec de l'exécution de la commande %s\n", cmd);
break;
case -1:
printf("Échec du fork.\n");
break;
default:
wait(&status);
}
}
break;
case CMD_FORKANDCONTINUE:
{
int f = 0;
switch(f = fork())
{
case 0:
execvp(cmd_argv[0],cmd_argv);
printf("Échec de l'exécution de la commande %s\n", cmd);
break;
case -1:
printf("Échec du fork.\n");
break;
default:
break;
}
}
break;
case CMD_EXEC:
{
execvp(cmd_argv[0],cmd_argv);
printf("Échec de l'exécution de la commande %s\n", cmd);
}
default:
break;
}
free_cmd(cmd_argv);
}
print_prompt();
}
return 0;
}