Files
FireflyGo_Proxy/admin_self_darwin.go
T

78 lines
1.7 KiB
Go

//go:build darwin
// +build darwin
package main
import (
"fmt"
"os"
"os/exec"
"os/signal"
"strconv"
"strings"
"syscall"
)
func relaunchWithAdminIfNeeded() (bool, error) {
if os.Geteuid() == 0 {
return false, nil
}
exePath, err := os.Executable()
if err != nil {
return false, fmt.Errorf("get executable path: %w", err)
}
workDir, err := os.Getwd()
if err != nil {
return false, fmt.Errorf("get working directory: %w", err)
}
wrapperPID := os.Getpid()
launcherPID := os.Getppid()
args := make([]string, 0, len(os.Args))
args = append(args, shellQuote(exePath))
for _, arg := range os.Args[1:] {
args = append(args, shellQuote(arg))
}
if !hasFlagArg("parent-pid") {
args = append(args, shellQuote("-parent-pid"), shellQuote(strconv.Itoa(wrapperPID)))
}
command := fmt.Sprintf(
"cd %s && %s > /dev/null 2>&1 &",
shellQuote(workDir),
strings.Join(args, " "),
)
script := fmt.Sprintf("do shell script %s with administrator privileges", appleScriptString(command))
if out, err := exec.Command("osascript", "-e", script).CombinedOutput(); err != nil {
return false, formatCommandError("relaunch proxy as admin", err, out)
}
waitForRelaunchedProxyShutdown(launcherPID)
return true, nil
}
func waitForRelaunchedProxyShutdown(launcherPID int) {
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
defer signal.Stop(stop)
select {
case <-stop:
case <-parentProcessDone(launcherPID):
}
}
func hasFlagArg(name string) bool {
for _, arg := range os.Args[1:] {
trimmed := strings.TrimLeft(arg, "-")
if trimmed == name || strings.HasPrefix(trimmed, name+"=") {
return true
}
}
return false
}