diff --git a/include/common/standard.h b/include/common/standard.h index cf8f1f046..80a1fc234 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -1496,6 +1496,7 @@ void dump_addr_and_bytes(struct buffer *buf, const char *pfx, const void *addr, void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len, int unsafe); int may_access(const void *ptr); void *resolve_sym_name(struct buffer *buf, const char *pfx, void *addr); +const char *get_exec_path(); #if defined(USE_BACKTRACE) /* Note that this may result in opening libgcc() on first call, so it may need diff --git a/include/types/global.h b/include/types/global.h index 407fbff60..592d28867 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -245,6 +245,7 @@ extern unsigned char boot_seed[20]; // per-boot random seed (160 bits initially /* bit values to go with "warned" above */ #define WARN_ANY 0x00000001 /* any warning was emitted */ #define WARN_FORCECLOSE_DEPRECATED 0x00000002 +#define WARN_EXEC_PATH 0x00000004 /* executable path already reported */ /* to be used with warned and WARN_* */ diff --git a/src/log.c b/src/log.c index 50b5080c4..2d926649e 100644 --- a/src/log.c +++ b/src/log.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -1109,6 +1110,14 @@ void ha_alert(const char *fmt, ...) va_list argp; if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | MODE_STARTING))) { + if (!(warned & WARN_EXEC_PATH)) { + const char *path = get_exec_path(); + + warned |= WARN_EXEC_PATH; + ha_notice("haproxy version is %s\n", haproxy_version); + if (path) + ha_notice("path to executable is %s\n", path); + } va_start(argp, fmt); print_message("ALERT", fmt, argp); va_end(argp); diff --git a/src/standard.c b/src/standard.c index 3afaf5a99..eba79101b 100644 --- a/src/standard.c +++ b/src/standard.c @@ -16,6 +16,10 @@ #include #endif +#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16)) +#include +#endif + #include #include #include @@ -4335,6 +4339,22 @@ void debug_hexdump(FILE *out, const char *pfx, const char *buf, } } +/* Tries to report the executable path name on platforms supporting this. If + * not found or not possible, returns NULL. + */ +const char *get_exec_path() +{ + const char *ret = NULL; + +#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16)) + long execfn = getauxval(AT_EXECFN); + + if (execfn && execfn != ENOENT) + ret = (const char *)execfn; +#endif + return ret; +} + #ifdef __ELF__ /* calls dladdr() or dladdr1() on and . If dladdr1 is available, * also returns the symbol size in , otherwise returns 0 there.