I am trying to exec() a call to grep inside of my C program. I am looking for the number of occurrences of a string pattern in a given file, which can be achieved with:
$ grep -e my_string -F my_file.txt -c
Which gives a number output as expected, such as:
5
However, what I hoped would be equivalent seems to be having some difficulties. The following code:
char *arg_list[] = {"-e", "my_string", "-F", "my_file.txt", "-c", "\0"};
int pid;
if ((pid = fork()) == 0) {
if (execvp("grep", arg_list) < 0)
perror("execvp");
}
Results in:
my_file.txt:5
-e: : No such file or directory
There are two issues. First, I just want the number-- not the file in which it is found. Second, I'm not sure why it is trying to assert that the -e flag needs to be a file. If I switch around the argument list to be:
char *arg_list[] = {"-F", "my_file.txt", "-e", "my_string", "-c", "\0"};
Then I get back:
my_file.txt:5
-F: : No such file or directory
I'm not sure where to start looking for why this is happening. I'm also not sure why the output of the grep call from the command-line is just a number, but the exec()'d grep call outputs both the filename and number.
Any help would be appreciated! Thank you.
EDIT:
Solution: include the program name in the argument list, or simply use the system() call. Also, RTFM.
You have two problems (insert JWZ quote about regular expressions here):
The first argument in the array passed exec
gets passed in as argv[0]
to the new executable. Ordinarily, this is the name of the executable, and it's what programs use to figure out their own name. So you're telling grep that its name is -e
, and its arguments are my_string -F my_file.txt -c ""
. It's not getting the -e
argument like you might expect, so it misinterprets its arguments and gives you an error.
You're not properly NULL-terminating the array of arguments to exec
. The last argument must be a literal NULL
, not a string "\0"
. That string is an empty string, but it's not a null pointer.