mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
feat: moved from the AppleScript for asking a root access when manipulating the fans to the Helper (SMJobBless + XPC) (#1173)
This commit is contained in:
@@ -1002,66 +1002,127 @@ public class SettingsContainerView: NSStackView {
|
||||
|
||||
public class SMCHelper {
|
||||
public static let shared = SMCHelper()
|
||||
private let smc: String
|
||||
|
||||
public init() {
|
||||
self.smc = Bundle.main.path(forResource: "smc", ofType: nil)!
|
||||
}
|
||||
private var connection: NSXPCConnection? = nil
|
||||
|
||||
public func setFanSpeed(_ id: Int, speed: Int) {
|
||||
if !self.checkRights() {
|
||||
if !self.ensureRights() {
|
||||
return
|
||||
helperStatus { installed in
|
||||
if !installed {
|
||||
self.install()
|
||||
}
|
||||
guard let helper = self.helper(nil) else { return }
|
||||
|
||||
helper.setFanSpeed(id: id, value: speed) { result in
|
||||
if let result, !result.isEmpty {
|
||||
print(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = syncShell("\(self.smc) fan -id \(id) -v \(speed)")
|
||||
}
|
||||
|
||||
public func setFanMode(_ id: Int, mode: Int) {
|
||||
if !self.checkRights() {
|
||||
if !self.ensureRights() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_ = syncShell("\(self.smc) fan -id \(id) -m \(mode)")
|
||||
}
|
||||
|
||||
public func checkRights() -> Bool {
|
||||
do {
|
||||
let attributes = try FileManager.default.attributesOfItem(atPath: self.smc)
|
||||
guard let owner = attributes[FileAttributeKey(rawValue: "NSFileOwnerAccountName")] as? String,
|
||||
let ownerGroup = attributes[FileAttributeKey(rawValue: "NSFileGroupOwnerAccountName")] as? String,
|
||||
let permissions = attributes[FileAttributeKey(rawValue: "NSFilePosixPermissions")] as? Int else {
|
||||
print("some of the smc attributes is missing")
|
||||
return false
|
||||
helperStatus { installed in
|
||||
if !installed {
|
||||
self.install()
|
||||
}
|
||||
guard let helper = self.helper(nil) else { return }
|
||||
|
||||
if owner == "root" && ownerGroup == "admin" && permissions == 3437 {
|
||||
return true
|
||||
helper.setFanMode(id: id, mode: mode) { result in
|
||||
if let result, !result.isEmpty {
|
||||
print(result)
|
||||
}
|
||||
}
|
||||
} catch let error {
|
||||
print("get smc attributes, \(error)")
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private func ensureRights() -> Bool {
|
||||
guard let script = NSAppleScript(source: "do shell script \"/usr/sbin/chown root:admin \(self.smc) && /bin/chmod 6555 \(self.smc)\" with administrator privileges") else {
|
||||
return false
|
||||
public func isActive() -> Bool {
|
||||
return self.connection != nil
|
||||
}
|
||||
|
||||
private func helperStatus(completion: @escaping (_ installed: Bool) -> Void) {
|
||||
let helperURL = Bundle.main.bundleURL.appendingPathComponent("Contents/Library/LaunchServices/eu.exelban.Stats.SMC.Helper")
|
||||
guard
|
||||
let helperBundleInfo = CFBundleCopyInfoDictionaryForURL(helperURL as CFURL) as? [String: Any],
|
||||
let helperVersion = helperBundleInfo["CFBundleShortVersionString"] as? String,
|
||||
let helper = self.helper(completion) else {
|
||||
completion(false)
|
||||
return
|
||||
}
|
||||
|
||||
var err: NSDictionary? = nil
|
||||
script.executeAndReturnError(&err)
|
||||
if err != nil {
|
||||
print("cannot upgrade owner to root: \(String(describing: err))")
|
||||
return false
|
||||
helper.version { installedHelperVersion in
|
||||
completion(installedHelperVersion == helperVersion)
|
||||
}
|
||||
}
|
||||
|
||||
private func install() {
|
||||
var authRef: AuthorizationRef?
|
||||
var authStatus = AuthorizationCreate(nil, nil, [.preAuthorize], &authRef)
|
||||
|
||||
guard authStatus == errAuthorizationSuccess else {
|
||||
print("Unable to get a valid empty authorization reference to load Helper daemon")
|
||||
return
|
||||
}
|
||||
|
||||
return true
|
||||
let authItem = kSMRightBlessPrivilegedHelper.withCString { authorizationString in
|
||||
AuthorizationItem(name: authorizationString, valueLength: 0, value: nil, flags: 0)
|
||||
}
|
||||
|
||||
let pointer = UnsafeMutablePointer<AuthorizationItem>.allocate(capacity: 1)
|
||||
pointer.initialize(to: authItem)
|
||||
|
||||
defer {
|
||||
pointer.deinitialize(count: 1)
|
||||
pointer.deallocate()
|
||||
}
|
||||
|
||||
var authRights = AuthorizationRights(count: 1, items: pointer)
|
||||
|
||||
let flags: AuthorizationFlags = [.interactionAllowed, .extendRights, .preAuthorize]
|
||||
authStatus = AuthorizationCreate(&authRights, nil, flags, &authRef)
|
||||
|
||||
guard authStatus == errAuthorizationSuccess else {
|
||||
print("Unable to get a valid loading authorization reference to load Helper daemon")
|
||||
return
|
||||
}
|
||||
|
||||
var error: Unmanaged<CFError>?
|
||||
if SMJobBless(kSMDomainUserLaunchd, "eu.exelban.Stats.SMC.Helper" as CFString, authRef, &error) == false {
|
||||
let blessError = error!.takeRetainedValue() as Error
|
||||
print("Error while installing the Helper: \(blessError.localizedDescription)")
|
||||
return
|
||||
}
|
||||
|
||||
AuthorizationFree(authRef!, [])
|
||||
}
|
||||
|
||||
private func helperConnection() -> NSXPCConnection? {
|
||||
guard self.connection == nil else {
|
||||
return self.connection
|
||||
}
|
||||
|
||||
let connection = NSXPCConnection(machServiceName: "eu.exelban.Stats.SMC.Helper", options: .privileged)
|
||||
connection.exportedObject = self
|
||||
connection.remoteObjectInterface = NSXPCInterface(with: HelperProtocol.self)
|
||||
connection.invalidationHandler = {
|
||||
self.connection?.invalidationHandler = nil
|
||||
OperationQueue.main.addOperation {
|
||||
self.connection = nil
|
||||
}
|
||||
}
|
||||
|
||||
self.connection = connection
|
||||
self.connection?.resume()
|
||||
|
||||
return self.connection
|
||||
}
|
||||
|
||||
private func helper(_ completion: ((Bool) -> Void)?) -> HelperProtocol? {
|
||||
guard let helper = self.helperConnection()?.remoteObjectProxyWithErrorHandler({ _ in
|
||||
if let onCompletion = completion { onCompletion(false) }
|
||||
}) as? HelperProtocol else { return nil }
|
||||
|
||||
helper.setSMCPath(Bundle.main.path(forResource: "smc", ofType: nil)!)
|
||||
|
||||
return helper
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
5
Kit/scripts/uninstall.sh
Normal file
5
Kit/scripts/uninstall.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#! /bin/sh
|
||||
|
||||
sudo launchctl unload /Library/LaunchDaemons/eu.exelban.Stats.SMC.Helper.plist
|
||||
sudo rm /Library/LaunchDaemons/eu.exelban.Stats.SMC.Helper.plist
|
||||
sudo rm /Library/PrivilegedHelperTools/eu.exelban.Stats.SMC.Helper
|
||||
@@ -57,9 +57,7 @@ public class Sensors: Module {
|
||||
}
|
||||
|
||||
public override func willTerminate() {
|
||||
if !SMCHelper.shared.checkRights() {
|
||||
return
|
||||
}
|
||||
guard SMCHelper.shared.isActive() else { return }
|
||||
|
||||
self.sensorsReader.list.filter({ $0 is Fan }).forEach { (s: Sensor_p) in
|
||||
if let f = s as? Fan, let mode = f.customMode {
|
||||
|
||||
@@ -313,9 +313,7 @@ internal class FanView: NSStackView {
|
||||
private var maxBtn: NSButton? = nil
|
||||
|
||||
private var speedState: Bool {
|
||||
get {
|
||||
return Store.shared.bool(key: "Sensors_speed", defaultValue: false)
|
||||
}
|
||||
Store.shared.bool(key: "Sensors_speed", defaultValue: false)
|
||||
}
|
||||
private var speed: Double {
|
||||
get {
|
||||
@@ -328,9 +326,7 @@ internal class FanView: NSStackView {
|
||||
private var resetModeAfterSleep: Bool = false
|
||||
|
||||
private var horizontalMargin: CGFloat {
|
||||
get {
|
||||
return self.edgeInsets.top + self.edgeInsets.bottom + (self.spacing*CGFloat(self.arrangedSubviews.count))
|
||||
}
|
||||
self.edgeInsets.top + self.edgeInsets.bottom + (self.spacing*CGFloat(self.arrangedSubviews.count))
|
||||
}
|
||||
|
||||
private var willSleepMode: FanMode? = nil
|
||||
@@ -634,7 +630,7 @@ internal class FanView: NSStackView {
|
||||
}
|
||||
|
||||
@objc private func sleepListener(aNotification: NSNotification) {
|
||||
guard SMCHelper.shared.checkRights() && self.fan.customMode != .automatic else { return }
|
||||
guard SMCHelper.shared.isActive() && self.fan.customMode != .automatic else { return }
|
||||
|
||||
self.willSleepMode = self.fan.customMode
|
||||
self.willSleepSpeed = self.fan.customSpeed
|
||||
|
||||
18
SMC/Helper/Info.plist
Normal file
18
SMC/Helper/Info.plist
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>eu.exelban.Stats.SMC.Helper</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>eu.exelban.Stats.SMC.Helper</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>SMAuthorizedClients</key>
|
||||
<array>
|
||||
<string>identifier "eu.exelban.Stats" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
13
SMC/Helper/Launchd.plist
Normal file
13
SMC/Helper/Launchd.plist
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>eu.exelban.Stats.SMC.Helper</string>
|
||||
<key>MachServices</key>
|
||||
<dict>
|
||||
<key>eu.exelban.Stats.SMC.Helper</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
97
SMC/Helper/main.swift
Normal file
97
SMC/Helper/main.swift
Normal file
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// main.swift
|
||||
// Helper
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 17/11/2022
|
||||
// Using Swift 5.0
|
||||
// Running on macOS 13.0
|
||||
//
|
||||
// Copyright © 2022 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
let helper = Helper()
|
||||
helper.run()
|
||||
|
||||
class Helper: NSObject, NSXPCListenerDelegate, HelperProtocol {
|
||||
private let listener: NSXPCListener
|
||||
|
||||
private var connections = [NSXPCConnection]()
|
||||
private var shouldQuit = false
|
||||
private var shouldQuitCheckInterval = 1.0
|
||||
|
||||
private var smc: String? = nil
|
||||
|
||||
override init() {
|
||||
self.listener = NSXPCListener(machServiceName: "eu.exelban.Stats.SMC.Helper")
|
||||
super.init()
|
||||
self.listener.delegate = self
|
||||
}
|
||||
|
||||
public func run() {
|
||||
self.listener.resume()
|
||||
while !self.shouldQuit {
|
||||
RunLoop.current.run(until: Date(timeIntervalSinceNow: self.shouldQuitCheckInterval))
|
||||
}
|
||||
}
|
||||
|
||||
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection connection: NSXPCConnection) -> Bool {
|
||||
connection.exportedInterface = NSXPCInterface(with: HelperProtocol.self)
|
||||
connection.exportedObject = self
|
||||
connection.invalidationHandler = {
|
||||
if let connectionIndex = self.connections.firstIndex(of: connection) {
|
||||
self.connections.remove(at: connectionIndex)
|
||||
}
|
||||
if self.connections.isEmpty {
|
||||
self.shouldQuit = true
|
||||
}
|
||||
}
|
||||
|
||||
self.connections.append(connection)
|
||||
connection.resume()
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Helper {
|
||||
func version(completion: (String) -> Void) {
|
||||
completion(Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "0")
|
||||
}
|
||||
func setSMCPath(_ path: String) {
|
||||
self.smc = path
|
||||
}
|
||||
|
||||
func setFanMode(id: Int, mode: Int, completion: (String?) -> Void) {
|
||||
guard let smc = self.smc else {
|
||||
completion("missing smc tool")
|
||||
return
|
||||
}
|
||||
let result = syncShell("\(smc) fan \(id) -m \(mode)")
|
||||
completion(result)
|
||||
}
|
||||
|
||||
func setFanSpeed(id: Int, value: Int, completion: (String?) -> Void) {
|
||||
guard let smc = self.smc else {
|
||||
completion("missing smc tool")
|
||||
return
|
||||
}
|
||||
let result = syncShell("\(smc) fan \(id) -v \(value)")
|
||||
completion(result)
|
||||
}
|
||||
|
||||
public func syncShell(_ args: String) -> String {
|
||||
let task = Process()
|
||||
task.launchPath = "/bin/sh"
|
||||
task.arguments = ["-c", args]
|
||||
let pipe = Pipe()
|
||||
|
||||
task.standardOutput = pipe
|
||||
task.launch()
|
||||
task.waitUntilExit()
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
return String(data: data, encoding: .utf8)!
|
||||
}
|
||||
}
|
||||
20
SMC/Helper/protocol.swift
Normal file
20
SMC/Helper/protocol.swift
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// protocol.swift
|
||||
// Helper
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 17/11/2022
|
||||
// Using Swift 5.0
|
||||
// Running on macOS 13.0
|
||||
//
|
||||
// Copyright © 2022 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc public protocol HelperProtocol {
|
||||
func version(completion: @escaping (String) -> Void)
|
||||
func setSMCPath(_ path: String)
|
||||
|
||||
func setFanMode(id: Int, mode: Int, completion: @escaping (String?) -> Void)
|
||||
func setFanSpeed(id: Int, value: Int, completion: @escaping (String?) -> Void)
|
||||
}
|
||||
@@ -97,25 +97,28 @@ func main() {
|
||||
|
||||
print("[INFO]: set \(value) on \(key)")
|
||||
case .fan:
|
||||
guard let idIndex = args.firstIndex(where: { $0 == "-id" }),
|
||||
args.indices.contains(idIndex+1),
|
||||
let id = Int(args[idIndex+1]) else {
|
||||
print("[ERROR]: missing id")
|
||||
guard let idString = args.first, let id = Int(idString) else {
|
||||
print("[ERROR]: missing fan id")
|
||||
return
|
||||
}
|
||||
var help: Bool = true
|
||||
|
||||
if let index = args.firstIndex(where: { $0 == "-v" }), args.indices.contains(index+1), let value = Int(args[index+1]) {
|
||||
SMC.shared.setFanSpeed(id, speed: value)
|
||||
return
|
||||
help = false
|
||||
}
|
||||
|
||||
if let index = args.firstIndex(where: { $0 == "-m" }), args.indices.contains(index+1),
|
||||
let raw = Int(args[index+1]), let mode = FanMode.init(rawValue: raw) {
|
||||
SMC.shared.setFanMode(id, mode: mode)
|
||||
return
|
||||
help = false
|
||||
}
|
||||
|
||||
print("[ERROR]: missing value or mode")
|
||||
guard help else { return }
|
||||
|
||||
print("Available Flags:")
|
||||
print(" -m change the fan mode: 0 - automatic, 1 - manual")
|
||||
print(" -v change the fan speed")
|
||||
case .fans:
|
||||
guard let count = SMC.shared.getValue("FNum") else {
|
||||
print("FNum not found")
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
5C8E001029269C7F0027C75A /* protocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE493829265055000F2856 /* protocol.swift */; };
|
||||
5CFE492A29264DF1000F2856 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE492929264DF1000F2856 /* main.swift */; };
|
||||
5CFE493929265055000F2856 /* protocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE493829265055000F2856 /* protocol.swift */; };
|
||||
5CFE493D2926513E000F2856 /* eu.exelban.Stats.SMC.Helper in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5CFE492729264DF1000F2856 /* eu.exelban.Stats.SMC.Helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
5CFE494229265418000F2856 /* uninstall.sh in Resources */ = {isa = PBXBuildFile; fileRef = 5CFE494129265418000F2856 /* uninstall.sh */; };
|
||||
5CFE494429265421000F2856 /* changelog.py in Resources */ = {isa = PBXBuildFile; fileRef = 5CFE494329265421000F2856 /* changelog.py */; };
|
||||
9A045EB72594F8D100ED58F2 /* Dashboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A045EB62594F8D100ED58F2 /* Dashboard.swift */; };
|
||||
9A11AAD6266FD77F000C1C05 /* Bluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A11AACF266FD77F000C1C05 /* Bluetooth.framework */; };
|
||||
9A11AAD7266FD77F000C1C05 /* Bluetooth.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9A11AACF266FD77F000C1C05 /* Bluetooth.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@@ -259,6 +265,25 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
5CFE492529264DF1000F2856 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
5CFE493C29265130000F2856 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = Contents/Library/LaunchServices;
|
||||
dstSubfolderSpec = 1;
|
||||
files = (
|
||||
5CFE493D2926513E000F2856 /* eu.exelban.Stats.SMC.Helper in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9A46BF89266D7CFA001A1117 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -317,6 +342,13 @@
|
||||
30370F8F253DCBC0006404D8 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
40BE2B202745D63800AE9396 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
4921436D25319699000A1C47 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
5CFE492729264DF1000F2856 /* eu.exelban.Stats.SMC.Helper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = eu.exelban.Stats.SMC.Helper; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
5CFE492929264DF1000F2856 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
5CFE493829265055000F2856 /* protocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = protocol.swift; sourceTree = "<group>"; };
|
||||
5CFE493A292650BD000F2856 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
5CFE493B292650F8000F2856 /* Launchd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Launchd.plist; sourceTree = "<group>"; };
|
||||
5CFE494129265418000F2856 /* uninstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = uninstall.sh; sourceTree = "<group>"; };
|
||||
5CFE494329265421000F2856 /* changelog.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = changelog.py; sourceTree = "<group>"; };
|
||||
62BA5F74254810C8009D0AC2 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
63A07F97275018DF00352C46 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
7A19DAE52552C326001B192F /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
@@ -463,6 +495,13 @@
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
5CFE492429264DF1000F2856 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9A11AACC266FD77F000C1C05 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -575,6 +614,17 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
5CFE492829264DF1000F2856 /* Helper */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5CFE492929264DF1000F2856 /* main.swift */,
|
||||
5CFE493829265055000F2856 /* protocol.swift */,
|
||||
5CFE493A292650BD000F2856 /* Info.plist */,
|
||||
5CFE493B292650F8000F2856 /* Launchd.plist */,
|
||||
);
|
||||
path = Helper;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9A11AAD0266FD77F000C1C05 /* Bluetooth */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -618,6 +668,7 @@
|
||||
9A2846F72666A9CC00EC1F6D /* Kit.framework */,
|
||||
9A11AACF266FD77F000C1C05 /* Bluetooth.framework */,
|
||||
9AAC5E2A280ACC120043D892 /* Tests.xctest */,
|
||||
5CFE492729264DF1000F2856 /* eu.exelban.Stats.SMC.Helper */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -716,7 +767,9 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9A2848012666AB2F00EC1F6D /* updater.sh */,
|
||||
5CFE494129265418000F2856 /* uninstall.sh */,
|
||||
9A46BF35266D6E17001A1117 /* i18n.py */,
|
||||
5CFE494329265421000F2856 /* changelog.py */,
|
||||
);
|
||||
path = scripts;
|
||||
sourceTree = "<group>";
|
||||
@@ -848,6 +901,7 @@
|
||||
9ADE6FD9265D032100D2FBA8 /* SMC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5CFE492829264DF1000F2856 /* Helper */,
|
||||
9ADE6FDA265D032100D2FBA8 /* main.swift */,
|
||||
9ADE7038265D059000D2FBA8 /* smc.swift */,
|
||||
);
|
||||
@@ -952,6 +1006,23 @@
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
5CFE492629264DF1000F2856 /* Helper */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 5CFE492D29264DF1000F2856 /* Build configuration list for PBXNativeTarget "Helper" */;
|
||||
buildPhases = (
|
||||
5CFE492329264DF1000F2856 /* Sources */,
|
||||
5CFE492429264DF1000F2856 /* Frameworks */,
|
||||
5CFE492529264DF1000F2856 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Helper;
|
||||
productName = Helper;
|
||||
productReference = 5CFE492729264DF1000F2856 /* eu.exelban.Stats.SMC.Helper */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
9A11AACE266FD77F000C1C05 /* Bluetooth */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 9A11AADA266FD77F000C1C05 /* Build configuration list for PBXNativeTarget "Bluetooth" */;
|
||||
@@ -983,6 +1054,7 @@
|
||||
9AECEF3D24ACF98800DB95D4 /* Copy Files */,
|
||||
9A88E2672659002E00E2B7B0 /* ShellScript */,
|
||||
9A46BF89266D7CFA001A1117 /* CopyFiles */,
|
||||
5CFE493C29265130000F2856 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -1219,10 +1291,13 @@
|
||||
KnownAssetTags = (
|
||||
New,
|
||||
);
|
||||
LastSwiftUpdateCheck = 1240;
|
||||
LastUpgradeCheck = 1400;
|
||||
LastSwiftUpdateCheck = 1410;
|
||||
LastUpgradeCheck = 1410;
|
||||
ORGANIZATIONNAME = "Serhiy Mytrovtsiy";
|
||||
TargetAttributes = {
|
||||
5CFE492629264DF1000F2856 = {
|
||||
CreatedOnToolsVersion = 14.1;
|
||||
};
|
||||
9A11AACE266FD77F000C1C05 = {
|
||||
CreatedOnToolsVersion = 12.4;
|
||||
LastSwiftMigration = 1240;
|
||||
@@ -1340,6 +1415,7 @@
|
||||
9AE29AD4249A50350071B02D /* Sensors */,
|
||||
9A11AACE266FD77F000C1C05 /* Bluetooth */,
|
||||
9AAC5E29280ACC120043D892 /* Tests */,
|
||||
5CFE492629264DF1000F2856 /* Helper */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -1369,6 +1445,8 @@
|
||||
9A46BF36266D6E17001A1117 /* i18n.py in Resources */,
|
||||
9A2848892666AC0100EC1F6D /* Assets.xcassets in Resources */,
|
||||
9A2848082666AB3000EC1F6D /* updater.sh in Resources */,
|
||||
5CFE494229265418000F2856 /* uninstall.sh in Resources */,
|
||||
5CFE494429265421000F2856 /* changelog.py in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1466,6 +1544,15 @@
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
5CFE492329264DF1000F2856 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5CFE492A29264DF1000F2856 /* main.swift in Sources */,
|
||||
5CFE493929265055000F2856 /* protocol.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9A11AACB266FD77F000C1C05 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1495,6 +1582,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5C8E001029269C7F0027C75A /* protocol.swift in Sources */,
|
||||
9AD7F866266F759200E5F863 /* smc.swift in Sources */,
|
||||
9A2847612666AA2700EC1F6D /* PieChart.swift in Sources */,
|
||||
9A2847672666AA2700EC1F6D /* BarChart.swift in Sources */,
|
||||
@@ -1770,6 +1858,58 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
5CFE492B29264DF1000F2856 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = RP2S87B72W;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Helper/Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
"OTHER_LDFLAGS[arch=*]" = (
|
||||
"-sectcreate",
|
||||
__TEXT,
|
||||
__info_plist,
|
||||
"\"$(SRCROOT)/SMC/Helper/Info.plist\"",
|
||||
"-sectcreate",
|
||||
__TEXT,
|
||||
__launchd_plist,
|
||||
"\"$(SRCROOT)/SMC/Helper/Launchd.plist\"",
|
||||
);
|
||||
PRODUCT_NAME = eu.exelban.Stats.SMC.Helper;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
5CFE492C29264DF1000F2856 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = RP2S87B72W;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Helper/Info.plist";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
"OTHER_LDFLAGS[arch=*]" = (
|
||||
"-sectcreate",
|
||||
__TEXT,
|
||||
__info_plist,
|
||||
"\"$(SRCROOT)/SMC/Helper/Info.plist\"",
|
||||
"-sectcreate",
|
||||
__TEXT,
|
||||
__launchd_plist,
|
||||
"\"$(SRCROOT)/SMC/Helper/Launchd.plist\"",
|
||||
);
|
||||
PRODUCT_NAME = eu.exelban.Stats.SMC.Helper;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
9A11AAD8266FD77F000C1C05 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -2431,7 +2571,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.serhiy.Stats.Tests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -2453,7 +2593,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.serhiy.Stats.Tests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -2701,6 +2841,15 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
5CFE492D29264DF1000F2856 /* Build configuration list for PBXNativeTarget "Helper" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
5CFE492B29264DF1000F2856 /* Debug */,
|
||||
5CFE492C29264DF1000F2856 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
9A11AADA266FD77F000C1C05 /* Build configuration list for PBXNativeTarget "Bluetooth" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -20,6 +20,20 @@
|
||||
ReferencedContainer = "container:Stats.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "5CFE492629264DF1000F2856"
|
||||
BuildableName = "eu.exelban.Stats.SMC.Helper"
|
||||
BlueprintName = "Helper"
|
||||
ReferencedContainer = "container:Stats.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
|
||||
@@ -39,5 +39,10 @@
|
||||
<string>NSApplication</string>
|
||||
<key>NSUserNotificationAlertStyle</key>
|
||||
<string>alert</string>
|
||||
<key>SMPrivilegedExecutables</key>
|
||||
<dict>
|
||||
<key>eu.exelban.Stats.SMC.Helper</key>
|
||||
<string>identifier "eu.exelban.Stats.SMC.Helper" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
Reference in New Issue
Block a user