execvp - ls: fts_open: No such file or directory

2019-02-15 19:20发布

问题:

I'm currently struggling with this error. I'm writing a shell emulator, using fork() for executing a command using execvp();. Almost every command I try to parse to my shell is working perfectly, except for ls without arguments. If I try to execute ls -lah, everything works, but a simple ls won't, receiving the following error:

ls: fts_open: No such file or directory

Here is a snippet of my code: (just the essential)

pid = fork();
      if (pid==0)
      {
        puts("CHILD");
        puts(args[0]);
        puts(args[1]);
        printf("%d\n", strlen(args[1]));
        args[2] = NULL;
        execvp(args[0], args);
      }
      else wait(NULL);
      puts("BACK TO PARENT");
    }

and here is the output for ls:

ls
CHILD
ls

0
ls: fts_open: No such file or directory
BACK TO PARENT

as you can see, args[0] contains ls, args[1] is empty, as there are no arguments, the length of args[1] is 0, but i keep getting the error.

Any idea on what it could be?

EDIT:

Kudos for Jonathan Leffler for finding it out: (also, it seems like it is just an issue on Mac)

The point is that args[1] is not really empty, so, the OS tries to open the '' file, which, obviously, does not exists, and, by what is looks, can't be created, since it is not really a name.

So, Here is what I did: check the len of args[1]. If it is 0, set it to NULL. (just freeing the memory did not really helped)

pid = fork();
      if (pid==0)
      {
        puts("CHILD");
        puts(args[0]);
        puts(args[1]);
        if (strlen(args[1]) == 0)
            args[1] = 0;
        args[2] = NULL;
        execvp(args[0], args);
      }
      else wait(NULL);
      puts("BACK TO PARENT");
    }

回答1:

If there are no more arguments, the pointer should be null, not a non-null pointer to a zero length string.

pid = fork();
if (pid==0)
{
    puts("CHILD");
    puts(args[0]);
    fflush(stdout);
    args[1] = 0;
    execvp(args[0], args);
    fprintf(stderr, "Failed to exec %s\n", args[0]);
    exit(1);
}
else
    wait(NULL);
puts("BACK TO PARENT");

Just out of pure curiosity, I tried this at my command line:

$ ls ''
ls: fts_open: No such file or directory
$

Are you running on a Mac too? (To say I was surprised to see the same message doesn't begin to describe my reaction!) What's more intriguing is that creating a file fts_open doesn't seem to get rid of the error message. Weird behaviour by ls, but in response to an invalid request (there are no file names that are the empty string).



标签: c exec fork execvp