DH Kim DH Kim - 3 months ago 22
Bash Question

Linux | Shell implementation in C | redirected file includes the prompt

I'm implementing linux shell in C and seems my output redirection is not working properly. when I run "ls > testFile", I just get an empty prompt while I expect "minishell>", and I found it when opened testFile. why this happen? is this the problem of redirection function itself or functions including redirection? (parse_line or process_cmd)

int main(void) {
char cmdline[MAXLINE];
while (1) {
// print prompt
printf("%s", prompt);
fflush(stdout);

// get user input
if (fgets(cmdline, MAXLINE, stdin) == NULL) {
return 1;
} else {
process_cmd(cmdline);

fflush(stdout);
}
}

return 0;
}

void process_cmd(char *cmdline) {
int argc;
char *argv[MAXARGS];
int status;

argc = parse_line(cmdline, argv);

if (argc == 0) {
return;
}

if (builtin_cmd(argc, argv) == 1) {
int pid = fork();

if (pid == 0) {
argv[argc] = NULL;

if (execvp(argv[0], argv) == -1) {
perror ("Error");
}

printf("%s: command not found.\n", argv[0]);
exit(1);
}
wait(&status);
}
return;
}

int parse_line(char *cmdline, char **argv) {
int count = 0;
int isRedirected = -1;
argv[0] = strtok(cmdline, delimiter);


if (argv[0] == NULL) {
return 0;
}

count++;

while(1) {
argv[count] = strtok(NULL, delimiter);
if (argv[count] == NULL) {
break;
}
count++;
}

// redirection check
for (int index = 0; index < count; index++) {
if ((strcmp(argv[index], ">") == 0)) {
if (argv[index+1] == NULL) {
printf("output file missing.\n");
printf("USAGE: [command] > [target_file_name]\n");
return count;
}
isRedirected = redirect(argv[index+1]);
for ( index = index+2; index != count; index++) {
argv[index-2] = argv[index];
}
argv[count-1] = NULL;
argv[count-2] = NULL;
count = count - 2;
break;
}
}

if (isRedirected > 0) {
reverseRedirected(isRedirected);
}


return count;

}

int redirect(char *redirectionDest) {
int stdOutputFd;
int fd = open(redirectionDest,O_CREAT|O_TRUNC|O_WRONLY,S_IRUSR|S_IWUSR);
if ((stdOutputFd = dup(1)) == -1) {
perror("Error");
return -1;
}
if (dup2(fd, 1) == -1) {
perror("Error");
close(stdOutputFd);
return -1;
}

close(fd);

return stdOutputFd;
}

void reverseRedirected(int fd) {
if (dup2(1, fd) == -1) {
printf("fd dup failed!!\n");
exit(0);
}

return;
}

Answer

You never un-redirect after the command finishes, so the shell's output continues to go to the redirected file descriptor.

Edit:

I also just noticed: your reverseRedirected function (which is improperly called in the redirect function, rather than after the command finishes) has the dup2 arguments in the wrong order.