#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
static char line[1024];
//counting the number of words in a char**
int countWords (char** words) {
int count = 0;
//until we are not reaching NULL we continue
while (words[count] != NULL) {
count++;
}
return count;
}
//parsing a string
char** parseString (char* cmd) {
char ** res = NULL;
char * p = strtok (cmd, " ");
int nbrSpace = 0;
while (p) {
res = realloc (res, sizeof (char*) * ++nbrSpace);
if (res == NULL){//memory allocation problem
exit (-1);
}
res[nbrSpace-1] = p;
p = strtok (NULL, " ");
}
//adding extra last element with value NULL for execvp function
res = realloc (res, sizeof (char*) * (nbrSpace+1));
res[nbrSpace] = NULL;
return res;
}
//
void merge (char* fileName, char *fileName1) {
int fd = open(fileName, O_RDWR);
char c;
while (read(fd, &c, 1) > 0) { //going at the end of the file
}
//int fd = open(fileName, O_RDWR |O_APPEND);
//char c;
char retour[] = "\n";
char diese[] = "#";
write (fd, retour, strlen(retour));
for (int i = 0; i < 80; i++) {
if (write (fd, diese, strlen(diese)) == -1) {
perror("Details : ");
}
}
write (fd, retour, strlen(retour));
int fd1 = open(fileName1, O_RDWR);
while(read(fd1, &c, 1) > 0) {
write(fd, &c, sizeof(c));
}
close(fd1);
close(fd);
}
void dumshShell (int argc, char ** argv) {
if (argc > 0) {
if (strcmp(argv[0], "exit") == 0) {
exit(0);
}
else if (strcmp(argv[0], "cd") == 0) {
if (argc > 1){chdir(argv[1]);} else{}
}
else {
pid_t pid = fork();
if (pid == -1) {
perror("Details :");
return;
} else if (pid == 0) {
execvp(argv[0], argv);
exit(0);
} else {
//waiting for child to terminate
int status;
waitpid(pid, &status, 0);
return;
}
}
}
}
void redirection (int typeStream, int fd, char* fileName) {
if (typeStream == 1) { //in stdout
//erasing the file or creating it if it doesn't exist
int streamFile = open(fileName, O_CREAT|O_RDWR|O_APPEND, S_IRUSR | S_IWUSR);
char c;
//reading stream and writing in the file
while (read(fd, &c, 1) > 0) {
write(streamFile, &c, sizeof(c));
}
close(streamFile);
}
else if (typeStream == 2) { //in stderr
int streamFile = open(fileName, O_CREAT|O_RDWR|O_APPEND, S_IRUSR | S_IWUSR);
char c;
//reading stream and writing in the file
while (read(fd, &c, 1) > 0) {
write(streamFile, &c, sizeof(c));
}
close(streamFile);
}
else{}
}
//function for >1
void redir1Stream (int argc, char ** argv, char* fileName, char* mkFile) {
int stdout[2];
int stderr[2];
//creating the pipes
if (pipe(stdout) == -1 || pipe(stderr) == -1) {
perror("pipe : ");
}
//creating first child
int pid = fork();
if (pid < 0) {
perror("fork :");
}
if(pid == 0) { //first child
//creating second child
int pid1 = fork();
if (pid1 < 0) {
perror("fork1 : ");
}
if(pid1 == 0) { //second child
close(stderr[1]);
close(stdout[1]);
redirection(1, stdout[0], fileName);
exit(0);
} else {
close(stderr[1]);
close(stdout[1]);
redirection(2, stderr[0], mkFile);
exit(0);
}
} else {
close(stdout[0]);
close(stderr[0]);
int saved_stdout = dup(1);
int saved_stderr = dup(2);
dup2(stdout[1], 1);
dup2(stderr[1], 2);
dumshShell(argc, argv);
close(stdout[1]);
close(stderr[1]);
dup2(saved_stdout, 1);
dup2(saved_stderr, 2);
}
close(stdout[0]);
close(stderr[0]);
close(stderr[1]);
close(stdout[1]);
merge(fileName, mkFile);
}
void dumsh (int argc, char** argv) {
char name[] = "/tmp/prefXXXXXX";
int status = mkstemp(name);
int flag = 0;
char* copy = NULL;
if (argc > 0) {
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], ">1") == 0 && i == argc-2) {
copy = malloc(strlen(argv[argc-1])+1);
copy = strcpy(copy, argv[argc-1]);
argv[argc-2] = NULL;
redir1Stream(argc-2, argv, copy, name);
free(copy);
return;
}
}
}
}
int main(int argc, char** argv) {
//reinitializing white color
char white[] = "\033[0;38m$>";
while (1) {
//waiting for user instruction
write(1, white, sizeof(white)-1);
fflush(NULL);
if (!fgets(line, 1024, stdin))
return 0;
//getting rid of the \n character at the end of line
line[strlen(line)-1] = '\0';
char **cmd = parseString(line);
int n = countWords(cmd);
dumsh(n, cmd);
}
return 0;
}