?MAKE:usensgetexecutablepath: cat rm_try Compile run Setvar
?MAKE:	-pick add $@ %<
?S:usensgetexecutablepath:
?S:	This symbol, if defined, indicates that we can use _NSGetExecutablePath
?S:	and realpath to get a full path for the executable, and hence convert
?S:	$^X to an absolute path.
?S:.
?C:USE_NSGETEXECUTABLEPATH:
?C:	This symbol, if defined, indicates that we can use _NSGetExecutablePath
?C:	and realpath to get a full path for the executable, and hence convert
?C:	$^X to an absolute path.
?C:.
?H:#$usensgetexecutablepath USE_NSGETEXECUTABLEPATH	/**/
?H:.
?LINT:set usensgetexecutablepath
?F:!try
: Determine if we can use _NSGetExecutablePath to find executing program
echo " "
echo "Determining whether we can use _NSGetExecutablePath to find executing program..." >&4
$cat >try.c <<'EOM'
/* Intentionally a long probe as I'd like to sanity check that the exact
   approach is going to work, as thinking it will work, but only having it
   part working at runtime is worse than not having it.  */
#include <mach-o/dyld.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <string.h>

int
main(int argc, char **argv) {
    char buf[1];
    uint32_t size = sizeof(buf);
    int result;
    char *buffer;
    char *tidied;
    char *argv_leaf = strrchr(argv[0], '/');
    char *tidied_leaf;

    if (!argv_leaf) {
	fprintf(stderr, "Can't locate / in '%s'\n", argv[0]);
	return 1;
    }

    _NSGetExecutablePath(buf, &size);
    if (size > MAXPATHLEN * MAXPATHLEN) {
	fprintf(stderr, "_NSGetExecutablePath size %u is too long for a path\n",
		(unsigned int) size);
	return 2;
    }

    buffer = (char *)malloc(size);
    if (!buffer) {
	perror("malloc");
	return 3;
    }

    result = _NSGetExecutablePath(buffer, &size);
    if (result != 0) {
	fprintf(stderr, "_NSGetExecutablePath returned %i for a size of %u\n",
		result, (unsigned int) size);
	return 4;
    }

    tidied = realpath(buffer, NULL);
    if (!tidied) {
	perror("realpath");
	return 5;
    }

    free(buffer);

    if (*tidied != '/') {
	fprintf(stderr, "Not an absolute path: '%s'\n", tidied);
	return 6;
    }

    if (strstr(tidied, "/./")) {
	fprintf(stderr, "Contains /./: '%s'\n", tidied);
	return 7;
    }

    if (strstr(tidied, "/../")) {
	fprintf(stderr, "Contains /../: '%s'\n", tidied);
	return 8;
    }

    tidied_leaf = strrchr(tidied, '/');
    if (strcmp(tidied_leaf, argv_leaf) != 0) {
	fprintf(stderr, "Leafnames differ: '%s' vs '%s'\n", argv[0], tidied);
	return 9;
    }

    free(tidied);

    return 0;
}
EOM

val=$undef
set try
if eval $compile; then
	if $run ./try; then
		echo "You can use _NSGetExecutablePath to find the executing program." >&4
		val="$define"
	else
		echo "Nope, _NSGetExecutablePath doesn't work here." >&4
	fi
else
	echo "I'm unable to compile the test program." >&4
	echo "I'll assume no _NSGetExecutablePath here." >&4
fi
$rm_try
set usensgetexecutablepath
eval $setvar

