diff options
Diffstat (limited to 'libgfortran/runtime/main.c')
-rw-r--r-- | libgfortran/runtime/main.c | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c index 58ec6cc4961..8a572ecd5ef 100644 --- a/libgfortran/runtime/main.c +++ b/libgfortran/runtime/main.c @@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include <stdlib.h> #include <string.h> #include <limits.h> +#include <errno.h> #ifdef HAVE_UNISTD_H @@ -70,23 +71,18 @@ static int argc_save; static char **argv_save; static const char *exe_path; -static int please_free_exe_path_when_done; +static bool please_free_exe_path_when_done; /* Save the path under which the program was called, for use in the backtrace routines. */ void store_exe_path (const char * argv0) { -#ifndef PATH_MAX -#define PATH_MAX 1024 -#endif - #ifndef DIR_SEPARATOR #define DIR_SEPARATOR '/' #endif - char buf[PATH_MAX], *path; - const char *cwd; + char *cwd, *path; /* This can only happen if store_exe_path is called multiple times. */ if (please_free_exe_path_when_done) @@ -95,13 +91,27 @@ store_exe_path (const char * argv0) /* Reading the /proc/self/exe symlink is Linux-specific(?), but if it works it gives the correct answer. */ #ifdef HAVE_READLINK - int len; - if ((len = readlink ("/proc/self/exe", buf, sizeof (buf) - 1)) != -1) + ssize_t len, psize = 256; + while (1) { - buf[len] = '\0'; - exe_path = strdup (buf); - please_free_exe_path_when_done = 1; - return; + path = xmalloc (psize); + len = readlink ("/proc/self/exe", path, psize); + if (len < 0) + { + free (path); + break; + } + else if (len < psize) + { + path[len] = '\0'; + exe_path = strdup (path); + free (path); + please_free_exe_path_when_done = true; + return; + } + /* The remaining option is len == psize. */ + free (path); + psize *= 4; } #endif @@ -117,12 +127,29 @@ store_exe_path (const char * argv0) #endif { exe_path = argv0; - please_free_exe_path_when_done = 0; + please_free_exe_path_when_done = false; return; } #ifdef HAVE_GETCWD - cwd = getcwd (buf, sizeof (buf)); + size_t cwdsize = 256; + while (1) + { + cwd = xmalloc (cwdsize); + if (getcwd (cwd, cwdsize)) + break; + else if (errno == ERANGE) + { + free (cwd); + cwdsize *= 4; + } + else + { + free (cwd); + cwd = NULL; + break; + } + } #else cwd = NULL; #endif @@ -130,7 +157,7 @@ store_exe_path (const char * argv0) if (!cwd) { exe_path = argv0; - please_free_exe_path_when_done = 0; + please_free_exe_path_when_done = false; return; } @@ -138,10 +165,11 @@ store_exe_path (const char * argv0) if the executable is not in the cwd, but at this point we're out of better ideas. */ size_t pathlen = strlen (cwd) + 1 + strlen (argv0) + 1; - path = malloc (pathlen); + path = xmalloc (pathlen); snprintf (path, pathlen, "%s%c%s", cwd, DIR_SEPARATOR, argv0); + free (cwd); exe_path = path; - please_free_exe_path_when_done = 1; + please_free_exe_path_when_done = true; } |