Viewing: execvp.c
📄 execvp.c (Read Only) ⬅ To go back
#include "unistd.h"
#include "string.h"
#include "stdlib.h"
#include "errno.h"
#include <stddef.h>

extern char** __environ;

int execvp(const char* file, char* const argv[]) {
    if (!file || !*file) { errno = ENOENT; return -1; }

    /* If file contains '/', use it directly */
    if (strchr(file, '/'))
        return execve(file, argv, __environ);

    /* Search PATH */
    const char* path = getenv("PATH");
    if (!path) path = "/bin:/usr/bin";

    char buf[256];
    size_t flen = strlen(file);

    while (*path) {
        const char* sep = path;
        while (*sep && *sep != ':') sep++;
        size_t dlen = (size_t)(sep - path);
        if (dlen == 0) { dlen = 1; path = "."; }

        if (dlen + 1 + flen + 1 > sizeof(buf)) {
            path = *sep ? sep + 1 : sep;
            continue;
        }

        memcpy(buf, path, dlen);
        buf[dlen] = '/';
        memcpy(buf + dlen + 1, file, flen + 1);

        execve(buf, argv, __environ);
        /* If ENOENT, try next; otherwise fail */
        if (errno != ENOENT) return -1;

        path = *sep ? sep + 1 : sep;
    }

    errno = ENOENT;
    return -1;
}

int execlp(const char* file, const char* arg, ...) {
    /* Count args by walking the va_list manually via stack pointers.
     * On i386, args are pushed right-to-left on the stack.
     * We'll use a simple approach: max 32 args. */
    const char* args[33];
    const char** p = &arg;
    int i = 0;
    while (*p && i < 32) {
        args[i++] = *p;
        p++;
    }
    args[i] = (const char*)0;
    return execvp(file, (char* const*)args);
}

int execl(const char* path, const char* arg, ...) {
    const char* args[33];
    const char** p = &arg;
    int i = 0;
    while (*p && i < 32) {
        args[i++] = *p;
        p++;
    }
    args[i] = (const char*)0;
    return execve(path, (char* const*)args, __environ);
}