Skip to content

get_program_exe_path needs additional porting and improvements #96

@johnsonjh

Description

@johnsonjh

get_program_exe_path() is subject to overflow on long paths and it only works on Linux, Cygwin, and macOS.

I ported the libsir _sir_getappfilename function to work on 17 platforms: Linux, Android, macOS, IBM AIX, IBM i (OS/400), Windows, Cygwin, FreeBSD, NetBSD, OpenBSD, DragonFly BSD, GNU/Hurd, Haiku, Solaris, illumos, SerenityOS, and Emscripten.

This was especially complicated to get working right without too many edge cases on OpenBSD, AIX, and IBM i. This functionality on all platforms is heavily tested and proven.

You can use actually use it as a direct drop-in replacement.

Here is a patch if you want to try it. It assumes libsir in ./libsir:

Details
diff --git a/GNUmakefile b/GNUmakefile
index 2c10fa8..026f81f 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,13 +1,13 @@
 CC?=cc
-CFLAGS?=-O3 -flto -Wall -g -Werror=implicit-function-declaration -Werror=int-conversion
-LDLIBS?=-lm
+CFLAGS?=-O3 -flto -Wall -g -Werror=implicit-function-declaration -Werror=int-conversion -I./libsir/include
+LDLIBS?=-L./libsir/build/lib -lsir_s -lm
 INSTALL?=install
 PREFIX?=/usr
 
 OBJS=\
  cpu.o\
  loader.o\
  main.o\
  codepage.o\
  dosnames.o\
  dis.o\
diff --git a/src/utils.c b/src/utils.c
index 138029a..10dcbed 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,38 +1,9 @@
 /* Platform dependent utility functions */
-#include "utils.h"
-#include "dbg.h"
-#include <unistd.h>
 
-#ifdef __APPLE__
-#include <mach-o/dyld.h>
-#endif
+#include "sir.h"
+#include "sir/filesystem.h"
 
 const char *get_program_exe_path(void)
 {
-#if defined(__linux__) || defined(__CYGWIN__)
-
-    static char exe_path[4096] = {
-        0,
-    };
-    if(readlink("/proc/self/exe", exe_path, 4095) == -1)
-        return 0;
-    else
-        return exe_path;
-
-#elif defined(__APPLE__)
-
-    static char exe_path[4096] = {
-        0,
-    };
-    uint32_t length = 4095;
-    if(_NSGetExecutablePath(exe_path, &length))
-        return 0;
-    else
-        return exe_path;
-#else
-
-    /* No implementation */
-    return 0;
-
-#endif
+    return _sir_getappfilename();
 }

I know you probably don't want to bring in libsir as a dependency/subtree/submodule (although it does have a lot of other nice features you could use).

It is actually trivial to get Linux, Android, NetBSD, Solaris, illumos, Dragonfly BSD, Hurd, and SerenityOS working. I've made a PR for that (#97).

Haiku will be easy too.

Extracting the functionality needed to implement this for OpenBSD, AIX, and IBM i (OS/400) — without libsir — would be a much larger project, but is of course possible.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions