#include #include #include #include #include #include #include #include enum command_mode { mode_background, mode_foreground }; struct command{ int argc; char**argv; char* cmdline; enum command_mode mode; }; /* create a command structure from a command line */ struct command* extract_command(char* cmdline) { struct command* c = malloc(sizeof(struct command)); c->argc = 0; c->argv = NULL; c->cmdline = malloc(sizeof(char)*(strlen(cmdline)+1)); strcpy(c->cmdline, cmdline); /* first, let's count the number of parameters */ char* token = strtok(cmdline, " "); while(token) { c->argc++; token = strtok(NULL, " "); } /* strtok modified cmdline, so let's restore it */ strcpy(cmdline, c->cmdline); /* now, extract the parameters */ c->argv = malloc(sizeof(char*) * (c->argc+1)); c->argv[0] = strtok(cmdline, " "); int i; for(i=1; iargc; i++) { c->argv[i] = strtok(NULL, " "); } if(c->argc && strcmp("&", c->argv[c->argc-1]) == 0) { c->argc--; c->mode = mode_background; } else { c->mode = mode_foreground; } c->argv[c->argc] = NULL; return c; } /* execute a command */ void execute_command(struct command* c) { if(c->argc == 0) { /* empty command, nothing to do */ return; } pid_t pid_child = fork(); if(!pid_child) { execvp(c->argv[0], c->argv); /* execvp should not exit except in case of an error */ fprintf(stderr, "Error running command %s: %s\n", c->argv[0], strerror(errno)); exit(EXIT_FAILURE); } else { int status; waitpid(pid_child, &status, 0); } } int main(int argc, char** argv){ do { char *cmdline = NULL; /* print a prompt, and return a buffer that contains the user command */ cmdline = readline("mysh $ "); /* extract the command, and execute it */ struct command* cmd = extract_command(cmdline); execute_command(cmd); if(cmd->argc > 0 && strcmp(cmd->argv[0] , "exit") == 0) { return EXIT_SUCCESS; } /* cleanup */ free(cmd); free(cmdline); cmdline = NULL; } while(1); return EXIT_SUCCESS; }