Merged changes from hunter. Attempt to fix cthulhu announcing modifiers when suspended for xterm.

This commit is contained in:
Storm Dragon committed 2026-10-31 16:07:29 -04:00
1 parent 27867a48cb
commit f2cc47c8a0
24 files changed
+679 -67

No files matched your search

+163
View File
@@ -0,0 +1,163 @@
// Copyright (c) 2026 Storm Dragon
// SPDX-License-Identifier: GPL-3.0-or-later
package wine
import (
"bytes"
"crypto/sha256"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
)
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 ""
}
func (manager *Manager) controller_only(source prefix) bool {
if manager.ControllerOnly || os.Getenv("WINE_ACCESS_NO_DIALOG_READER") != "" && os.Getenv("WINE_ACCESS_NO_DIALOG_READER") != "0" {
return true
}
for _, name := range manager.ExcludedPrograms {
if source.programs[strings.ToLower(name)] {
return true
}
}
return false
}
func (manager *Manager) helper_arguments(controllerOnly bool) []string {
var arguments []string
names := append([]string(nil), manager.ExcludedPrograms...)
sort.Strings(names)
for _, name := range names {
// Validate again at the process boundary; never pass paths or separators
// into the native hook exclusion list.
if name != "" && !strings.ContainsAny(name, "\x00\r\n/\\") {
arguments = append(arguments, "--exclude-hook-program", strings.ToLower(name))
}
}
if controllerOnly {
arguments = append(arguments, "--no-dialog-reader")
}
return arguments
}
// A pressure-vessel wineserver cannot see the host's /usr. Publish complete,
// immutable helper sets in the home-mounted state directory. Never overwrite
// an older set: running processes may still have its sidecar mapped.
func stage_helper(helper string, environment map[string]string) (string, error) {
if _, present := environment["PRESSURE_VESSEL_RUNTIME"]; !present {
return helper, nil
}
stateHome := os.Getenv("XDG_STATE_HOME")
if stateHome == "" {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
stateHome = filepath.Join(home, ".local", "state")
}
if !filepath.IsAbs(stateHome) {
return "", fmt.Errorf("Wine helper state directory must be absolute")
}
names := []string{filepath.Base(helper), filepath.Base(helper) + ".so", "wine-access-menu.dll", "wine-access-menu32.dll", "wine-access-menu-host32.exe"}
contents := make(map[string][]byte)
modes := make(map[string]os.FileMode)
digest := sha256.New()
for _, name := range names {
path := filepath.Join(filepath.Dir(helper), name)
data, err := os.ReadFile(path)
if err != nil {
return "", fmt.Errorf("read helper set: %w", err)
}
info, err := os.Stat(path)
if err != nil {
return "", err
}
contents[name], modes[name] = data, 0600
if info.Mode().Perm()&0111 != 0 {
modes[name] = 0700
}
fmt.Fprintf(digest, "%s\x00%d\x00%d\x00", name, len(data), modes[name])
digest.Write(data)
}
root := filepath.Join(stateHome, "cthulhu", "wine-access", "helper")
if err := os.MkdirAll(root, 0700); err != nil {
return "", err
}
stage := filepath.Join(root, fmt.Sprintf("%x", digest.Sum(nil)))
if _, err := os.Stat(stage); os.IsNotExist(err) {
temporary, err := os.MkdirTemp(root, ".stage-")
if err != nil {
return "", err
}
defer os.RemoveAll(temporary)
for _, name := range names {
if err := os.WriteFile(filepath.Join(temporary, name), contents[name], modes[name]); err != nil {
return "", err
}
}
if err := os.Rename(temporary, stage); err != nil {
if info, statErr := os.Stat(stage); statErr != nil || !info.IsDir() {
return "", err
}
}
}
for _, name := range names {
path := filepath.Join(stage, name)
data, err := os.ReadFile(path)
if err != nil {
return "", err
}
info, err := os.Stat(path)
if err != nil {
return "", err
}
if !bytes.Equal(data, contents[name]) || info.Mode().Perm() != modes[name] {
return "", fmt.Errorf("incomplete or modified staged Wine helper")
}
}
return filepath.Join(stage, filepath.Base(helper)), nil
}