@@ -232,10 +232,18 @@ func call_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
232232
233233//go:linkname os_runtime_executable_path os.runtime_executable_path
234234func os_runtime_executable_path () string {
235- argv := (* unsafe .Pointer )(unsafe .Pointer (main_argv ))
235+ return executablePath
236+ }
237+
238+ var executablePath string
236239
240+ func platform_argv (argc int32 , argv * unsafe.Pointer ) {
241+ executablePath = executable_path (argc , argv )
242+ }
243+
244+ func executable_path (argc int32 , argv * unsafe.Pointer ) string {
237245 // skip over argv
238- argv = (* unsafe .Pointer )(unsafe .Add (unsafe .Pointer (argv ), (uintptr (main_argc )+ 1 )* unsafe .Sizeof (argv )))
246+ argv = (* unsafe .Pointer )(unsafe .Add (unsafe .Pointer (argv ), (uintptr (argc )+ 1 )* unsafe .Sizeof (argv )))
239247
240248 // skip over envv
241249 for (* argv ) != nil {
@@ -251,11 +259,21 @@ func os_runtime_executable_path() string {
251259 length : length ,
252260 ptr : (* byte )(cstr ),
253261 }
254- executablePath := * (* string )(unsafe .Pointer (& argString ))
262+ path := * (* string )(unsafe .Pointer (& argString ))
255263
256264 // strip "executable_path=" prefix if available, it's added after OS X 10.11.
257- executablePath = stringsTrimPrefix (executablePath , "executable_path=" )
258- return executablePath
265+ path = stringsTrimPrefix (path , "executable_path=" )
266+
267+ if path != "" && path [0 ] == '/' {
268+ // absolute path
269+ return path
270+ }
271+
272+ cwd := getcwd ()
273+ if cwd != "" {
274+ path = joinPath (cwd , path )
275+ }
276+ return path
259277}
260278
261279func stringsTrimPrefix (s , prefix string ) string {
@@ -264,3 +282,40 @@ func stringsTrimPrefix(s, prefix string) string {
264282 }
265283 return s
266284}
285+
286+ func joinPath (dir , name string ) string {
287+ if len (dir ) > 0 && dir [len (dir )- 1 ] == '/' {
288+ return dir + name
289+ }
290+ return dir + "/" + name
291+ }
292+
293+ // from syscall
294+ func getcwd () string {
295+ const pathMax = 1024
296+ var buf [4 * pathMax ]byte
297+ s := libc_getcwd (& buf [0 ], uint (len (buf )))
298+ if s == nil {
299+ return ""
300+ }
301+ n := clen (buf [:])
302+ if n < 1 {
303+ return ""
304+ }
305+ return string (buf [:n ])
306+ }
307+
308+ // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
309+ func clen (n []byte ) int {
310+ for i := 0 ; i < len (n ); i ++ {
311+ if n [i ] == 0 {
312+ return i
313+ }
314+ }
315+ return len (n )
316+ }
317+
318+ // char *getcwd(char *buf, size_t size)
319+ //
320+ //export getcwd
321+ func libc_getcwd (buf * byte , size uint ) * byte
0 commit comments