From 8b367c7f2d77bb5e1d7586853669df644a2b1d52 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Mon, 1 Jul 2024 21:04:33 +0200 Subject: Add getexecpath functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 3 ++ egetexecpath.c | 18 ++++++++ engetexecpath.c | 34 +++++++++++++++ getexecpath.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ libsimple/path.h | 14 +++++++ 5 files changed, 194 insertions(+) create mode 100644 egetexecpath.c create mode 100644 engetexecpath.c create mode 100644 getexecpath.c diff --git a/Makefile b/Makefile index d44d559..5a2ada3 100644 --- a/Makefile +++ b/Makefile @@ -413,6 +413,7 @@ OBJ =\ ecallocn.o\ efreadlink.o\ egetcwd.o\ + egetexecpath.o\ egmtime.o\ elocaltime.o\ emalloc.o\ @@ -443,6 +444,7 @@ OBJ =\ encallocn.o\ enfreadlink.o\ engetcwd.o\ + engetexecpath.o\ engmtime.o\ enlocaltime.o\ enmalloc.o\ @@ -553,6 +555,7 @@ OBJ =\ getcwd.o\ getenv_e.o\ getenv_ne.o\ + getexecpath.o\ gmtime.o\ habs.o\ hdiff.o\ diff --git a/egetexecpath.c b/egetexecpath.c new file mode 100644 index 0000000..17998de --- /dev/null +++ b/egetexecpath.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +extern inline char *libsimple_egetexecpath(void); + + +#else +#include "test.h" + +int +main(void) /* TODO test */ +{ + return 0; +} + +#endif diff --git a/engetexecpath.c b/engetexecpath.c new file mode 100644 index 0000000..14994e8 --- /dev/null +++ b/engetexecpath.c @@ -0,0 +1,34 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +char * +libsimple_engetexecpath(int status) +{ + int saved_errno; + char *ret; + saved_errno = errno;; + errno = 0; + ret = libsimple_getexecpath(); + if (!ret) { + if (errno) + libsimple_enprintf(status, "libsimple_getexecpath:"); + else + libsimple_enprintf(status, "libsimple_getexecpath: unable to determine path\n"); + } + errno = saved_errno; + return ret; +} + + +#else +#include "test.h" + +int +main(void) /* TODO test */ +{ + return 0; +} + +#endif diff --git a/getexecpath.c b/getexecpath.c new file mode 100644 index 0000000..84bfea4 --- /dev/null +++ b/getexecpath.c @@ -0,0 +1,125 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + +#include + + +extern char *argv0; + + +static char * +getexecpath_by_execfn(void) +{ + unsigned long auxval; + char *execpath, *path, *target; + const char *name, *s, *fdlink; + size_t n; + + auxval = getauxval(AT_EXECFN); + if (!auxval) + return NULL; + + name = (void *)auxval; + if (strstarts(name, "/dev/fd/")) + s = &name[sizeof("/dev/fd/") - 1U]; + else if (strstarts(name, "/proc/self/fd/")) + s = &name[sizeof("/proc/self/fd/") - 1U]; + else + return libsimple_abspath(name, NULL); + + while (isdigit(*s)) + s++; + if (*s) { + n = (size_t)(s - name); + path = malloc(n + 1U); + if (!path) + return NULL; + memcpy(path, name, n); + path[n] = '\0'; + fdlink = path; + } else { + path = NULL; + fdlink = name; + } + target = libsimple_readmagiclink(fdlink); + free(path); + if (!target) + return NULL; + execpath = malloc(strlen(target) + strlen(s) + 1U); + if (!execpath) { + free(target); + return NULL; + } + stpcpy(stpcpy(execpath, target), s); + free(target); + + return execpath; +} + + +static char * +getexecpath_by_execfd(void) +{ + unsigned long auxval; + int fd; + char path[sizeof("/dev/fd/") + 3U * sizeof(int)]; + + errno = 0; + auxval = getauxval(AT_EXECFN); + if (!auxval && errno) + return NULL; + fd = (int)auxval; + + sprintf(path, "/dev/fd/%i", fd); + return libsimple_readmagiclink(path); +} + + +static char * +getexecpath_by_proc_exe(void) +{ + return libsimple_readmagiclink("/proc/self/exe"); +} + + +static char * +getexecpath_by_argv0(void) +{ + char *s = argv0; + + if (strchr(s, '/')) + return libsimple_abspath(s, NULL); + + return NULL; +} + + +char * +libsimple_getexecpath(void) +{ + char *r; + + if ((r = getexecpath_by_execfn())) + return r; + if ((r = getexecpath_by_execfd())) + return r; + if ((r = getexecpath_by_proc_exe())) + return r; + if ((r = getexecpath_by_argv0())) + return r; + + return NULL; +} + + +#else +#include "test.h" + +int +main(void) /* TODO test */ +{ + return 0; +} + +#endif diff --git a/libsimple/path.h b/libsimple/path.h index 6f2a8b8..cb78863 100644 --- a/libsimple/path.h +++ b/libsimple/path.h @@ -139,3 +139,17 @@ libsimple_ereadmagiclink(const char *path__) /* TODO man, doc */ { return libsimple_enreadmagiclink(libsimple_default_failure_exit, path__); } + + +LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__))) +char *libsimple_getexecpath(void); /* TODO man, doc */ + +LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__))) +char *libsimple_engetexecpath(int); /* TODO man, doc */ + +LIBSIMPLE_GCC_ONLY__(__attribute__((__malloc__, __assume_aligned__(1), __warn_unused_result__, __nonnull__, __returns_nonnull__))) +inline char * +libsimple_egetexecpath(void) /* TODO man, doc */ +{ + return libsimple_engetexecpath(libsimple_default_failure_exit); +} -- cgit v1.2.3-70-g09d2