1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2003 Felix Kuehling 3bf215546Sopenharmony_ci * Copyright © 2018 Advanced Micro Devices, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 7bf215546Sopenharmony_ci * a copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 16bf215546Sopenharmony_ci * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17bf215546Sopenharmony_ci * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 18bf215546Sopenharmony_ci * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 24bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 25bf215546Sopenharmony_ci * of the Software. 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "u_process.h" 29bf215546Sopenharmony_ci#include "detect_os.h" 30bf215546Sopenharmony_ci#include "macros.h" 31bf215546Sopenharmony_ci#include <string.h> 32bf215546Sopenharmony_ci#include <errno.h> 33bf215546Sopenharmony_ci#include <stdlib.h> 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#undef GET_PROGRAM_NAME 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#if DETECT_OS_WINDOWS 38bf215546Sopenharmony_ci#include <windows.h> 39bf215546Sopenharmony_ci#else 40bf215546Sopenharmony_ci#include <unistd.h> 41bf215546Sopenharmony_ci#endif 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci#if DETECT_OS_APPLE 44bf215546Sopenharmony_ci#include <mach-o/dyld.h> 45bf215546Sopenharmony_ci#endif 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci#if DETECT_OS_FREEBSD 48bf215546Sopenharmony_ci#include <sys/types.h> 49bf215546Sopenharmony_ci#include <sys/sysctl.h> 50bf215546Sopenharmony_ci#endif 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci#if defined(__linux__) && defined(HAVE_PROGRAM_INVOCATION_NAME) 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cistatic char *path = NULL; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_cistatic void __freeProgramPath() 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci free(path); 59bf215546Sopenharmony_ci path = NULL; 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cistatic const char * 63bf215546Sopenharmony_ci__getProgramName() 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci char * arg = strrchr(program_invocation_name, '/'); 66bf215546Sopenharmony_ci if (arg) { 67bf215546Sopenharmony_ci /* If the / character was found this is likely a linux path or 68bf215546Sopenharmony_ci * an invocation path for a 64-bit wine program. 69bf215546Sopenharmony_ci * 70bf215546Sopenharmony_ci * However, some programs pass command line arguments into argv[0]. 71bf215546Sopenharmony_ci * Strip these arguments out by using the realpath only if it was 72bf215546Sopenharmony_ci * a prefix of the invocation name. 73bf215546Sopenharmony_ci */ 74bf215546Sopenharmony_ci if (!path) { 75bf215546Sopenharmony_ci path = realpath("/proc/self/exe", NULL); 76bf215546Sopenharmony_ci atexit(__freeProgramPath); 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci if (path && strncmp(path, program_invocation_name, strlen(path)) == 0) { 80bf215546Sopenharmony_ci /* This shouldn't be null because path is a a prefix, 81bf215546Sopenharmony_ci * but check it anyway since path is static. */ 82bf215546Sopenharmony_ci char * name = strrchr(path, '/'); 83bf215546Sopenharmony_ci if (name) 84bf215546Sopenharmony_ci return name + 1; 85bf215546Sopenharmony_ci } 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci return arg+1; 88bf215546Sopenharmony_ci } 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci /* If there was no '/' at all we likely have a windows like path from 91bf215546Sopenharmony_ci * a wine application. 92bf215546Sopenharmony_ci */ 93bf215546Sopenharmony_ci arg = strrchr(program_invocation_name, '\\'); 94bf215546Sopenharmony_ci if (arg) 95bf215546Sopenharmony_ci return arg+1; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci return program_invocation_name; 98bf215546Sopenharmony_ci} 99bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() __getProgramName() 100bf215546Sopenharmony_ci#elif defined(HAVE_PROGRAM_INVOCATION_NAME) 101bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() program_invocation_short_name 102bf215546Sopenharmony_ci#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) || defined(ANDROID) 103bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() getprogname() 104bf215546Sopenharmony_ci#elif defined(__NetBSD__) 105bf215546Sopenharmony_ci# include <sys/param.h> 106bf215546Sopenharmony_ci# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) 107bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() getprogname() 108bf215546Sopenharmony_ci# endif 109bf215546Sopenharmony_ci#elif defined(__sun) 110bf215546Sopenharmony_ci/* Solaris has getexecname() which returns the full path - return just 111bf215546Sopenharmony_ci the basename to match BSD getprogname() */ 112bf215546Sopenharmony_ci# include <libgen.h> 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_cistatic const char * 115bf215546Sopenharmony_ci__getProgramName() 116bf215546Sopenharmony_ci{ 117bf215546Sopenharmony_ci static const char *progname; 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci if (progname == NULL) { 120bf215546Sopenharmony_ci const char *e = getexecname(); 121bf215546Sopenharmony_ci if (e != NULL) { 122bf215546Sopenharmony_ci /* Have to make a copy since getexecname can return a readonly 123bf215546Sopenharmony_ci string, but basename expects to be able to modify its arg. */ 124bf215546Sopenharmony_ci char *n = strdup(e); 125bf215546Sopenharmony_ci if (n != NULL) { 126bf215546Sopenharmony_ci progname = basename(n); 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci } 130bf215546Sopenharmony_ci return progname; 131bf215546Sopenharmony_ci} 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() __getProgramName() 134bf215546Sopenharmony_ci#elif defined(WIN32) 135bf215546Sopenharmony_cistatic const char * 136bf215546Sopenharmony_ci__getProgramName() 137bf215546Sopenharmony_ci{ 138bf215546Sopenharmony_ci static const char *progname; 139bf215546Sopenharmony_ci if (progname == NULL) { 140bf215546Sopenharmony_ci static char buf[MAX_PATH]; 141bf215546Sopenharmony_ci GetModuleFileNameA(NULL, buf, sizeof(buf)); 142bf215546Sopenharmony_ci progname = strrchr(buf, '\\'); 143bf215546Sopenharmony_ci if (progname) 144bf215546Sopenharmony_ci progname++; 145bf215546Sopenharmony_ci else 146bf215546Sopenharmony_ci progname = buf; 147bf215546Sopenharmony_ci } 148bf215546Sopenharmony_ci return progname; 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() __getProgramName() 151bf215546Sopenharmony_ci#elif defined(__HAIKU__) 152bf215546Sopenharmony_ci# include <libgen.h> 153bf215546Sopenharmony_ciextern char **__libc_argv; 154bf215546Sopenharmony_ciextern int __libc_argc; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic const char * 157bf215546Sopenharmony_ci__getProgramName() 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci static const char *progname; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci if (progname == NULL) { 162bf215546Sopenharmony_ci char *n = strdup(__libc_argv[0]); 163bf215546Sopenharmony_ci if (n != NULL) { 164bf215546Sopenharmony_ci progname = basename(n); 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci return progname; 168bf215546Sopenharmony_ci} 169bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() __getProgramName() 170bf215546Sopenharmony_ci#endif 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci#if !defined(GET_PROGRAM_NAME) 173bf215546Sopenharmony_ci# if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__UCLIBC__) || defined(ANDROID) 174bf215546Sopenharmony_ci/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU. 175bf215546Sopenharmony_ci * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's 176bf215546Sopenharmony_ci * used as a last resort, if there is no documented facility available. */ 177bf215546Sopenharmony_cistatic const char * 178bf215546Sopenharmony_ci__getProgramName() 179bf215546Sopenharmony_ci{ 180bf215546Sopenharmony_ci extern const char *__progname; 181bf215546Sopenharmony_ci char * arg = strrchr(__progname, '/'); 182bf215546Sopenharmony_ci if (arg) 183bf215546Sopenharmony_ci return arg+1; 184bf215546Sopenharmony_ci else 185bf215546Sopenharmony_ci return __progname; 186bf215546Sopenharmony_ci} 187bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() __getProgramName() 188bf215546Sopenharmony_ci# else 189bf215546Sopenharmony_ci# define GET_PROGRAM_NAME() "" 190bf215546Sopenharmony_ci# pragma message ( "Warning: Per application configuration won't work with your OS version." ) 191bf215546Sopenharmony_ci# endif 192bf215546Sopenharmony_ci#endif 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ciconst char * 195bf215546Sopenharmony_ciutil_get_process_name(void) 196bf215546Sopenharmony_ci{ 197bf215546Sopenharmony_ci return GET_PROGRAM_NAME(); 198bf215546Sopenharmony_ci} 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_cisize_t 201bf215546Sopenharmony_ciutil_get_process_exec_path(char* process_path, size_t len) 202bf215546Sopenharmony_ci{ 203bf215546Sopenharmony_ci#if DETECT_OS_WINDOWS 204bf215546Sopenharmony_ci return GetModuleFileNameA(NULL, process_path, len); 205bf215546Sopenharmony_ci#elif DETECT_OS_APPLE 206bf215546Sopenharmony_ci uint32_t bufSize = len; 207bf215546Sopenharmony_ci int result = _NSGetExecutablePath(process_path, &bufSize); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci return (result == 0) ? strlen(process_path) : 0; 210bf215546Sopenharmony_ci#elif DETECT_OS_FREEBSD 211bf215546Sopenharmony_ci int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci (void) sysctl(mib, 4, process_path, &len, NULL, 0); 214bf215546Sopenharmony_ci process_path[len - 1] = '\0'; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci return len; 217bf215546Sopenharmony_ci#elif DETECT_OS_UNIX 218bf215546Sopenharmony_ci ssize_t r; 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci if ((r = readlink("/proc/self/exe", process_path, len)) > 0) 221bf215546Sopenharmony_ci goto success; 222bf215546Sopenharmony_ci if ((r = readlink("/proc/curproc/exe", process_path, len)) > 0) 223bf215546Sopenharmony_ci goto success; 224bf215546Sopenharmony_ci if ((r = readlink("/proc/curproc/file", process_path, len)) > 0) 225bf215546Sopenharmony_ci goto success; 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci return 0; 228bf215546Sopenharmony_cisuccess: 229bf215546Sopenharmony_ci if (r == len) 230bf215546Sopenharmony_ci return 0; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci process_path[r] = '\0'; 233bf215546Sopenharmony_ci return r; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci#endif 236bf215546Sopenharmony_ci return 0; 237bf215546Sopenharmony_ci} 238