/* Copyright (c) 2016, 2019, 2022 Dennis Wölfing
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* libc/src/unistd/execl.c
 * Executes a program. (POSIX2008, called from C89)
 */

#define execv __execv
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>

int __execl(const char* path, const char* argv0, ...) {
    // Count the arguments
    int argc = 1;
    va_list ap;
    va_start(ap, argv0);
    while (va_arg(ap, char*)) {
        argc++;
    }
    va_end(ap);

    // Create an array containing all arguments
    char** argv = malloc((argc + 1) * sizeof(char*));
    if (!argv) return -1;

    va_start(ap, argv0);
    argv[0] = (char*) argv0;
    for (int i = 1; i < argc; i++) {
        argv[i] = va_arg(ap, char*);
    }
    argv[argc] = NULL;
    va_end(ap);

    execv(path, argv);

    // Cleanup if execv failed
    free(argv);
    return -1;
}
__weak_alias(__execl, execl);
