commit 7ccb979c3348b5a34a66ce9c37e18a09306d516c Author: Fabien Givors Date: Sun Oct 28 18:56:06 2012 +0100 soumission initiale diff --git a/TP-4/Makefile b/TP-4/Makefile new file mode 100644 index 0000000..6617c63 --- /dev/null +++ b/TP-4/Makefile @@ -0,0 +1,2 @@ +shell: shell.c + gcc -Wall -pedantic --extra-warnings -std=c99 -o $@ $^ diff --git a/TP-4/shell.c b/TP-4/shell.c new file mode 100644 index 0000000..c4dda32 --- /dev/null +++ b/TP-4/shell.c @@ -0,0 +1,222 @@ +/* Copyright (C) 2012 Fabien Givors + * 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 + * . + * + */ + +#define _BSD_SOURCE +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +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; +}