commit
7ccb979c33
2 changed files with 224 additions and 0 deletions
@ -0,0 +1,2 @@
|
||||
shell: shell.c |
||||
gcc -Wall -pedantic --extra-warnings -std=c99 -o $@ $^
|
@ -0,0 +1,222 @@
|
||||
/* 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; |
||||
} |
Loading…
Reference in new issue