execve() when used with "which" is not outputting to terminal

97 Views Asked by At

I am attempting to retrieve the path of a command line argument I pass through to a program. e.g

running ./a.out results.txt cat should give me /bin/cat but gives me nothing
running ./a.out results.txt wc should give me /usr/bin/wc but gives me nothing
running ./a.out results.txt sdfasfd results in No such file or directory

basically I am trying to reproduce the "which cat" or "which wc" etc command line. I am running the following test

    void runtest(char **argv)
    {
      char *args[3];
      args[0] = "/usr/bin/which";
      args[1] = argv[2];
      args[2] = NULL;
      printf("EXECUTING \n");
      execve(args[0], args, NULL);
      perror("");
    }

I am however not getting any output in terminal of path. I would appreciate if somebody could advise me why the above does not workhow to retrieve the path for the command/executable passed through to the program based on above test function WITHOUT any new additional functions (I have strict restrictions for my assignment and can only use execve and if I must, access().

Once the path is retrieved I will be using it in another function to actually run the command on the file passed through to program as per ./a.out results.txt cat. I cannot hardcode the path as cat, wc and others dont always share the same Path. Thank you

1

There are 1 best solutions below

1
Thomas On

The manual page execve(2) says:

On Linux, argv and envp can be specified as NULL. In both cases, this has the same effect as specifying the argument as a pointer to a list containing a single null pointer. Do not take advantage of this nonstandard and nonportable misfeature! On many other UNIX systems, specifying argv as NULL will result in an error (EFAULT). Some other UNIX systems treat the envp==NULL case the same as Linux.

So, even if you're on Linux, you're setting an empty environment that doesn't contain even a PATH variable, so the search fails. On my system, an error is printed by which:

/usr/bin/which: no cat in ((null))

It works if you use execv instead, which doesn't require an environment and just inherits it from the parent process:

        execv(args[0], args);