mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-16 14:49:09 +02:00
* fix(cli): recover daemon executable path Co-authored-by: multica-agent <github@multica.ai> * fix(daemon): reuse executable fallback for restart Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: Eve <eve@multica-ai.local> Co-authored-by: multica-agent <github@multica.ai>
51 lines
1.3 KiB
Go
51 lines
1.3 KiB
Go
// Package selfexec resolves the executable backing the current process.
|
|
package selfexec
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
)
|
|
|
|
// Resolve prefers the OS-reported executable path. Some launch environments
|
|
// can omit that metadata, so it falls back to argv[0] using normal executable
|
|
// lookup semantics instead of treating a bare command name as relative to the
|
|
// current directory.
|
|
func Resolve() (string, error) {
|
|
return resolveWith(os.Executable, os.Args)
|
|
}
|
|
|
|
func resolveWith(osExecutable func() (string, error), args []string) (string, error) {
|
|
exePath, err := osExecutable()
|
|
if err == nil {
|
|
return exePath, nil
|
|
}
|
|
osExecutableErr := fmt.Errorf("os.Executable: %w", err)
|
|
|
|
if len(args) == 0 || args[0] == "" {
|
|
return "", errors.Join(osExecutableErr, errors.New("argv[0] is empty"))
|
|
}
|
|
|
|
candidate, fallbackErr := exec.LookPath(args[0])
|
|
if fallbackErr == nil {
|
|
candidate, fallbackErr = filepath.Abs(candidate)
|
|
}
|
|
if fallbackErr == nil {
|
|
var info os.FileInfo
|
|
info, fallbackErr = os.Stat(candidate)
|
|
if fallbackErr == nil && !info.Mode().IsRegular() {
|
|
fallbackErr = fmt.Errorf("%s is not a regular file", candidate)
|
|
}
|
|
}
|
|
if fallbackErr != nil {
|
|
return "", errors.Join(
|
|
osExecutableErr,
|
|
fmt.Errorf("resolve argv[0] %q: %w", args[0], fallbackErr),
|
|
)
|
|
}
|
|
|
|
return candidate, nil
|
|
}
|