Skip to content

Commit 2c865a8

Browse files
authored
Merge pull request #963 from rgoldberg/667-reset-without-external-processes
Refactor `Reset`
2 parents cea7715 + c32ca83 commit 2c865a8

File tree

2 files changed

+52
-30
lines changed

2 files changed

+52
-30
lines changed

.swiftlint.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ function_body_length:
4747
warning: 75
4848
indentation_width:
4949
include_multiline_strings: false
50+
line_length:
51+
ignores_multiline_strings: true
5052
number_separator:
5153
minimum_length: 6
5254
opening_brace:

Sources/mas/Commands/Reset.swift

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Copyright © 2016 mas-cli. All rights reserved.
66
//
77

8+
private import AppKit
89
internal import ArgumentParser
910
private import CommerceKit
1011

@@ -32,37 +33,56 @@ extension MAS {
3233
/// As `storeagent` no longer exists, terminates all processes known to be
3334
/// associated with the Mac App Store.
3435
func run(printer: Printer) {
35-
let killall = Process()
36-
killall.launchPath = "/usr/bin/killall"
37-
killall.arguments = [
38-
"ContextStoreAgent",
39-
"Dock",
40-
"SetStoreUpdateService",
41-
"appstoreagent",
42-
"appstorecomponentsd",
43-
"storeaccountd",
44-
"storeassetd",
45-
"storedownloadd",
46-
"storeinstalld",
47-
"storekitagent",
48-
"storelegacy",
49-
"storeuid",
50-
]
51-
let stderr = Pipe()
52-
killall.standardError = stderr
53-
killall.standardOutput = Pipe()
36+
for bundleID in ["com.apple.dock", "com.apple.storeuid"] {
37+
for app in NSRunningApplication.runningApplications(withBundleIdentifier: bundleID) where !app.terminate() {
38+
printer.warning("Failed to terminate app with bundle ID:", bundleID)
39+
if !app.forceTerminate() {
40+
printer.error("Failed to force terminate app with bundle ID:", bundleID)
41+
}
42+
}
43+
}
44+
45+
let executablePathSet = Set([
46+
"/System/Library/Frameworks/StoreKit.framework/Support/storekitagent",
47+
"/System/Library/PrivateFrameworks/AppStoreComponents.framework/Support/appstorecomponentsd",
48+
"/System/Library/PrivateFrameworks/AppStoreDaemon.framework/Support/appstoreagent",
49+
"""
50+
/System/Library/PrivateFrameworks/CascadeSets.framework/Versions/A/XPCServices/SetStoreUpdateService.xpc/Contents/MacOS/SetStoreUpdateService
51+
""",
52+
"/System/Library/PrivateFrameworks/CommerceKit.framework/Versions/A/Resources/storeaccountd",
53+
"/System/Library/PrivateFrameworks/CommerceKit.framework/Versions/A/Resources/storeassetd",
54+
"/System/Library/PrivateFrameworks/CommerceKit.framework/Versions/A/Resources/storedownloadd",
55+
"/System/Library/PrivateFrameworks/CommerceKit.framework/Versions/A/Resources/storeinstalld",
56+
"/System/Library/PrivateFrameworks/CommerceKit.framework/Versions/A/Resources/storelegacy",
57+
])
58+
59+
var processListMIB = [CTL_KERN, KERN_PROC, KERN_PROC_ALL]
60+
var length = 0
61+
guard sysctl(&processListMIB, u_int(processListMIB.count), nil, &length, nil, 0) == 0 else {
62+
printer.error("Failed to get process list length")
63+
return
64+
}
65+
66+
var kinfoProcs = [kinfo_proc](repeating: kinfo_proc(), count: length / MemoryLayout<kinfo_proc>.stride)
67+
guard sysctl(&processListMIB, u_int(processListMIB.count), &kinfoProcs, &length, nil, 0) == 0 else {
68+
printer.error("Failed to get process list")
69+
return
70+
}
71+
72+
var executablePathBuffer = [CChar](repeating: 0, count: Int(PATH_MAX))
73+
for pid in kinfoProcs.map(\.kp_proc.p_pid) {
74+
guard
75+
proc_pidpath(pid, &executablePathBuffer, UInt32(executablePathBuffer.count)) > 0,
76+
let executablePath = String(cString: executablePathBuffer, encoding: .utf8),
77+
executablePathSet.contains(executablePath)
78+
else {
79+
continue
80+
}
5481

55-
killall.launch()
56-
killall.waitUntilExit()
57-
if killall.terminationStatus != 0 {
58-
let output = stderr.fileHandleForReading.readDataToEndOfFile()
59-
printer.error(
60-
"killall failed with exit status ",
61-
killall.terminationStatus,
62-
":\n",
63-
String(data: output, encoding: .utf8) ?? "Error info not available",
64-
separator: ""
65-
)
82+
let exitStatus = kill(pid, SIGTERM)
83+
if exitStatus != 0 {
84+
printer.error("Failed to terminate", executablePath, "getting exit status", exitStatus, "for pid", pid)
85+
}
6686
}
6787

6888
let folder = CKDownloadDirectory(nil)

0 commit comments

Comments
 (0)