From c9f8890633c938030ecc2f751e8b0856363b3a90 Mon Sep 17 00:00:00 2001 From: Attila Kovacs Date: Thu, 9 Jan 2025 20:44:01 +0100 Subject: [PATCH] Program names on platforms without __progname in libc --- Makefile | 3 ++- README.md | 2 +- config.mk | 17 +++++++++---- include/procname.h | 31 +++++++++++++++++++++++ src/procname.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ src/smax.c | 9 +++---- 6 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 include/procname.h create mode 100644 src/procname.c diff --git a/Makefile b/Makefile index 20d69c1..8d63c31 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,8 @@ distclean: clean # ---------------------------------------------------------------------------- SOURCES = $(SRC)/smax.c $(SRC)/smax-easy.c $(SRC)/smax-lazy.c $(SRC)/smax-queue.c \ - $(SRC)/smax-meta.c $(SRC)/smax-messages.c $(SRC)/smax-resilient.c $(SRC)/smax-util.c + $(SRC)/smax-meta.c $(SRC)/smax-messages.c $(SRC)/smax-resilient.c \ + $(SRC)/smax-util.c $(SRC)/procname.c # Generate a list of object (obj/*.o) files from the input sources OBJECTS := $(subst $(SRC),$(OBJ),$(SOURCES)) diff --git a/README.md b/README.md index 7739f5c..2ab117a 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ prior to invoking `make`. The following build variables can be configured: - `WEXTRA`: If set to 1, `-Wextra` is added to `CFLAGS` automatically. - - `LDFLAGS`: Extra linker flags (default: _not set_). Note, `-lm -lredisx -lxchange -pthread` will be added + - `LDFLAGS`: Extra linker flags (default: _not set_). Note, `-lm -lpthread -lredisx -lxchange` will be added automatically. - `CHECKEXTRA`: Extra options to pass to `cppcheck` for the `make check` target diff --git a/config.mk b/config.mk index 5cf5487..755b6e9 100644 --- a/config.mk +++ b/config.mk @@ -45,12 +45,15 @@ ifeq ($(WEXTRA), 1) CFLAGS += -Wextra endif +# On some old platforms __progname is not provided by libc. We have a +# workaround in place for LynxOS/PowerPCs. For other platforms without +# __progname, uncomment the line below to use a default program name +# instead. +#NO_PROCNAME = 1 + # Extra link flags (if any) #LDFLAGS = -# Link flags to use for threading with pthread -THREADS ?= -pthread - # Link flags required for network functions (if any) to include in LDFLAGS #NETFLAGS = -lnsl @@ -76,6 +79,10 @@ CHECKOPTS += --inline-suppr $(CHECKEXTRA) # Below are some generated constants based on the one that were set above # ============================================================================ +ifeq ($(NO_PROCNAME),1) + CPPFLAGS += -DNO_PROCNAME=1 +endif + ifdef OSFLAGS LDFLAGS += $(OSFLAGS) endif @@ -84,8 +91,8 @@ ifdef NETFLAGS LDFLAGS += $(NETFLAGS) endif -# Links against pthread and dependencies -LDFLAGS += $(THREADS) -lredisx -lxchange +# Link against pthread and dependencies +LDFLAGS += -lpthread -lredisx -lxchange # Search for libraries under LIB ifneq ($(findstring $(LIB),$(LD_LIBRARY_PATH)),$LIB) diff --git a/include/procname.h b/include/procname.h new file mode 100644 index 0000000..a972d7c --- /dev/null +++ b/include/procname.h @@ -0,0 +1,31 @@ +/** + * + * @date Created on: May 12, 2020 + * @author Attila Kovacs + * + * Obtain the process name on platforms where the `__progname` is not defined by libc + * such as on LynxOS 3.1 / PowerPC... + */ + +#ifndef LYNXOS_PROCNAME_H_ +#define LYNXOS_PROCNAME_H_ + +#define DEFAULT_PROCESS_NAME "anonymous" + +#if __Lynx__ && __powerpc__ +/** + * Gets the process name for a given pid on LynxOS, by parsing process tables from /dev/mem. + * + * \param[in] pid Process ID, such as returned by getpid(). + * \param[out] procName String to return process name in (terminated, and with path stripped) + * \param[in] length The maximum number of characters to print into procName. + * + * \return 0 if the process was successfully identified (i.e. alive) + * 1 if there is no live process with that ID (returns default name) + * -1 if there was an error trying to look up the process name (return redault name). + */ +int getProcessName(int pid, char *procName, const int length); + +#endif + +#endif /* LYNXOS_PROCNAME_H_ */ diff --git a/src/procname.c b/src/procname.c new file mode 100644 index 0000000..5b8df65 --- /dev/null +++ b/src/procname.c @@ -0,0 +1,63 @@ +/** + * + * @date Created on: May 12, 2020 + * @author Attila Kovacs + * + * Obtain the process name on LynxOS 3.1 / PowerPC, where the `__progname` macro does + * not exists... + */ + +#include "procname.h" + +#if __Lynx__ && __powerpc__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// We'll parse the process table to match the PID to a process name... +int getProcessName(int pid, char *procName, const int length) { + int fd, status; + char *shortName; + __pentry proc; + + // Default process name + strncpy(procName, DEFAULT_PROCESS_NAME, length-1); + procName[length-1] = '\0'; + + if(pid <= 0 || pid > info(_I_NPROCTAB)) { + errno = EINVAL; + return -1; + } + + fd = open("/dev/mem", O_RDONLY); + if (fd < 0) return -1; + + lseek(fd, info(_I_PROCTAB) + pid * sizeof(struct pentry), 0); + status = read(fd, &proc, sizeof(struct pentry)); + close(fd); + + if(status < 0) return -1; + + /* Ignore if slot is marked as free */ + if(proc.pstate & PRFREE) return 1; + + shortName = strrchr(proc.pname, '/'); + if(shortName == NULL) shortName = proc.pname; + else shortName++; + + strncpy(procName, shortName, length-1); + procName[length-1] = '\0'; // Failsafe terminate. + + return 0; +} + + +#endif diff --git a/src/smax.c b/src/smax.c index 59a7bb0..550d4f7 100644 --- a/src/smax.c +++ b/src/smax.c @@ -29,10 +29,7 @@ #include #include "smax-private.h" - -#if __Lynx__ #include "procname.h" -#endif @@ -349,10 +346,10 @@ void smaxSetHostName(const char *name) { * */ char *smaxGetProgramID() { -#if __Lynx__ && __powerpc__ +#if (__Lynx__ && __powerpc__) char procName[40]; #else - const char *procName; + const char *procName = DEFAULT_PROCESS_NAME; extern char *__progname; #endif @@ -360,7 +357,7 @@ char *smaxGetProgramID() { if(programID) return programID; -#if __Lynx__ && __powerpc__ +#if (__Lynx__ && __powerpc__) getProcessName(getpid(), procName, 40); #else procName = __progname;