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