Files
FireflyGo_Proxy/admin_self_linux.go
T

74 lines
1.8 KiB
Go

//go:build linux
// +build linux
package main
import (
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
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)
}
args := make([]string, 0, len(os.Args))
args = append(args, shellQuote(exePath))
for _, arg := range os.Args[1:] {
args = append(args, shellQuote(arg))
}
logPath := filepath.Join(os.TempDir(), "firefly-go-proxy.log")
command := fmt.Sprintf(
"cd %s && nohup %s >> %s 2>&1 &",
shellQuote(workDir),
strings.Join(args, " "),
shellQuote(logPath),
)
if pkexecPath, err := exec.LookPath("pkexec"); err == nil {
if out, err := exec.Command(pkexecPath, "sh", "-c", command).CombinedOutput(); err == nil {
return true, nil
} else if _, sudoErr := exec.LookPath("sudo"); sudoErr != nil {
return false, formatCommandError("relaunch proxy as admin with pkexec", err, out)
}
}
sudoPath, err := exec.LookPath("sudo")
if err != nil {
return false, errors.New("pkexec or sudo is required to relaunch with admin privileges")
}
if out, err := exec.Command(sudoPath, "sh", "-c", command).CombinedOutput(); err != nil {
return false, formatCommandError("relaunch proxy as admin with sudo", err, out)
}
return true, nil
}
func shellQuote(value string) string {
return "'" + strings.ReplaceAll(value, "'", "'\\''") + "'"
}
func formatCommandError(action string, err error, out []byte) error {
msg := strings.TrimSpace(string(out))
if msg == "" {
return fmt.Errorf("%s: %w", action, err)
}
return fmt.Errorf("%s: %w: %s", action, err, msg)
}