1

I have developed the following code: main:

#include<stdio.h>
#include<unistd.h>

int main()
{
    char *const args[] = {"/bin/ls", "> test.txt 2>&1", NULL};
    execvp(args[0], args);

    /* If this is reached execvp failed. */

    perror("execvp");
    return 0;
}

I need to execute this shell command : /bin/ls > test.txt 2>&1 but I have got an error:

$gcc -o main main.c 
$ vi main.c
$ gcc -o main main.c 
$ ./main 
/bin/ls: cannot access '> test.txt 2>&1': No such file or directory
$ 

Why it returns /bin/ls: cannot access '> test.txt 2>&1': No such file or directory ? Have you a solution to fix that ?

2 Answers 2

4

no that doesn't work. Redirecting is a function of your shell. And by using one of the exec functions, you bypass the shell completely. So you need to handle redirection yourself.

int out = open("test.txt", O_WRONLY | O_CREAT, 0644);
dup2(out, 1);
dup2(out, 2);
close(out);
execvp(args[0], args);

but drop the second item in args first.

This will open the output file and duplicate it to stdin and stdout like the shell would do. Finally close the original descriptor as that is no longer needed.

I left out error checking, but you should definitely add that of course.

Sign up to request clarification or add additional context in comments.

2 Comments

First, you're missing the mode argument, so your open() call should be something like open("test.txt", O_WRONLY | O_CREAT, 0644);. And in the spirit of completeness, a production-quality implementation of this would perform error checking on all calls, and dup() and save at least stderr so if excevp() fails an error message can be written to the original stderr.
@AndrewHenle, I did indeed forgot the mode argument. I edited the answer to include it.
1

Redirections are interpreted by the shell. But execvp() does not run a shell. It runs an executable. You can do what is done internally by system() by calling "sh -c":

#include<stdio.h>
#include<unistd.h>

int main(void)
{
    char *const args[] = {"/bin/sh", "-c", "/bin/ls > test.txt 2>&1", NULL};
    execvp(args[0], args);

    /* If this is reached execvp failed. */

    perror("execvp");
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.