@@ -103,36 +103,39 @@ struct Syslib {
103
103
char * (* dlerror )(void );
104
104
};
105
105
106
- #define ELFCLASS32 1
107
- #define ELFDATA2LSB 1
108
- #define EM_AARCH64 183
109
- #define ET_EXEC 2
110
- #define ET_DYN 3
111
- #define PT_LOAD 1
112
- #define PT_DYNAMIC 2
113
- #define PT_INTERP 3
114
- #define EI_CLASS 4
115
- #define EI_DATA 5
116
- #define PF_X 1
117
- #define PF_W 2
118
- #define PF_R 4
119
- #define AT_PHDR 3
120
- #define AT_PHENT 4
121
- #define AT_PHNUM 5
122
- #define AT_PAGESZ 6
123
- #define AT_BASE 7
124
- #define AT_ENTRY 9
125
- #define AT_UID 11
126
- #define AT_EUID 12
127
- #define AT_GID 13
128
- #define AT_EGID 14
129
- #define AT_HWCAP 16
130
- #define AT_HWCAP2 16
131
- #define AT_SECURE 23
132
- #define AT_RANDOM 25
133
- #define AT_EXECFN 31
134
-
135
- #define AUXV_WORDS 29
106
+ #define ELFCLASS32 1
107
+ #define ELFDATA2LSB 1
108
+ #define EM_AARCH64 183
109
+ #define ET_EXEC 2
110
+ #define ET_DYN 3
111
+ #define PT_LOAD 1
112
+ #define PT_DYNAMIC 2
113
+ #define PT_INTERP 3
114
+ #define EI_CLASS 4
115
+ #define EI_DATA 5
116
+ #define PF_X 1
117
+ #define PF_W 2
118
+ #define PF_R 4
119
+ #define AT_PHDR 3
120
+ #define AT_PHENT 4
121
+ #define AT_PHNUM 5
122
+ #define AT_PAGESZ 6
123
+ #define AT_BASE 7
124
+ #define AT_FLAGS 8
125
+ #define AT_FLAGS_PRESERVE_ARGV0_BIT 0
126
+ #define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
127
+ #define AT_ENTRY 9
128
+ #define AT_UID 11
129
+ #define AT_EUID 12
130
+ #define AT_GID 13
131
+ #define AT_EGID 14
132
+ #define AT_HWCAP 16
133
+ #define AT_HWCAP2 16
134
+ #define AT_SECURE 23
135
+ #define AT_RANDOM 25
136
+ #define AT_EXECFN 31
137
+
138
+ #define AUXV_WORDS 31
136
139
137
140
/* from the xnu codebase */
138
141
#define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul
@@ -322,17 +325,7 @@ static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
322
325
if (pathlen && ps -> path [pathlen - 1 ] != '/' ) ps -> path [pathlen ++ ] = '/' ;
323
326
memmove (ps -> path + pathlen , ps -> name , ps -> namelen );
324
327
ps -> path [pathlen + ps -> namelen ] = 0 ;
325
- if (!access (ps -> path , X_OK )) {
326
- if (ps -> indirect ) {
327
- ps -> namelen -= 4 ;
328
- ps -> path [pathlen + ps -> namelen ] = 0 ;
329
- if (access (ps -> path , X_OK ) < 0 ) {
330
- Pexit (ps -> path , - errno , "access(X_OK)" );
331
- }
332
- }
333
- return 1 ;
334
- }
335
- return 0 ;
328
+ return !access (ps -> path , X_OK );
336
329
}
337
330
338
331
static char SearchPath (struct PathSearcher * ps ) {
@@ -358,21 +351,17 @@ static char FindCommand(struct PathSearcher *ps) {
358
351
ps -> path [0 ] = 0 ;
359
352
360
353
/* paths are always 100% taken literally when a slash exists
361
- $ ape foo/bar.com arg1 arg2 */
362
- if (memchr (ps -> name , '/' , ps -> namelen )) {
363
- return AccessCommand (ps , 0 );
364
- }
365
-
366
- /* we don't run files in the current directory
354
+ $ ape foo/bar.com arg1 arg2
355
+ we don't run files in the current directory
367
356
$ ape foo.com arg1 arg2
368
357
unless $PATH has an empty string entry, e.g.
369
358
$ expert PATH=":/bin"
370
359
$ ape foo.com arg1 arg2
371
360
however we will execute this
372
361
$ ape - foo.com foo.com arg1 arg2
373
362
because cosmo's execve needs it */
374
- if (ps -> literally && AccessCommand (ps , 0 )) {
375
- return 1 ;
363
+ if (ps -> literally || memchr (ps -> name , '/' , ps -> namelen )) {
364
+ return AccessCommand ( ps , 0 ) ;
376
365
}
377
366
378
367
/* otherwise search for name on $PATH */
@@ -382,7 +371,8 @@ static char FindCommand(struct PathSearcher *ps) {
382
371
static char * Commandv (struct PathSearcher * ps , const char * name ,
383
372
const char * syspath ) {
384
373
ps -> syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin" ;
385
- if (!(ps -> namelen = StrLen ((ps -> name = name )))) return 0 ;
374
+ ps -> name = name ;
375
+ if (!(ps -> namelen = ps -> indirect ? ps -> indirect : StrLen (ps -> name ))) return 0 ;
386
376
if (ps -> namelen + 1 > sizeof (ps -> path )) return 0 ;
387
377
if (FindCommand (ps )) {
388
378
return ps -> path ;
@@ -861,25 +851,27 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
861
851
auxv [7 ] = ebuf -> ehdr .e_entry ;
862
852
auxv [8 ] = AT_PAGESZ ;
863
853
auxv [9 ] = pagesz ;
864
- auxv [10 ] = AT_UID ;
865
- auxv [11 ] = getuid ();
866
- auxv [12 ] = AT_EUID ;
867
- auxv [13 ] = geteuid ();
868
- auxv [14 ] = AT_GID ;
869
- auxv [15 ] = getgid ();
870
- auxv [16 ] = AT_EGID ;
871
- auxv [17 ] = getegid ();
872
- auxv [18 ] = AT_HWCAP ;
873
- auxv [19 ] = 0xffb3ffffu ;
874
- auxv [20 ] = AT_HWCAP2 ;
875
- auxv [21 ] = 0x181 ;
876
- auxv [22 ] = AT_SECURE ;
877
- auxv [23 ] = issetugid ();
878
- auxv [24 ] = AT_RANDOM ;
879
- auxv [25 ] = (long )M -> rando ;
880
- auxv [26 ] = AT_EXECFN ;
881
- auxv [27 ] = (long )execfn ;
882
- auxv [28 ] = 0 ;
854
+ auxv [10 ] = AT_FLAGS ;
855
+ auxv [11 ] = M -> ps .literally ? AT_FLAGS_PRESERVE_ARGV0 : 0 ;
856
+ auxv [12 ] = AT_UID ;
857
+ auxv [13 ] = getuid ();
858
+ auxv [14 ] = AT_EUID ;
859
+ auxv [15 ] = geteuid ();
860
+ auxv [16 ] = AT_GID ;
861
+ auxv [17 ] = getgid ();
862
+ auxv [18 ] = AT_EGID ;
863
+ auxv [19 ] = getegid ();
864
+ auxv [20 ] = AT_HWCAP ;
865
+ auxv [21 ] = 0xffb3ffffu ;
866
+ auxv [22 ] = AT_HWCAP2 ;
867
+ auxv [23 ] = 0x181 ;
868
+ auxv [24 ] = AT_SECURE ;
869
+ auxv [25 ] = issetugid ();
870
+ auxv [26 ] = AT_RANDOM ;
871
+ auxv [27 ] = (long )M -> rando ;
872
+ auxv [28 ] = AT_EXECFN ;
873
+ auxv [29 ] = (long )execfn ;
874
+ auxv [30 ] = 0 ;
883
875
884
876
/* we're now ready to load */
885
877
Spawn (exe , fd , sp , e , p , & M -> lib , M -> ps .path );
@@ -891,7 +883,7 @@ int main(int argc, char **argv, char **envp) {
891
883
struct ApeLoader * M ;
892
884
long * sp , * sp2 , * auxv ;
893
885
union ElfEhdrBuf * ebuf ;
894
- char * p , * pe , * exe , * prog , * execfn , * shell ;
886
+ char * p , * pe , * exe , * prog , * execfn ;
895
887
896
888
/* allocate loader memory in program's arg block */
897
889
n = sizeof (struct ApeLoader );
@@ -954,12 +946,16 @@ int main(int argc, char **argv, char **envp) {
954
946
M -> lib .dlerror = dlerror ;
955
947
956
948
/* getenv("_") is close enough to at_execfn */
957
- execfn = argc > 0 ? argv [ 0 ] : 0 ;
949
+ execfn = 0 ;
958
950
for (i = 0 ; envp [i ]; ++ i ) {
959
951
if (envp [i ][0 ] == '_' && envp [i ][1 ] == '=' ) {
960
952
execfn = envp [i ] + 2 ;
961
953
}
962
954
}
955
+ prog = GetEnv (envp + i + 1 , "executable_path" );
956
+ if (!execfn ) {
957
+ execfn = prog ;
958
+ }
963
959
964
960
/* sneak the system five abi back out of args */
965
961
sp = (long * )(argv - 1 );
@@ -981,8 +977,8 @@ int main(int argc, char **argv, char **envp) {
981
977
sp = sp2 ;
982
978
983
979
/* interpret command line arguments */
984
- if ((M -> ps .indirect = argc > 0 ? GetIndirectOffset (argv [ 0 ]) : 0 )) {
985
- /* if argv[0] is $prog.ape, then we strip off the .ape and run
980
+ if ((M -> ps .indirect = GetIndirectOffset (prog ) )) {
981
+ /* if called as $prog.ape, then strip off the .ape and run the
986
982
$prog. This allows you to use symlinks to trick the OS when
987
983
a native executable is required. For example, let's say you
988
984
want to use the APE binary /opt/cosmos/bin/bash as a system
@@ -991,13 +987,7 @@ int main(int argc, char **argv, char **envp) {
991
987
but it will if you say:
992
988
ln -sf /usr/local/bin/ape /opt/cosmos/bin/bash.ape
993
989
and then use #!/opt/cosmos/bin/bash.ape instead. */
994
- M -> ps .literally = 0 ;
995
- if (* argv [0 ] == '-' && (shell = GetEnv (envp , "SHELL" )) &&
996
- !StrCmp (argv [0 ] + 1 , BaseName (shell ))) {
997
- execfn = prog = shell ;
998
- } else {
999
- prog = (char * )sp [1 ];
1000
- }
990
+ M -> ps .literally = 1 ;
1001
991
argc = sp [0 ];
1002
992
argv = (char * * )(sp + 1 );
1003
993
} else if ((M -> ps .literally = argc >= 3 && !StrCmp (argv [1 ], "-" ))) {
0 commit comments