0

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
# :(
Community
  • 1
  • 1
Daniel
  • 2,435
  • 5
  • 26
  • 40

3 Answers3

1

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:~$ 
Eric Urban
  • 3,671
  • 1
  • 18
  • 23
  • Thanks, was there a secondary problem I missed? – Eric Urban Mar 09 '13 at 06:12
  • Infelicities — like the `for` loop finding the newline from `fgets()`, or the odd parentheses around `(child = fork());`, or `exit(1);` and `exit(EXIT_SUCCESS)` (inconsistency) — could perhaps be mentioned. It might be better to report an error if the `execvp()` returns. It would be more conventional to print `arg[0]` before `arg[1]`, but it isn't an insuperable issue. The code might note the return value from `wait()`, and maybe use the exit status of the child to control its own exit status. Otherwise, I don't see any problems. – Jonathan Leffler Mar 09 '13 at 06:18
0

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));
}
Barath Ravikumar
  • 5,658
  • 3
  • 23
  • 39
0

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].

md5
  • 23,373
  • 3
  • 44
  • 93