Ugly helper to get full pathname of the current binary. */
| 969 | |
| 970 | /* Ugly helper to get full pathname of the current binary. */ |
| 971 | const char *find_my_abspath(const tal_t *ctx, const char *argv0) |
| 972 | { |
| 973 | char *me; |
| 974 | |
| 975 | /* A command containing / is run relative to the current directory, |
| 976 | * not searched through the path. The shell sets argv0 to the command |
| 977 | * run, though something else could set it to a arbitrary value and |
| 978 | * this logic would be wrong. */ |
| 979 | if (strchr(argv0, PATH_SEP)) { |
| 980 | const char *path; |
| 981 | /* Absolute paths are easy. */ |
| 982 | if (strstarts(argv0, PATH_SEP_STR)) |
| 983 | path = argv0; |
| 984 | /* It contains a '/', it's relative to current dir. */ |
| 985 | else |
| 986 | path = path_join(tmpctx, path_cwd(tmpctx), argv0); |
| 987 | |
| 988 | me = path_canon(ctx, path); |
| 989 | if (!me || access(me, X_OK) != 0) |
| 990 | errx(1, "I cannot find myself at %s based on my name %s", |
| 991 | path, argv0); |
| 992 | } else { |
| 993 | /* No /, search path */ |
| 994 | char **pathdirs; |
| 995 | const char *pathenv = getenv("PATH"); |
| 996 | size_t i; |
| 997 | |
| 998 | /* This replicates the standard shell path search algorithm */ |
| 999 | if (!pathenv) |
| 1000 | errx(1, "Cannot find myself: no $PATH set"); |
| 1001 | |
| 1002 | pathdirs = tal_strsplit(tmpctx, pathenv, ":", STR_NO_EMPTY); |
| 1003 | me = NULL; |
| 1004 | for (i = 0; pathdirs[i]; i++) { |
| 1005 | /* This returns NULL if it doesn't exist. */ |
| 1006 | me = path_canon(ctx, |
| 1007 | path_join(tmpctx, pathdirs[i], argv0)); |
| 1008 | if (me && access(me, X_OK) == 0) |
| 1009 | break; |
| 1010 | /* Nope, try again. */ |
| 1011 | me = tal_free(me); |
| 1012 | } |
| 1013 | if (!me) |
| 1014 | errx(1, "Cannot find %s in $PATH", argv0); |
| 1015 | } |
| 1016 | |
| 1017 | return me; |
| 1018 | } |