Files
2026-11-02 23:37:45 -05:00

105 lines
3.0 KiB
Go

// Copyright (c) 2026 Storm Dragon
// SPDX-License-Identifier: GPL-3.0-or-later
package wine
import (
"bytes"
"os"
"path/filepath"
"sort"
"strings"
"git.stormux.org/storm/cthulhu/internal/config"
)
func program_name(commandLine string) string {
name := strings.SplitN(commandLine, "\x00", 2)[0]
return filepath.Base(strings.ReplaceAll(strings.ToLower(strings.TrimSpace(name)), "\\", "/"))
}
func wine_loader(exe, configured string) string {
if executable(configured) {
// Protontricks' proxy requires its own runtime environment. Join the
// existing server with the actual Proton loader instead.
file, err := os.Open(configured)
if err == nil {
data := make([]byte, 8192)
count, _ := file.Read(data)
file.Close()
if !bytes.Contains(data[:count], []byte("PROTONTRICKS_STEAM_RUNTIME")) {
return configured
}
}
}
directory := filepath.Dir(exe)
for _, name := range []string{strings.TrimSuffix(filepath.Base(exe), "-preloader"), "wine"} {
candidate := filepath.Join(directory, name)
if executable(candidate) {
return candidate
}
}
for range 5 {
parent := filepath.Dir(directory)
if parent == directory || parent == string(filepath.Separator) {
break
}
directory = parent
for _, name := range []string{"wine", "wine64"} {
candidate := filepath.Join(directory, "bin", name)
if executable(candidate) {
return candidate
}
}
}
return ""
}
// wholesale_controller_only reports whether the whole helper must run
// without dialog reading. Only the global controller-only switch and the
// environment override select it here; a helper binary remembered as
// unconfirmed (see Manager.helper_unconfirmed) is the third trigger. A
// listed program by itself never selects wholesale mode: the helper gates
// it natively while other programs in the prefix keep dialog reading.
func wholesale_controller_only(settings Settings) bool {
if settings.ControllerOnly {
return true
}
override := os.Getenv("WINE_ACCESS_NO_DIALOG_READER")
return override != "" && override != "0"
}
// exclusion_names returns the hook-exclusion program names exactly as the
// helper will store them: validated at the process boundary, lowercased,
// deduplicated case-insensitively, and sorted. The validation mirrors the
// helper's own rules so the count sent here matches the count its ready
// record reports.
func exclusion_names(settings Settings) []string {
seen := make(map[string]bool, len(settings.ExcludedPrograms))
var names []string
for _, name := range settings.ExcludedPrograms {
if !config.ValidWineProgramName(name) {
continue
}
lower := strings.ToLower(name)
if seen[lower] {
continue
}
seen[lower] = true
names = append(names, lower)
}
sort.Strings(names)
return names
}
func helper_arguments(controllerOnly bool, settings Settings) []string {
var arguments []string
for _, name := range exclusion_names(settings) {
arguments = append(arguments, "--exclude-hook-program", name)
}
if controllerOnly {
arguments = append(arguments, "--no-dialog-reader")
}
return arguments
}