This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Improved $^X absolute pathname conversion.
[metaconfig.git] / U / perl / usensgetexecutablepath.U
1 ?MAKE:usensgetexecutablepath: cat rm_try Compile run Setvar
2 ?MAKE:  -pick add $@ %<
3 ?S:usensgetexecutablepath:
4 ?S:     This symbol, if defined, indicates that we can use _NSGetExecutablePath
5 ?S:     and realpath to get a full path for the executable, and hence convert
6 ?S:     $^X to an absolute path.
7 ?S:.
8 ?C:USE_NSGETEXECUTABLEPATH:
9 ?C:     This symbol, if defined, indicates that we can use _NSGetExecutablePath
10 ?C:     and realpath to get a full path for the executable, and hence convert
11 ?C:     $^X to an absolute path.
12 ?C:.
13 ?H:#$usensgetexecutablepath USE_NSGETEXECUTABLEPATH     /**/
14 ?H:.
15 ?LINT:set usensgetexecutablepath
16 ?F:!try
17 : Determine if we can use _NSGetExecutablePath to find executing program
18 echo " "
19 echo "Determining whether we can use _NSGetExecutablePath to find executing program..." >&4
20 $cat >try.c <<'EOM'
21 /* Intentionally a long probe as I'd like to sanity check that the exact
22    approach is going to work, as thinking it will work, but only having it
23    part working at runtime is worse than not having it.  */
24 #include <mach-o/dyld.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/param.h>
28 #include <string.h>
29
30 int
31 main(int argc, char **argv) {
32     char buf[1];
33     uint32_t size = sizeof(buf);
34     int result;
35     char *buffer;
36     char *tidied;
37     char *argv_leaf = strrchr(argv[0], '/');
38     char *tidied_leaf;
39
40     if (!argv_leaf) {
41         fprintf(stderr, "Can't locate / in '%s'\n", argv[0]);
42         return 1;
43     }
44
45     _NSGetExecutablePath(buf, &size);
46     if (size > MAXPATHLEN * MAXPATHLEN) {
47         fprintf(stderr, "_NSGetExecutablePath size %u is too long for a path\n",
48                 (unsigned int) size);
49         return 2;
50     }
51
52     buffer = malloc(size);
53     if (!buffer) {
54         perror("malloc");
55         return 3;
56     }
57
58     result = _NSGetExecutablePath(buffer, &size);
59     if (result != 0) {
60         fprintf(stderr, "_NSGetExecutablePath returned %i for a size of %u\n",
61                 result, (unsigned int) size);
62         return 4;
63     }
64
65     tidied = realpath(buffer, NULL);
66     if (!tidied) {
67         perror("realpath");
68         return 5;
69     }
70
71     free(buffer);
72
73     if (*tidied != '/') {
74         fprintf(stderr, "Not an absolute path: '%s'\n", tidied);
75         return 6;
76     }
77
78     if (strstr(tidied, "/./")) {
79         fprintf(stderr, "Contains /./: '%s'\n", tidied);
80         return 7;
81     }
82
83     if (strstr(tidied, "/../")) {
84         fprintf(stderr, "Contains /../: '%s'\n", tidied);
85         return 8;
86     }
87
88     tidied_leaf = strrchr(tidied, '/');
89     if (strcmp(tidied_leaf, argv_leaf) != 0) {
90         fprintf(stderr, "Leafnames differ: '%s' vs '%s'\n", argv[0], tidied);
91         return 9;
92     }
93
94     free(tidied);
95
96     return 0;
97 }
98 EOM
99
100 val=$undef
101 set try
102 if eval $compile_ok; then
103         if $run ./try; then
104                 echo "You can use _NSGetExecutablePath to find the executing program." >&4
105                 val="$define"
106         else
107                 echo "Nope, _NSGetExecutablePath doesn't work here." >&4
108         fi
109 else
110         echo "I'm unable to compile the test program." >&4
111         echo "I'll assume no _NSGetExecutablePath here." >&4
112 fi
113 $rm_try
114 set usensgetexecutablepath
115 eval $setvar
116