Created
September 15, 2017 17:24
-
-
Save phongngtuan/f02535be4f7f362477ef0c1716f3abf4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <string.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <fcntl.h> | |
| #define READ_END 0 | |
| #define WRITE_END 1 | |
| int tokenize(char *line, char *sep, char *argv[][2000],char **redirect_in, char **redirect_out) { | |
| int index = 0; | |
| int stage = 0; | |
| char *token = strtok(line, sep); | |
| while (token != NULL) { | |
| if (strcmp(token, ">") == 0) { | |
| token = strtok(NULL, sep); | |
| (*redirect_out) = token; | |
| } | |
| else if (strcmp(token, "<") == 0) { | |
| token = strtok(NULL, sep); | |
| (*redirect_in) = token; | |
| } | |
| else if (strcmp(token, "|") == 0) { | |
| argv[stage][index] = 0; | |
| index = 0; | |
| stage++; | |
| } | |
| else { | |
| argv[stage][index] = token; | |
| index++; | |
| } | |
| token = strtok(NULL, sep); | |
| } | |
| argv[stage][index] = 0; | |
| return stage + 1; | |
| } | |
| int main() { | |
| int pid1 = -1; | |
| int pid2 = -1; | |
| int pipefd[2]; | |
| char line[2000]; | |
| size_t bufsize = 2000; | |
| const char sep[50] = " "; | |
| char *buffer = line; | |
| int chars; | |
| //read a line | |
| while((chars = getline(&buffer, &bufsize, stdin)) != -1) { | |
| char *argv[2][2000]; | |
| line[chars-1] = '\0'; | |
| char* redirect_in; | |
| char* redirect_out; | |
| int index = 0; | |
| int command = 0; | |
| int stages = tokenize(line, sep, argv[command], &redirect_in, &redirect_out); | |
| printf("\nyash$ "); | |
| //piping | |
| if (stages > 1) { | |
| //happens in parent | |
| if (pipe(pipefd) == -1) { | |
| fprintf(stderr, "failed to created pipe\n"); | |
| return -1; | |
| } | |
| } | |
| //actual forking | |
| //second command optionally | |
| if (stages > 1) { | |
| pid2 = fork(); | |
| if (pid2 == -1) { | |
| fprintf(stderr, "Could not fork process\n"); | |
| return -1; | |
| } else if (pid2 == 0) { | |
| //child process 2 | |
| //redirection output | |
| if (redirect_out != NULL) { | |
| int fd = open(redirect_out, O_WRONLY|O_CREAT|O_TRUNC, 0666); | |
| dup2(fd, 1); | |
| close(fd); | |
| } | |
| //2nd command always reads from pipe | |
| if (dup2(pipefd[READ_END], STDIN_FILENO) == -1) { | |
| fprintf(stderr, "dup2 failed: cannot read from pipe"); | |
| return -1; | |
| } | |
| close(pipefd[READ_END]); | |
| close(pipefd[WRITE_END]); | |
| execvp(argv[1][0], &argv[1][0]); | |
| //child process 2 ends here | |
| fprintf(stderr, "Ooops\n"); | |
| return -1; | |
| } | |
| } | |
| //first command | |
| pid1 = fork(); | |
| if (pid1 == -1) { | |
| fprintf(stderr, "Could not fork process\n"); | |
| return -1; | |
| } else if (pid1 == 0) { | |
| // child process | |
| //redirection input | |
| if (redirect_in != NULL) { | |
| int fd = open(redirect_in, O_RDONLY, 0666); | |
| dup2(fd, STDIN_FILENO); | |
| close(fd); | |
| } | |
| if (stages <= 1) { | |
| //redirection to output file | |
| if (redirect_out != NULL) { | |
| int fd = open(redirect_out, O_WRONLY|O_CREAT|O_TRUNC, 0666); | |
| dup2(fd, 1); | |
| close(fd); | |
| } | |
| } else { | |
| //write to pipe | |
| if (dup2(pipefd[WRITE_END], STDOUT_FILENO) == -1) { | |
| fprintf(stderr, "dup2 failed: cannot write to pipe"); | |
| return -1; | |
| } | |
| close(pipefd[READ_END]); | |
| close(pipefd[WRITE_END]); | |
| } | |
| execvp(argv[0][0], &argv[0][0]); | |
| //child process 1 ends here | |
| fprintf(stderr, "Ooops\n"); | |
| return -1; | |
| } | |
| //closing both end because parent doesn't need pipes | |
| close(pipefd[READ_END]); | |
| close(pipefd[WRITE_END]); | |
| wait(&pid1); | |
| wait(&pid2); | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment