X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Futil%2Fu_process.c;h=68fda93a53bb22515fb5c04f64d85534d8640df7;hb=848e7b947d0d505d54d27780b052e5532c721678;hp=5bf3f56db4ed0070d9bfcd1fda9d6729f3ac4fa6;hpb=17f49950da91137366910183f616d15b8bbf580c;p=mesa.git diff --git a/src/util/u_process.c b/src/util/u_process.c index 5bf3f56db4e..68fda93a53b 100644 --- a/src/util/u_process.c +++ b/src/util/u_process.c @@ -26,36 +26,84 @@ */ #include "u_process.h" +#include "detect_os.h" +#include "macros.h" #include #include #include #undef GET_PROGRAM_NAME -#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__) -# if !defined(__GLIBC__) || (__GLIBC__ < 2) -/* These aren't declared in any libc5 header */ -extern char *program_invocation_name, *program_invocation_short_name; -# endif +#if DETECT_OS_WINDOWS +#include +#else +#include +#endif + +#if DETECT_OS_APPLE +#include +#endif + +#if defined(__linux__) && defined(HAVE_PROGRAM_INVOCATION_NAME) + +static char *path = NULL; + +static void __freeProgramPath() +{ + free(path); + path = NULL; +} + static const char * __getProgramName() { - char * arg = strrchr(program_invocation_name, '/'); - if (arg) - return arg+1; - else - return program_invocation_name; + char * arg = strrchr(program_invocation_name, '/'); + if (arg) { + /* If the / character was found this is likely a linux path or + * an invocation path for a 64-bit wine program. + * + * However, some programs pass command line arguments into argv[0]. + * Strip these arguments out by using the realpath only if it was + * a prefix of the invocation name. + */ + if (!path) { + path = realpath("/proc/self/exe", NULL); + atexit(__freeProgramPath); + } + + if (path && strncmp(path, program_invocation_name, strlen(path)) == 0) { + /* This shouldn't be null because path is a a prefix, + * but check it anyway since path is static. */ + char * name = strrchr(path, '/'); + if (name) + return name + 1; + } + + return arg+1; + } + + /* If there was no '/' at all we likely have a windows like path from + * a wine application. + */ + arg = strrchr(program_invocation_name, '\\'); + if (arg) + return arg+1; + + return program_invocation_name; } # define GET_PROGRAM_NAME() __getProgramName() -#elif defined(__CYGWIN__) +#elif defined(HAVE_PROGRAM_INVOCATION_NAME) # define GET_PROGRAM_NAME() program_invocation_short_name #elif defined(__FreeBSD__) && (__FreeBSD__ >= 2) # include # if (__FreeBSD_version >= 440000) # define GET_PROGRAM_NAME() getprogname() # endif -#elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) -# define GET_PROGRAM_NAME() getprogname() +#elif defined(__NetBSD__) +# include +# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) +# define GET_PROGRAM_NAME() getprogname() +# endif #elif defined(__DragonFly__) # define GET_PROGRAM_NAME() getprogname() #elif defined(__APPLE__) @@ -90,7 +138,7 @@ __getProgramName() #endif #if !defined(GET_PROGRAM_NAME) -# if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__) || defined(ANDROID) +# if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__UCLIBC__) || defined(ANDROID) /* This is a hack. It's said to work on OpenBSD, NetBSD and GNU. * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's * used as a last resort, if there is no documented facility available. */ @@ -116,3 +164,35 @@ util_get_process_name(void) { return GET_PROGRAM_NAME(); } + +size_t +util_get_process_exec_path(char* process_path, size_t len) +{ +#if DETECT_OS_WINDOWS + return GetModuleFileNameA(NULL, process_path, len); +#elif DETECT_OS_APPLE + uint32_t bufSize = len; + int result = _NSGetExecutablePath(process_path, &bufSize); + + return (result == 0) ? strlen(process_path) : 0; +#elif DETECT_OS_UNIX + ssize_t r; + + if ((r = readlink("/proc/self/exe", process_path, len)) > 0) + goto success; + if ((r = readlink("/proc/curproc/exe", process_path, len)) > 0) + goto success; + if ((r = readlink("/proc/curproc/file", process_path, len)) > 0) + goto success; + + return 0; +success: + if (r == len) + return 0; + + process_path[r] = '\0'; + return r; + +#endif + return 0; +}