Skip to content

Instantly share code, notes, and snippets.

@phongngtuan
Created September 15, 2017 17:24
Show Gist options
  • Select an option

  • Save phongngtuan/f02535be4f7f362477ef0c1716f3abf4 to your computer and use it in GitHub Desktop.

Select an option

Save phongngtuan/f02535be4f7f362477ef0c1716f3abf4 to your computer and use it in GitHub Desktop.
#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