1/* 2 * Copyright © 2003 Felix Kuehling 3 * Copyright © 2018 Advanced Micro Devices, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 16 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 18 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * The above copyright notice and this permission notice (including the 24 * next paragraph) shall be included in all copies or substantial portions 25 * of the Software. 26 */ 27 28#include "u_process.h" 29#include <string.h> 30#include <errno.h> 31#include <stdlib.h> 32 33#undef GET_PROGRAM_NAME 34 35#if defined(__linux__) && defined(HAVE_PROGRAM_INVOCATION_NAME) 36 37static char *path = NULL; 38 39static void __freeProgramPath() 40{ 41 free(path); 42 path = NULL; 43} 44 45static const char * 46__getProgramName() 47{ 48 char * arg = strrchr(program_invocation_name, '/'); 49 if (arg) { 50 /* If the / character was found this is likely a linux path or 51 * an invocation path for a 64-bit wine program. 52 * 53 * However, some programs pass command line arguments into argv[0]. 54 * Strip these arguments out by using the realpath only if it was 55 * a prefix of the invocation name. 56 */ 57 if (!path) { 58 path = realpath("/proc/self/exe", NULL); 59 atexit(__freeProgramPath); 60 } 61 62 if (path && strncmp(path, program_invocation_name, strlen(path)) == 0) { 63 /* This shouldn't be null because path is a a prefix, 64 * but check it anyway since path is static. */ 65 char * name = strrchr(path, '/'); 66 if (name) 67 return name + 1; 68 } 69 70 return arg+1; 71 } 72 73 /* If there was no '/' at all we likely have a windows like path from 74 * a wine application. 75 */ 76 arg = strrchr(program_invocation_name, '\\'); 77 if (arg) 78 return arg+1; 79 80 return program_invocation_name; 81} 82# define GET_PROGRAM_NAME() __getProgramName() 83#elif defined(HAVE_PROGRAM_INVOCATION_NAME) 84# define GET_PROGRAM_NAME() program_invocation_short_name 85#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2) 86# include <osreldate.h> 87# if (__FreeBSD_version >= 440000) 88# define GET_PROGRAM_NAME() getprogname() 89# endif 90#elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) 91# define GET_PROGRAM_NAME() getprogname() 92#elif defined(__DragonFly__) 93# define GET_PROGRAM_NAME() getprogname() 94#elif defined(__APPLE__) 95# define GET_PROGRAM_NAME() getprogname() 96#elif defined(ANDROID) 97# define GET_PROGRAM_NAME() getprogname() 98#elif defined(__sun) 99/* Solaris has getexecname() which returns the full path - return just 100 the basename to match BSD getprogname() */ 101# include <libgen.h> 102 103static const char * 104__getProgramName() 105{ 106 static const char *progname; 107 108 if (progname == NULL) { 109 const char *e = getexecname(); 110 if (e != NULL) { 111 /* Have to make a copy since getexecname can return a readonly 112 string, but basename expects to be able to modify its arg. */ 113 char *n = strdup(e); 114 if (n != NULL) { 115 progname = basename(n); 116 } 117 } 118 } 119 return progname; 120} 121 122# define GET_PROGRAM_NAME() __getProgramName() 123#endif 124 125#if !defined(GET_PROGRAM_NAME) 126# if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__UCLIBC__) || defined(ANDROID) 127/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU. 128 * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's 129 * used as a last resort, if there is no documented facility available. */ 130static const char * 131__getProgramName() 132{ 133 extern const char *__progname; 134 char * arg = strrchr(__progname, '/'); 135 if (arg) 136 return arg+1; 137 else 138 return __progname; 139} 140# define GET_PROGRAM_NAME() __getProgramName() 141# else 142# define GET_PROGRAM_NAME() "" 143# pragma message ( "Warning: Per application configuration won't work with your OS version." ) 144# endif 145#endif 146 147const char * 148util_get_process_name(void) 149{ 150 return GET_PROGRAM_NAME(); 151} 152