I'm writing my own custom shell, and as a part of my project, when the program reads either "<" or ">" character from user input, it needs to redirect stdin and stdout to a custom file. I wrote a function for this below. The part where I'm struggling is that even though I wrote the code for input and output redirections pretty much in the same manner, output redirection seems to work as expected, while input redirection does not. See the code below:
void inOutReDirector(char **toks, char *inputFile, char *outputFile, int *fd0, int *fd1, int *in, int *out) {
fflush(0);
for (int i = 0; toks[i] != NULL; i ) {
if (strcmp(toks[i], "<") == 0) {
toks[i] = NULL;
strcpy(inputFile, toks[i 1]);
toks[i 1] = NULL;
*in = 1;
}
if (strcmp(toks[i], ">") == 0) {
toks[i] = NULL;
strcpy(outputFile, toks[i 1]);
toks[i 1] = NULL;
*out = 1;
}
}
//input redirection
if (*in == 1) {
if ((*fd0 = open(inputFile, O_RDONLY, 0)) < 0) {
printf("Couldn't open input file: %s", strerror(errno));
exit(1);
}
dup2(*fd0, STDIN_FILENO);
close(*fd0);
}
//output redirection
if (*out == 1) {
if ((*fd1 = creat(outputFile, 0644)) < 0) {
printf("Couldn't open output file: %s", strerror(errno));
exit(1);
}
dup2(*fd1, STDOUT_FILENO);
close(*fd1);
}
}
And here is how I call this function from my main:
int main() {
char *toks[STD_INPUT_SIZE] = {0};
int fd0, fd1, in = 0, out = 0;
char inputFile[64], outputFile[64];
pid_t pid;
while (1) {
//print prompt
//get user input
pid = fork();
if (pid < 0) {
printf("%s \n", strerror(errno));
exit(1);
}
int stopNeeded = strcmp(toks[0], "exit") == 0;
if (pid == 0 && !stopNeeded) {
pathFinder(toks, shellInput, currentDir); //finding path for execv input
inOutReDirector(toks, inputFile, outputFile, &fd0, &fd1, &in, &out); // I/O redirection
if (execv(shellInput, toks) != 0) {
char *errMsg = strerror(errno);
printf("%s \n", errMsg);
//clean the old contents of toks
for (int i = 0; i < STD_INPUT_SIZE; i) {
free(toks[i]);
toks[i] = NULL;
}
exit(1);
}
}
if (pid > 0) {
pid_t childPid = waitpid(pid, NULL, 0);
(void) childPid;
}
}
return 0;
}
And here is an example of output redirection from my terminal screen
$ ls > output.txt
$
This creates "output.txt" file and prints the result inside this file in the current directory.
And here is an example of input redirection from my terminal screen
$ cat < output.txt
$
Input redirection does not work correctly. It prints the prompt and waits for the input instead of showing the contents of output.txt in my terminal.
I appreciate any help you can provide in advance!
CodePudding user response:
The problem should be on this line of the function inOutReDirector
if (strcmp(toks[i], ">") == 0) {
should be changed to
else if (strcmp(toks[i], ">") == 0) {
When toks[i]
is equal to "<", toks[i]
will be set to NULL above, this line calling strcmp will cause SIGSEGV, so the child process will exit, and the subsequent execv
will not be executed.