Generic *NIX function */
| 143 | |
| 144 | /* Generic *NIX function */ |
| 145 | char *gmt_runtime_bindir (char *result, const char *candidate) { |
| 146 | char *c, *path, *dir, *save_ptr = NULL; |
| 147 | char candidate_abs[PATH_MAX+1]; |
| 148 | ssize_t len; |
| 149 | *result = '\0'; |
| 150 | |
| 151 | /* Try proc first */ |
| 152 | if ( (len = readlink ("/proc/self/exe", result, PATH_MAX)) != -1 ) { |
| 153 | result[len] = '\0'; |
| 154 | /* Truncate absolute path to dirname */ |
| 155 | if ( (c = strrchr (result, '/')) && c != result ) |
| 156 | *c = '\0'; |
| 157 | #ifdef DEBUG_RUNPATH |
| 158 | fprintf (stderr, "executable is in '%s' (from %s).\n", result, link); |
| 159 | #endif |
| 160 | return result; |
| 161 | } |
| 162 | |
| 163 | /* If candidate is NULL or empty */ |
| 164 | if ( candidate == NULL || *candidate == '\0' ) |
| 165 | return NULL; |
| 166 | |
| 167 | /* Handle absolute paths */ |
| 168 | if (*candidate == '/') { |
| 169 | /* Resolve symlinks */ |
| 170 | if (realpath (candidate, result) == NULL) |
| 171 | return NULL; |
| 172 | /* Truncate absolute path to dirname */ |
| 173 | if ( (c = strrchr (result, '/')) && c != result ) |
| 174 | *c = '\0'; |
| 175 | #ifdef DEBUG_RUNPATH |
| 176 | fprintf (stderr, "executable is in '%s' (from /).\n", result); |
| 177 | #endif |
| 178 | return result; |
| 179 | } |
| 180 | |
| 181 | /* Test if candidate was path from cwd */ |
| 182 | if (strchr (candidate, '/')) { |
| 183 | /* Get the real path */ |
| 184 | if (realpath (candidate, result) == NULL) |
| 185 | return NULL; |
| 186 | /* Truncate absolute path to dirname */ |
| 187 | if ( (c = strrchr (result, '/')) && c != result ) |
| 188 | *c = '\0'; |
| 189 | #ifdef DEBUG_RUNPATH |
| 190 | fprintf (stderr, "executable is in '%s' (from cwd).\n", result); |
| 191 | #endif |
| 192 | return result; |
| 193 | } |
| 194 | |
| 195 | /* Search candidate in the PATH */ |
| 196 | path = getenv ("PATH"); |
| 197 | if (path != NULL) { |
| 198 | /* Must copy string because changing pointers returned by getenv it is not allowed: */ |
| 199 | path = strdup (path); |
| 200 | for (dir = strtok_r (path, ":", &save_ptr); |
| 201 | dir != NULL; |
| 202 | dir = strtok_r (NULL, ":", &save_ptr)) { |
no test coverage detected