I have a purpose for creating a Linux shell in C. I am currently stuck in implementing redirects and connections. The code I have is below. The main () parses user input. If the command is built in, then this command is executed. Otherwise, tokenized input is passed to execute () (I know that I should probably put inline commands in my own function).
What executes () does is loop through the array. If he meets <, >or |, he must take appropriate action. The first thing I try to work correctly is the pipeline. I'm definitely doing something wrong because I can't get it to work even on one pipe. For example, an I / O example:
/home/ad/Documents> ls -l | grep sh
|: sh: No such file or directory
|
My idea was to get each of the directions and work with pipelines only in one case, and then, having made the function recursive, I can hope to use several redirects / channels in one command line. For example, I could do program1 < input1.txt > output1.txtor ls -l | grep sh > output2.txt.
I was hoping that someone could point out my mistakes in trying to contact and maybe offer some pointers on how to approach the case where the user enters multiple redirects / pipes.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
int MAX_PATH_LENGTH = 1024;
int BUF_LENGTH = 1024;
char * delims = " \n";
const int PIPE_READ = 0;
const int PIPE_WRITE = 1;
void execute(char **argArray){
char **pA = argArray;
int i = 0;
while(*pA != NULL) {
if(strcmp(argArray[i],"<") == 0) {
printf("<\n");
}
else if(strcmp(argArray[i],">") == 0) {
printf(">\n");
}
else if(strcmp(argArray[i],"|") == 0) {
int fds[2];
pipe(fds);
pid_t pid;
if((pid = fork()) == 0) {
dup2(fds[PIPE_WRITE], 1);
close(fds[PIPE_READ]);
close(fds[PIPE_WRITE]);
char** argList;
memcpy(argList, argArray, i);
execvp(argArray[0], argArray);
}
if((pid = fork()) == 0) {
dup2(fds[PIPE_READ], 0);
close(fds[PIPE_READ]);
close(fds[PIPE_WRITE]);
execvp(argArray[i+1], pA);
}
close(fds[PIPE_READ]);
close(fds[PIPE_WRITE]);
wait(NULL);
wait(NULL);
printf("|\n");
}
else {
if(pid == 0){
execvp(argArray[0], argArray);
printf("Command not found.\n");
}
else
wait(NULL);*/
}
*pA++;
i++;
}
}
int main () {
char path[MAX_PATH_LENGTH];
char buf[BUF_LENGTH];
char* strArray[BUF_LENGTH];
getcwd(path, MAX_PATH_LENGTH);
printf("%s> ", path);
fflush(stdout);
while(1) {
fgets(buf, BUF_LENGTH, stdin);
char *tokenPtr = NULL;
int i = 0;
tokenPtr = strtok(buf, delims);
if(strcmp(tokenPtr, "exit") == 0){
exit(0);
}
else if(strcmp(tokenPtr, "cd") == 0){
tokenPtr = strtok(NULL, delims);
if(chdir(tokenPtr) != 0){
printf("Path not found.\n");
}
getcwd(path, MAX_PATH_LENGTH);
}
else if(strcmp(tokenPtr, "pwd") == 0){
printf("%s\n", path);
}
else {
while(tokenPtr != NULL) {
strArray[i++] = tokenPtr;
tokenPtr = strtok(NULL, delims);
}
execute(strArray);
}
bzero(strArray, sizeof(strArray));
printf("%s> ", path);
fflush(stdout);
}
}