#include #include #include #include #include #include #include #include #include #include #include #include static int error; static int status=0; static int inout[2]; /* * cwd contains the current working directory. */ char cwd[MAXPATHLEN+1]; typedef int (*builtin_cmd)(int, char **); struct builtin { const char *name; builtin_cmd func; }; #define BIN(n) { #n, builtin_ ## n } int builtin_cd(int argc, char **argv) { /* body of cd builtin command */ /* add your code here */ if(argc < 2 || argc > 2){ printf("Error, cd needs 1 arguments"); }else{ status = chdir(argv[1]); } return(status); } int builtin_exit(int argc, char **argv) { /* body of exit builtin command */ /* add your code here */ exit(0); return(0); } int builtin_status(int argc, char **argv) { /* body of the status builtin command */ /* add your code here */ printf("Status of last command is: %d\n", status); return(0); } static struct builtin builtins[] = { BIN(cd), BIN(exit), BIN(status), { NULL } }; /* * run_builtin handles setting up the handlers for your builtin commands * * It accepts the array of strings, and tries to match the first argument * with the builtin mappings defined in the builtins[]. * Returns 0 if it did not manage to find builtin command, or 1 if args * contained a builtin command */ static int run_builtin(char **args) { int argc; struct builtin *b; for (b = builtins; b->name != NULL; b++) { if (strcmp(b->name, args[0]) == 0) { for (argc = 0; args[argc] != NULL; argc++) /* NOTHING */; error = b->func(argc, args); printf("Run builtin\n"); return (1); } } return (0); } void sigint_handler(int signum) { if (signum == SIGINT) { // Need to transmit signal to fg job? printf("\n^C caught\n"); } else { perror("sigint_handler: Unsupported signal caught"); } } static int run_command(char **args, int argsNb, int background) { char * arguments[argsNb]; char cmd[strlen(args[0])]; strcpy (cmd, args[0]); int parentPid; int status; int i; for(i = 0; i < argsNb; i++){ arguments[i] = malloc(sizeof(char)*strlen(args[i])); arguments[i] = args[i]; } arguments[argsNb] = malloc(sizeof(NULL)); //useful? arguments[argsNb] = NULL; if (!run_builtin(args)){ printf("Run command\n"); if(fork() == 0){ if(background){ printf("Process %d started\n", getpid()); } status = execvp (cmd, arguments); }else{ parentPid = getpid(); if(background){ if(fork() == 0){ }else{ wait(NULL); printf("Process %d done\n", getpid()+1); } }else{ wait(NULL); } } } return(0); } static char * parseword(char **pp) { char *p = *pp; char *word; for (; isspace(*p); p++) /* NOTHING */; word = p; for (; strchr(" \t;&|><\n", *p) == NULL; p++) /* NOTHING */; *pp = p; return (p != word ? word : NULL); } static int redirect(char* dest, char **args, int argsNb, int bg, int* pip){ char *filename; filename = parseword(&dest); //creating fd for redirection int fdDest = open(filename, O_CREAT, 0744); fdDest = open(filename, O_WRONLY); if(fdDest==-1){ printf("Error opening file\n"); return(-1); } else { printf("Redirection to %s (fd:%d)\n", filename, fdDest); } //saving stdout fd int fdStdout = dup(1); //redirecting to new fd dup2(fdDest,1); run_command(args, argsNb, bg); //close & restore close(fdDest); dup2(fdStdout, 1); return(0); } static int pipline(char **args, int argsNb,int bg, int pip0, int pip1, char *pipeArgs){ printf("in piplien fun\n"); //saving stdout fd int fdStdout = dup(1); if(pip0!=-1 && pip1==-1){ //there's something to read printf("now reading from pipe\n"); //parse pipeArgs an give them to run command //run_command(pipeArgs, argsNb, bg); printf("got from pipe: %s\n", pipeArgs); } if(pip1!=-1){ // now redirect output to pipe printf("now start writing to pipe\n"); dup2(pip1,1); printf("------pipe starts here\n"); run_command(args, argsNb, bg); int res = read(pip0, pipeArgs, sizeof(pipeArgs)); //read from pipe if (res == -1) return (error); else printf("ok: reading from pipe\n"); printf("------pipe ends here\n"); //restore close(pip1); dup2(fdStdout,1); printf("writing back to stdout\n"); } printf("exit of piplien fun\n"); return(0); } static int * readArgs(char* input, char **args, int argsNb, int bg, int* pip){ FILE *file; char *filename = parseword(&input); // open file in read mode file = fopen(filename, "r"); if(file == (FILE*) NULL){ printf("Error, impossible to open file %s in read mode!\n", filename); return 1; } //saving stdin fd int fdStdin = dup(0); //redirecting to new fd dup2(file, 0); run_command(args, argsNb, bg); //close & restore close(file); dup2(fdStdin, 0); return(0); } static int process(char *line) { int ch, ch2; char *p = line, *word; char *curr; char *args[100], **narg; char *output; char pipeArgs[100]; int pip[2]; int fd=-1, mode; int argsNb = 0; pip[0]=-1; pip[1]=-1; newcmd: inout[0] = STDIN_FILENO; inout[1] = STDOUT_FILENO; newcmd2: narg = args; *narg = NULL; for (;;) { if (*p == 0 && ch==0) break; if (p != line) p++; word = parseword(&p); ch = *p; *p = 0; if (word != NULL) { *narg++ = word; *narg = NULL; argsNb++; } nextch: /* * Here you should put your code for processing the commands * Up to this point, pointer word points to the next word, * ch points to the first character after the word * You should process according to what is in the ch. * For example, use switch(). Next example will skip whitespaces * and detect the redirection of the standard output. * */ switch (ch) { case ' ': case '\t': break; case '>': //execute command and redirect output redirect(++p,args, argsNb, 0, pip);//file is next argument output is execution of args[0] fd=-1; break; case '<': readArgs(++p, args, argsNb, 0, pip); //(++p);//gives arguments for call fd=-1; break; case '|': curr = args[0]; if(*(++p)== '|'){//execute and check status of first command if(pipline(args, argsNb,0, fd, -1, pipeArgs)==0) ++p; //do not execute next command fd=-1; } else {// pipe pipe(pip); //create new pipe pair fd=pip[0]; //upcoming func should read from fd pipline(args, argsNb,0, pip[0], pip[1], pipeArgs); } break; case '&': if(*(++p)== '&'){//execute and check status of first command if(pipline(args, argsNb,0, fd, -1, pipeArgs)!=0) ++p; } else //run in bg pipline(args, argsNb, 0, fd, -1, pipeArgs); //run_command(args, argsNb, 1); fd=-1; break; case '\n': printf("found commande: %s\n", *args); pipline(args, argsNb, 0, fd, -1, pipeArgs); fd=-1; break; default: printf("default entered\n"); }; } return(0); } int main(void) { char line[1000]; int position = 0; /* Catching program interrupt signal, C-c */ signal(SIGINT, SIG_IGN); signal(SIGINT, sigint_handler); do { #ifdef __GNU_LIBRARY__ getcwd(cwd, MAXPATHLEN); #else getwd(cwd); #endif position = strlen(cwd); if (position > MAXPATHLEN - 2) position = MAXPATHLEN - 2; cwd[position] = '>'; cwd[position+1] = ' '; cwd[position+2] = 0; fputs(cwd, stdout); char *res = fgets(line, sizeof(line), stdin); if (res == NULL) return (error); process(line); } while (1); return (error); }