/*-
* Copyright ( c ) 1991 , 1993
* The Regents of the University of California . All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1 . Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2 . Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3 . Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*/
#include <sys/types.h>
#include <sys/uio.h>
#include <errno.h>
#include <limits.h>
#include <paths.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "private/FdPath.h"
#include "private/__bionic_get_shell_path.h"
extern "C" char ** environ;
enum { ExecL, ExecLE, ExecLP };
template <int variant>
static int __execl(const char * name, const char * argv0, va_list ap) {
// Count the arguments.
va_list count_ap;
va_copy(count_ap, ap);
size_t n = 1 ;
while (va_arg(count_ap, char *) != nullptr) {
++n;
}
va_end(count_ap);
// Construct the new argv.
char * argv[n + 1 ];
argv[0 ] = const_cast <char *>(argv0);
n = 1 ;
while ((argv[n] = va_arg(ap, char *)) != nullptr) {
++n;
}
// Collect the argp too.
char ** argp = (variant == ExecLE) ? va_arg(ap, char **) : environ;
va_end(ap);
return (variant == ExecLP) ? execvp(name, argv) : execve(name, argv, argp);
}
int execl(const char * name, const char * arg, ...) {
va_list ap;
va_start(ap, arg);
int result = __execl<ExecL>(name, arg, ap);
va_end(ap);
return result;
}
int execle(const char * name, const char * arg, ...) {
va_list ap;
va_start(ap, arg);
int result = __execl<ExecLE>(name, arg, ap);
va_end(ap);
return result;
}
int execlp(const char * name, const char * arg, ...) {
va_list ap;
va_start(ap, arg);
int result = __execl<ExecLP>(name, arg, ap);
va_end(ap);
return result;
}
int execv(const char * name, char * const * argv) {
return execve(name, argv, environ);
}
int execvp(const char * name, char * const * argv) {
return execvpe(name, argv, environ);
}
static int __exec_as_script(const char * buf, char * const * argv, char * const * envp) {
size_t arg_count = 1 ;
while (argv[arg_count] != nullptr) ++arg_count;
const char * script_argv[arg_count + 2 ];
script_argv[0 ] = "sh" ;
script_argv[1 ] = buf;
memcpy(script_argv + 2 , argv + 1 , arg_count * sizeof (char *));
return execve(__bionic_get_shell_path(), const_cast <char **>(script_argv), envp);
}
int execvpe(const char * name, char * const * argv, char * const * envp) {
// Do not allow null name.
if (name == nullptr || *name == '\0' ) {
errno = ENOENT;
return -1 ;
}
// If it's an absolute or relative path name, it's easy.
if (strchr(name, '/' ) && execve(name, argv, envp) == -1 ) {
if (errno == ENOEXEC) return __exec_as_script(name, argv, envp);
return -1 ;
}
// Get the path we're searching.
const char * path = getenv("PATH" );
if (path == nullptr) path = _PATH_DEFPATH;
// Make a writable copy.
size_t len = strlen(path) + 1 ;
char writable_path[len];
memcpy(writable_path, path, len);
bool saw_EACCES = false ;
// Try each element of $PATH in turn...
char * strsep_buf = writable_path;
const char * dir;
while ((dir = strsep(&strsep_buf, ":" ))) {
// It's a shell path: double, leading and trailing colons
// mean the current directory.
if (*dir == '\0' ) dir = const_cast <char *>("." );
size_t dir_len = strlen(dir);
size_t name_len = strlen(name);
char buf[dir_len + 1 + name_len + 1 ];
mempcpy(mempcpy(mempcpy(buf, dir, dir_len), "/" , 1 ), name, name_len + 1 );
execve(buf, argv, envp);
switch (errno) {
case EISDIR:
case ELOOP:
case ENAMETOOLONG:
case ENOENT:
case ENOTDIR:
break ;
case ENOEXEC:
return __exec_as_script(buf, argv, envp);
case EACCES:
saw_EACCES = true ;
break ;
default :
return -1 ;
}
}
if (saw_EACCES) errno = EACCES;
return -1 ;
}
int fexecve(int fd, char * const * argv, char * const * envp) {
// execveat with AT_EMPTY_PATH (>= 3.19) seems to offer no advantages.
execve(FdPath(fd).c_str(), argv, envp);
if (errno == ENOENT) errno = EBADF;
return -1 ;
}
Messung V0.5 in Prozent C=94 H=93 G=93
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-28)
¤
*© Formatika GbR, Deutschland