user1617940
user1617940

Reputation: 31

Why am I having difficulty making execvp in C work?

I need to implement a basic shell in C. One of things I need is to implement a function that has a command and to execute it. my code:

    pID=fork();

    if (pID == 0)
       execvp(tmp[0], tmp);
    else if (pID > 0)
    {
       printf("%d", pID);
       wait(NULL);
    }
    else
      printf("Failed to create proccess \n");

The problem is that no matter what is the command I put in tmp, the program shows me the prompt again, and do nothing except that. For example if I write gedit (in order to open the gedit — a ntpad of Ubuntu), it doesn't open it, or if write ls -a it doesn't show me any output as the terminal of Ubuntu does.

Upvotes: 1

Views: 6759

Answers (3)

manolis manolakis
manolis manolakis

Reputation: 1

execvp() requires full path . If in tmp[0] isnt the full path of your executable file use execv()

execv(tmp[0], tmp);

Upvotes: 0

Adam Rosenfield
Adam Rosenfield

Reputation: 400274

Although you've failed to tell us what you're passing through the tmp variable to execvp, my psychic sense tells me that you forgot to null-terminate your argument list. A NULL argument tells execvp where the last argument is, and if you fail to put in a NULL, it will start reading random garbage off the stack.

If that random garbage points to large strings of non-zero data, it will run out of space to store the supposed arguments to the new process, which is typically a few hundred KB (see this page for some system-specific numbers, as well as various ways of getting your system's maximum arguments size).

When there's too much argument data, the system call execve(2) (called internally by execvp) fails with the error E2BIG.

So to see if this is what's happening to you, check the return value from execvp. If it even returns at all, it failed (if it succeeded, it wouldn't have returned since a new process would be executing!), so check the global value of errno to see why it failed:

if (pID == 0)
{
    execvp(tmp[0], tmp);
    printf("exec failed: %s\n", strerror(errno));
    exit(1);
}

Upvotes: 1

halm
halm

Reputation: 124

execvp should work. As the others mentioned, you really need to show how you populate tmp. That said, I would guess that that's where the error is. tmp needs to be a null terminated array.

#include <stdio.h>
main( int argc, char * argv[] )
{
int    pid = fork;
char * tmp[2];
  memset( tmp, 0, sizeof(tmp) );
  tmp[0] = argv[0];
  if( 0 == pid )
  {
    if( -1 == execvp( tmp[0], tmp ) )
    {
      char errmsg[64];
      snprintf( errmsg, sizeof(errmsg), "exec '%s' failed", tmp[0] );
      perror( errmsg );
    }
  else if( 0 < pid )
  {
    printf("[%d] %s\n", pid, tmp[0]);
    wait(NULL);
  }
  else
  {
    perror("fork failed");
  }
}

Upvotes: 2

Related Questions