#ifndef shell_main_func #define shell_main_func #include #include #include #include #include #include "main.h" #include "helper_functions.c" #define LSH_RL_BUFSIZE 1024 char *lsh_read_line(void) { int bufsize = LSH_RL_BUFSIZE; int position = 0; char *buffer = malloce(sizeof(char) * bufsize); int c; while (1) { // Read a character c = getchar(); // If we hit EOF, replace it with a null character and return. if (c == EOF || c == '\n') { buffer[position] = '\0'; return buffer; } else { buffer[position] = c; } position++; // If we have exceeded the buffer, reallocate. if (position >= bufsize) { bufsize += LSH_RL_BUFSIZE; buffer = realloc(buffer, bufsize); if (!buffer) { fprintf(stderr, "lsh: allocation error\n"); exit(EXIT_FAILURE); } } } } int cleanup_token(char **parse_args_last_p, int ch_i){ (*parse_args_last_p)[ch_i]='\0'; if((*parse_args_last_p)[ch_i+1]=='\0') return -1; //remove spaces and tabs around sep char int i=ch_i-1; while ((*parse_args_last_p)[i]==' '|| (*parse_args_last_p)[0]=='\t'){ (*parse_args_last_p)[i--]='\0'; } *parse_args_last_p=&(*parse_args_last_p)[ch_i+1]; while((*parse_args_last_p)[0]==' ' || (*parse_args_last_p)[0]=='\t') *parse_args_last_p=&(*parse_args_last_p)[1]; return 0; } char *strtok_cmd(char *token, cmd_t *type){ *type=Stdout; static char* parse_args_last_p; if(token != NULL){ parse_args_last_p=token; } if(parse_args_last_p==NULL){ return NULL; } char *return_char=parse_args_last_p; char in_quote=' '; if(parse_args_last_p != NULL){ int ch_i=0; while(1){ if (parse_args_last_p[ch_i] == '\0') break; if (in_quote==' ' && (parse_args_last_p[ch_i]=='"' || parse_args_last_p[ch_i]=='\'')){ bool pass_check=true; if(ch_i>0 && parse_args_last_p[ch_i-1]=='\\') pass_check=false; if(pass_check==true){ in_quote=parse_args_last_p[ch_i]; if (parse_args_last_p[ch_i+1] == '\0') break; ch_i++; } } if (in_quote!=' '){ if (parse_args_last_p[ch_i]==in_quote){ bool pass_check=true; if(ch_i>0 && parse_args_last_p[ch_i-1]=='\\') pass_check=false; if (pass_check) in_quote=' '; } } else{ switch (parse_args_last_p[ch_i]){ case ';': if(cleanup_token(&parse_args_last_p, ch_i)!=0) break; return return_char; break; case '|': if(cleanup_token(&parse_args_last_p, ch_i)!=0) break; *type=Pipe; return return_char; break; } } ch_i++; } parse_args_last_p=NULL; } return return_char; } CMD **lsh_split_command(char *line) { int bufsize = sizeof(CMD*), position = 0; CMD **tokens = malloce(bufsize); char *token; cmd_t cmd_type; token = strtok_cmd(line,&cmd_type); while (token != NULL) { tokens[position] = malloce(sizeof(CMD)); tokens[position]->cmd = token; tokens[position]->type = cmd_type; tokens[position]->stdInFd = 0; tokens[position]->next = NULL; if(position>0) tokens[position-1]->next = tokens[position]; position++; if (position * bufsize >= bufsize) { bufsize += sizeof(CMD*); tokens = realloc(tokens, bufsize); if (!tokens) { fprintf(stderr, "lsh: allocation error\n"); exit(EXIT_FAILURE); } } token = strtok_cmd(NULL,&cmd_type); } tokens[position] = NULL; return tokens; } int lsh_launch(char **args, CMD *cmd) { pid_t pid, wpid; int status; int stdOutPipe[2]; pipe(stdOutPipe); if(cmd->type==Pipe){ cmd->next->stdInFd=stdOutPipe[0]; } pid = fork(); if (pid == 0) { // Child process if(cmd->type!=Stdout){ close(stdOutPipe[0]); // close reading end in the child dup2(stdOutPipe[1], 1); // send stdout to the pipe dup2(stdOutPipe[1], 2); // send stderr to the pipe close(stdOutPipe[1]); // this descriptor is no longer needed } if(cmd->stdInFd!=0) dup2(cmd->stdInFd,STDIN_FILENO); if (execvp(args[0], args) == -1) perror("lsh"); exit(EXIT_FAILURE); } else if (pid < 0) { // Error forking perror("lsh"); } else { // Parent process do { wpid = waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); close(stdOutPipe[1]); // close the write end of the pipe in the parent if(cmd->stdInFd!=0) close(cmd->stdInFd); } return 1; } #endif