diff --git a/BrewBar/BrewBarApp.swift b/BrewBar/BrewBarApp.swift index 44b7ecf..9df1548 100644 --- a/BrewBar/BrewBarApp.swift +++ b/BrewBar/BrewBarApp.swift @@ -174,6 +174,23 @@ class AppDelegate: NSObject, NSApplicationDelegate { return "brew" } + /// Written once per launch; sudo runs it to show a GUI password dialog + /// whenever brew needs admin rights (no terminal is attached to Process). + static let askpassURL: URL = { + let dir = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] + .appendingPathComponent("BrewBar", isDirectory: true) + try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + + let url = dir.appendingPathComponent("askpass.sh") + let script = """ + #!/bin/zsh + osascript -e 'display dialog "BrewBar needs your administrator password to continue:" default answer "" with hidden answer with title "BrewBar" with icon caution buttons {"Cancel", "OK"} default button "OK"' -e 'text returned of result' + """ + try? script.write(to: url, atomically: true, encoding: .utf8) + try? FileManager.default.setAttributes([.posixPermissions: 0o700], ofItemAtPath: url.path) + return url + }() + func runBrew(_ command: String, completion: @escaping (String) -> Void = { _ in }) { DispatchQueue.global().async { let brew = self.resolveBrewPath() @@ -186,6 +203,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { process.executableURL = URL(fileURLWithPath: "/bin/zsh") process.arguments = ["-c", fullCommand] + var environment = ProcessInfo.processInfo.environment + environment["SUDO_ASKPASS"] = Self.askpassURL.path + process.environment = environment + let pipe = Pipe() process.standardOutput = pipe process.standardError = pipe