diff --git a/src/util/u_process.c b/src/util/u_process.c index a05fa57e95f..2d3f77242ea 100644 --- a/src/util/u_process.c +++ b/src/util/u_process.c @@ -32,8 +32,6 @@ #include #include -#undef GET_PROGRAM_NAME - #if DETECT_OS_WINDOWS #include #else @@ -49,21 +47,17 @@ #include #endif +#include "util/u_call_once.h" + +#undef GET_PROGRAM_NAME_NOT_AVAILABLE + #if defined(__linux__) && defined(HAVE_PROGRAM_INVOCATION_NAME) - -static char *path = NULL; - -static void __freeProgramPath() -{ - free(path); - path = NULL; -} - -static const char * +static char * __getProgramName() { char * arg = strrchr(program_invocation_name, '/'); if (arg) { + char *program_name = NULL; /* If the / character was found this is likely a linux path or * an invocation path for a 64-bit wine program. * @@ -71,20 +65,22 @@ __getProgramName() * 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); - } + char *path = realpath("/proc/self/exe", NULL); 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; + program_name = strdup(name + 1); } - - return arg+1; + if (path) { + free(path); + } + if (!program_name) { + program_name = strdup(arg+1); + } + return program_name; } /* If there was no '/' at all we likely have a windows like path from @@ -92,109 +88,137 @@ __getProgramName() */ arg = strrchr(program_invocation_name, '\\'); if (arg) - return arg+1; + return strdup(arg+1); - return program_invocation_name; + return strdup(program_invocation_name); } -# define GET_PROGRAM_NAME() __getProgramName() #elif defined(HAVE_PROGRAM_INVOCATION_NAME) -# define GET_PROGRAM_NAME() program_invocation_short_name -#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) || defined(ANDROID) -# define GET_PROGRAM_NAME() getprogname() -#elif defined(__NetBSD__) +static char * +__getProgramName() +{ + return strdup(program_invocation_short_name); +} +#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) || defined(ANDROID) || defined(__NetBSD__) +#if defined(__NetBSD__) # include -# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) -# define GET_PROGRAM_NAME() getprogname() -# endif +#endif +#if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 106000100) +#define GET_PROGRAM_NAME_NOT_AVAILABLE +#else /* !(defined(__NetBSD_Version__) && (__NetBSD_Version__ < 106000100)) */ +static char * +__getProgramName() +{ + const char *program_name = getprogname(); + if (program_name) { + return strdup(program_name); + } + return NULL; +} +#endif /* defined(__NetBSD_Version__) && (__NetBSD_Version__ < 106000100) */ #elif defined(__sun) /* Solaris has getexecname() which returns the full path - return just the basename to match BSD getprogname() */ # include -static const char * +static char * __getProgramName() { - static const char *progname; - - if (progname == NULL) { - const char *e = getexecname(); - if (e != NULL) { - /* Have to make a copy since getexecname can return a readonly - string, but basename expects to be able to modify its arg. */ - char *n = strdup(e); - if (n != NULL) { - progname = basename(n); - } - } - } - return progname; -} - -# define GET_PROGRAM_NAME() __getProgramName() -#elif DETECT_OS_WINDOWS -static const char * -__getProgramName() -{ - static const char *progname; - if (progname == NULL) { - static char buf[MAX_PATH]; - GetModuleFileNameA(NULL, buf, sizeof(buf)); - progname = strrchr(buf, '\\'); - if (progname) - progname++; - else - progname = buf; + char *progname = NULL; + const char *e = getexecname(); + if (e != NULL) { + /* Have to make a copy since getexecname can return a readonly + string, but basename expects to be able to modify its arg. */ + char *n = strdup(e); + if (n != NULL) { + progname = strdup(basename(n)); + free(n); + } } return progname; } -# define GET_PROGRAM_NAME() __getProgramName() +#elif DETECT_OS_WINDOWS +static char * +__getProgramName() +{ + char *progname; + static char buf[MAX_PATH]; + GetModuleFileNameA(NULL, buf, sizeof(buf)); + progname = strrchr(buf, '\\'); + if (progname) + progname++; + else + progname = buf; + return strdup(progname); +} #elif defined(__HAIKU__) # include extern char **__libc_argv; extern int __libc_argc; -static const char * +static char * __getProgramName() { - static const char *progname; - - if (progname == NULL) { - char *n = strdup(__libc_argv[0]); - if (n != NULL) { - progname = basename(n); - } - } - return progname; + char *progname = NULL; + char *n = strdup(__libc_argv[0]); + if (n != NULL) { + progname = strdup(basename(n)); + free(n); + } + return progname; } -# define GET_PROGRAM_NAME() __getProgramName() +#else +#define GET_PROGRAM_NAME_NOT_AVAILABLE #endif -#if !defined(GET_PROGRAM_NAME) -# if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__UCLIBC__) || defined(ANDROID) +#if defined(GET_PROGRAM_NAME_NOT_AVAILABLE) +#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. */ -static const char * +static char * __getProgramName() { extern const char *__progname; char * arg = strrchr(__progname, '/'); if (arg) - return arg+1; + return strdup(arg+1); else - return __progname; + return strdup(__progname); +} +#else +#pragma message ( "Warning: Per application configuration won't work with your OS version." ) +static char * +__getProgramName() +{ + return strdup(""); } -# define GET_PROGRAM_NAME() __getProgramName() -# else -# define GET_PROGRAM_NAME() "" -# pragma message ( "Warning: Per application configuration won't work with your OS version." ) -# endif #endif +#endif /* GET_PROGRAM_NAME_NOT_AVAILABLE */ + +static char *program_name; + +static void +free_program_name(void) +{ + free(program_name); + program_name = NULL; +} + +static void +util_get_process_name_callback(void) +{ + program_name = __getProgramName(); + if (program_name) { + atexit(free_program_name); + } +} const char * util_get_process_name(void) { - return GET_PROGRAM_NAME(); + static util_once_flag once_state = UTIL_ONCE_FLAG_INIT; + util_call_once(&once_state, util_get_process_name_callback); + return program_name; } size_t