Question

I'm trying a write a little program to run grep via execvp. This is basically identical to the problem I had here, but in this case, it only happens when I run grep (as opposed to echo, ls, emacs, etc which all work fine) and I've changed the incorrect wait() (I believe). I've also tried using quotes over the text I want to find

my code:

int main(void) {

  int i;
  char inputprogram[50];
  char vars[50] = "a search.txt";
  printf("input grep\n");
  fflush(stdout);
  fgets(inputprogram,50,stdin);
  for(i = 0; i < 50; i++){
            if(inputprogram [i] == '\n' ){
                inputprogram[i] = 0;
            }
        }
  char *arg [] = {inputprogram, vars , NULL};
  printf(">%s<\n", arg[1]);
  printf(">%s<\n", arg[0]);

  int status = 0;
  pid_t child;

  (child = fork());
  if(child == 0){
    printf("execute\n");
    execvp(inputprogram,  arg);
    exit(1);
  }
  else{
    printf("parent waiting...\n");
    wait(&status);
  }
  return EXIT_SUCCESS;
}

search.txt:

a
b
c
abc

input/output (# is in front of lines I typed, though is not part of the input):

shell> # ./work
input grep
# grep
>a search.txt<
>grep<
parent waiting...
execute
# a;dlghasdf
# go back
# :(
Was it helpful?

Solution

The function execvp expects each argument as a separate argument in the array passed in. You are passing 'vars' as a single argument that has spaces in it. Grep is waiting for input from standard input(the console here) and is searching for lines containing 'a search.txt'. The following program does what you expect.

#include "unistd.h"
int main(void) 
{
  char * executable = "grep";
  char *arg[] = { executable, "a","search.txt", NULL };
  execvp(executable, arg);
  return 0;
}

By passing the searched for string as its own argument, grep treats the next argument in the list as a file to search.

Here is what that program does for me:

ericu@eric-phenom-linux:~$ gcc -o execgrep /home/ericu/execgrep.c 
ericu@eric-phenom-linux:~$ ./execgrep 
a
abc
ericu@eric-phenom-linux:~$ cat search.txt 
c
b
a
abc
ericu@eric-phenom-linux:~$ 

Modifying the sample program to mirror what you are currently doing

#include "unistd.h"
int main(void) 
{
   char * executable = "grep";
   char *arg[] = { executable, "a search.txt", NULL };
   execvp(executable, arg);
   return 0;
}

Results in a program that expects input from standard input.

ericu@eric-phenom-linux:~$ echo -e "Review the man page from proper usage of execvp.a search.txt\nThis line does not show up in the output" | ./execgrep 
Review the man page from proper usage of execvp.a search.txt
ericu@eric-phenom-linux:~$ 

OTHER TIPS

After you get the exit status of your launched app

wait(&status);

Interpret it , using the WIFEXITED macro ,

if ( WIFEXITED (status) )
    printf("App exit status = %u ",WEXITSTATUS(status));
}

Before treating input/output, make sure that your program works. This is a small program to reproduce the error:

int main(void) 
{
  char *arg[] = { "grep", "a search.txt", NULL };
  execvp("/bin/grep", arg);
  return EXIT_SUCCESS;
}

However, without the first string of arg, it seems to work:

int main(void) 
{
  char *arg[] = { "a search.txt", NULL };
  execvp("/bin/grep", arg);
  return EXIT_SUCCESS;
}

However, I don't know why it would depend on the value of argv[0].

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top