1
\$\begingroup\$

I'm trying to implement execvp () using execv (). I don't know if the code is the best implementation.

my code:

#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>

extern char **environ; 

int my_execvp(char *file, char *argv[])
{
  char *p, *colon, *pathseq = getenv("PATH");
  size_t len;

  if(strchr (file, '/'))
    return execv(file, argv);

  if (pathseq == NULL) {
        len = confstr(_CS_PATH, (char *) NULL, 0);
        pathseq = (char *) alloca(1 + len);
        pathseq[0] = ':';
        (void) confstr (_CS_PATH, pathseq + 1, len);
  }
  len = strlen(file) + strlen(pathseq) + 2;

  for(p = pathseq; p && *p; p = colon)
  {
     char b[len];
     colon = strchr(p, ':');
     if(colon)
     {
        memcpy(b, p, (size_t) (colon - p));
        b[colon++-p] = 0;
     }
     else
        strcpy(b, p);
     strcat (b, "/");
     strcat (b, file);
     if(!access(b, F_OK)) {
            execv(b, argv);
            fprintf(stderr, "an error occurred in execv\n");
            abort();
     }
   }
   errno = ENOENT;
     return -1;
}

int main()
{
    /* "ls / -l" */
    char *arg[] = {"ls", "/", "-l", NULL};
    my_execvp (arg[0], arg);

    return 0;
} 

And the question I have, is it a good implementation? How could it be improved or write a better implementation?

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

The implementation is non-conformant.

  1. No handling of undefined PATH. Quoting man execp:

search path is the path specified in the environment by ``PATH'' variable. If this variable is not specified, the default path is set according to the _PATH_DEFPATH definition in <paths.h>

Once confstr returns 0, check errno, and act accordingly.

  1. Calling abort on execv failure is plain wrong. At least return what execv returns.

  2. Calling access is also incorrect. If the file exists, but doesn't have correct permissions, execvp shall continue searching.

As a side note, access is very rarely useful. Consider calling execvp blindly, and testing errno upon return.

  1. Final errno = ENOENT; is also non-compliant. execvp sets ENOENT if the file does not exist in any path. If it was found at least once, and fails to execute, the errno shall be EACCES.

  2. execvp is not supposed to fprintf anything.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.