Skip to content

Commit 90647ec

Browse files
author
DevelopLab
committed
1. Add Restart Cellular Service feature
1 parent 61847bd commit 90647ec

17 files changed

Lines changed: 584 additions & 9 deletions
148 KB
Binary file not shown.

MaintenanceHelper/Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
TARGET := iphone:clang:latest:12.0
2+
ARCHS = arm64 arm64e
3+
4+
include $(THEOS)/makefiles/common.mk
5+
6+
TOOL_NAME = MaintenanceHelper
7+
8+
MaintenanceHelper_FILES = main.m
9+
MaintenanceHelper_CFLAGS = -fobjc-arc
10+
MaintenanceHelper_CODESIGN_FLAGS = -Sentitlements.plist
11+
MaintenanceHelper_INSTALL_PATH = /usr/local/bin
12+
13+
include $(THEOS_MAKE_PATH)/tool.mk
14+
after-stage::
15+
@echo "Copying file to parent directory..."
16+
cp $(THEOS_STAGING_DIR)/usr/local/bin/$(TOOL_NAME) ../$(TOOL_NAME)/
17+
@echo "Copy completed."
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
2+
<plist version="1.0">
3+
<dict>
4+
<key>platform-application</key>
5+
<true/>
6+
<key>com.apple.private.security.container-required</key>
7+
<false/>
8+
</dict>
9+
</plist>

MaintenanceHelper/main.m

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#import <Foundation/Foundation.h>
2+
#import <signal.h>
3+
#import <sys/sysctl.h>
4+
#import <unistd.h>
5+
6+
static void enumerateProcesses(void (^block)(pid_t pid, NSString *execPath)) {
7+
int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
8+
size_t size = 0;
9+
10+
if (sysctl(mib, 3, NULL, &size, NULL, 0) != 0) return;
11+
12+
struct kinfo_proc *procs = malloc(size);
13+
if (!procs) return;
14+
15+
if (sysctl(mib, 3, procs, &size, NULL, 0) != 0) {
16+
free(procs);
17+
return;
18+
}
19+
20+
int count = (int)(size / sizeof(struct kinfo_proc));
21+
for (int i = 0; i < count; i++) {
22+
pid_t pid = procs[i].kp_proc.p_pid;
23+
if (pid <= 0) continue;
24+
25+
size_t argSize = 0;
26+
if (sysctl((int[]){CTL_KERN, KERN_PROCARGS2, pid}, 3, NULL, &argSize, NULL, 0) != 0)
27+
continue;
28+
29+
char *buffer = malloc(argSize);
30+
if (!buffer) continue;
31+
32+
if (sysctl((int[]){CTL_KERN, KERN_PROCARGS2, pid}, 3, buffer, &argSize, NULL, 0) == 0) {
33+
NSString *path = [NSString stringWithUTF8String:(buffer + sizeof(int))];
34+
if (path) {
35+
block(pid, path);
36+
}
37+
}
38+
39+
free(buffer);
40+
}
41+
42+
free(procs);
43+
}
44+
45+
int main(int argc, char *argv[]) {
46+
@autoreleasepool {
47+
enumerateProcesses(^(pid_t pid, NSString *execPath) {
48+
if ([execPath.lastPathComponent isEqualToString:@"CommCenter"]) {
49+
kill(pid, SIGTERM);
50+
}
51+
});
52+
}
53+
54+
return 0;
55+
}

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ before-all::
99

1010
# 使用 Xcode 项目构建
1111
XCODEPROJ_NAME = TrollSIMSwitcher
12-
BUILD_VERSION = "1.1"
12+
BUILD_VERSION = "1.2"
1313
FILE_NAME = "com.developlab.trollsimswitcher"
1414

1515
# 指定 Theos 使用 xcodeproj 规则
@@ -28,6 +28,9 @@ before-package::
2828
@rm -rf $(THEOS_STAGING_DIR)/Applications/$(XCODEPROJ_NAME).app/PlugIns/TrollSIMSwitcherWidgetExtension.appex/_CodeSignature
2929
@echo -e "\033[32mRemoving Frameworks folder..."
3030
@rm -rf $(THEOS_STAGING_DIR)/Applications/$(XCODEPROJ_NAME).app/Frameworks
31+
@echo -e "\033[32mCopy RootHelper to package..."
32+
# 这里必须要手动复制RootHelper到包内,不要放到Xcode工程目录下,不然就无法运行二进制文件
33+
@cp -f MaintenanceHelper/MaintenanceHelper $(THEOS_STAGING_DIR)/Applications/$(XCODEPROJ_NAME).app/
3134

3235
# 包装完成后重命名为 .tipa
3336
after-package::

TrollSIMSwitcher/AppDelegate.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
102102
switchSuccessful = CoreTelephonyController.instance.setCellularPlanEnable(planID: SettingsUtils.instance.getSelectCellularPlan1(), enable: false)
103103
case "TrollSIMSwitcherToggleCellularPlan": // 切换蜂窝数据卡状态
104104
switchSuccessful = CoreTelephonyController.instance.toggleCellularPlanEnable(planID: SettingsUtils.instance.getSelectCellularPlan1())
105+
case "TrollSIMSwitcherRebootCommCenter": // 重启基带服务
106+
let deviceController = DeviceController()
107+
if deviceController.rebootCommCenter() {
108+
UIApplication.shared.perform(#selector(NSXPCConnection.suspend)) // 返回桌面
109+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
110+
exit(0)
111+
}
112+
return
113+
}
105114
default: return
106115
}
107116

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface DeviceController : NSObject
4+
5+
- (void) Respring;
6+
- (Boolean) RebootCommCenter;
7+
8+
@end
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
#import "DeviceController.h"
2+
#include <spawn.h>
3+
#import <sys/sysctl.h>
4+
#import <Foundation/Foundation.h>
5+
//#import <FrontBoardServices/FBSSystemService.h>
6+
7+
@implementation DeviceController
8+
9+
#define POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE 1
10+
extern int posix_spawnattr_set_persona_np(const posix_spawnattr_t* __restrict, uid_t, uint32_t);
11+
extern int posix_spawnattr_set_persona_uid_np(const posix_spawnattr_t* __restrict, uid_t);
12+
extern int posix_spawnattr_set_persona_gid_np(const posix_spawnattr_t* __restrict, uid_t);
13+
14+
// @See https://github.com/opa334/TrollStore/blob/main/Shared/TSUtil.m#L297
15+
- (void) Respring
16+
{
17+
killall(@"SpringBoard", YES);
18+
exit(0);
19+
}
20+
21+
- (Boolean) RebootCommCenter
22+
{
23+
// killall(@"SpringBoard", YES);
24+
// exit(0);
25+
NSString *path = [[NSBundle mainBundle] pathForResource:@"MaintenanceHelper" ofType:@""];
26+
27+
NSArray *args = @[]; // 不需要任何额外参数
28+
NSString *stdOut = nil;
29+
NSString *stdErr = nil;
30+
31+
if (path == nil) {
32+
return NO;
33+
}
34+
35+
int result = spawnRoot(path, args, &stdOut, &stdErr);
36+
if (result == 0) {
37+
return YES;
38+
}
39+
40+
return NO;
41+
}
42+
43+
// @See https://github.com/opa334/TrollStore/blob/main/Shared/TSUtil.m#L79
44+
int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString** stdErr)
45+
{
46+
NSMutableArray* argsM = args.mutableCopy ?: [NSMutableArray new];
47+
[argsM insertObject:path atIndex:0];
48+
49+
NSUInteger argCount = [argsM count];
50+
char **argsC = (char **)malloc((argCount + 1) * sizeof(char*));
51+
52+
for (NSUInteger i = 0; i < argCount; i++)
53+
{
54+
argsC[i] = strdup([[argsM objectAtIndex:i] UTF8String]);
55+
}
56+
argsC[argCount] = NULL;
57+
58+
posix_spawnattr_t attr;
59+
posix_spawnattr_init(&attr);
60+
61+
posix_spawnattr_set_persona_np(&attr, 99, POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE);
62+
posix_spawnattr_set_persona_uid_np(&attr, 0);
63+
posix_spawnattr_set_persona_gid_np(&attr, 0);
64+
65+
posix_spawn_file_actions_t action;
66+
posix_spawn_file_actions_init(&action);
67+
68+
int outErr[2];
69+
if(stdErr)
70+
{
71+
pipe(outErr);
72+
posix_spawn_file_actions_adddup2(&action, outErr[1], STDERR_FILENO);
73+
posix_spawn_file_actions_addclose(&action, outErr[0]);
74+
}
75+
76+
int out[2];
77+
if(stdOut)
78+
{
79+
pipe(out);
80+
posix_spawn_file_actions_adddup2(&action, out[1], STDOUT_FILENO);
81+
posix_spawn_file_actions_addclose(&action, out[0]);
82+
}
83+
84+
pid_t task_pid;
85+
int status = -200;
86+
int spawnError = posix_spawn(&task_pid, [path UTF8String], &action, &attr, (char* const*)argsC, NULL);
87+
posix_spawnattr_destroy(&attr);
88+
for (NSUInteger i = 0; i < argCount; i++)
89+
{
90+
free(argsC[i]);
91+
}
92+
free(argsC);
93+
94+
if(spawnError != 0)
95+
{
96+
NSLog(@"posix_spawn error %d\n", spawnError);
97+
return spawnError;
98+
}
99+
100+
__block volatile BOOL _isRunning = YES;
101+
NSMutableString* outString = [NSMutableString new];
102+
NSMutableString* errString = [NSMutableString new];
103+
dispatch_semaphore_t sema = 0;
104+
dispatch_queue_t logQueue;
105+
if(stdOut || stdErr)
106+
{
107+
logQueue = dispatch_queue_create("com.opa334.TrollStore.LogCollector", NULL);
108+
sema = dispatch_semaphore_create(0);
109+
110+
int outPipe = out[0];
111+
int outErrPipe = outErr[0];
112+
113+
__block BOOL outEnabled = (BOOL)stdOut;
114+
__block BOOL errEnabled = (BOOL)stdErr;
115+
dispatch_async(logQueue, ^
116+
{
117+
while(_isRunning)
118+
{
119+
@autoreleasepool
120+
{
121+
if(outEnabled)
122+
{
123+
[outString appendString:getNSStringFromFile(outPipe)];
124+
}
125+
if(errEnabled)
126+
{
127+
[errString appendString:getNSStringFromFile(outErrPipe)];
128+
}
129+
}
130+
}
131+
dispatch_semaphore_signal(sema);
132+
});
133+
}
134+
135+
do
136+
{
137+
if (waitpid(task_pid, &status, 0) != -1) {
138+
NSLog(@"Child status %d", WEXITSTATUS(status));
139+
} else
140+
{
141+
perror("waitpid");
142+
_isRunning = NO;
143+
return -222;
144+
}
145+
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
146+
147+
_isRunning = NO;
148+
if(stdOut || stdErr)
149+
{
150+
if(stdOut)
151+
{
152+
close(out[1]);
153+
}
154+
if(stdErr)
155+
{
156+
close(outErr[1]);
157+
}
158+
159+
// wait for logging queue to finish
160+
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
161+
162+
if(stdOut)
163+
{
164+
*stdOut = outString.copy;
165+
}
166+
if(stdErr)
167+
{
168+
*stdErr = errString.copy;
169+
}
170+
}
171+
172+
return WEXITSTATUS(status);
173+
}
174+
175+
NSString* getNSStringFromFile(int fd)
176+
{
177+
NSMutableString* ms = [NSMutableString new];
178+
ssize_t num_read;
179+
char c;
180+
if(!fd_is_valid(fd)) return @"";
181+
while((num_read = read(fd, &c, sizeof(c))))
182+
{
183+
[ms appendString:[NSString stringWithFormat:@"%c", c]];
184+
if(c == '\n') break;
185+
}
186+
return ms.copy;
187+
}
188+
189+
int fd_is_valid(int fd)
190+
{
191+
return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
192+
}
193+
194+
// @See https://github.com/opa334/TrollStore/blob/main/Shared/TSUtil.m#L279
195+
void killall(NSString* processName, BOOL softly)
196+
{
197+
enumerateProcessesUsingBlock(^(pid_t pid, NSString* executablePath, BOOL* stop)
198+
{
199+
if([executablePath.lastPathComponent isEqualToString:processName])
200+
{
201+
if(softly)
202+
{
203+
kill(pid, SIGTERM);
204+
}
205+
else
206+
{
207+
kill(pid, SIGKILL);
208+
}
209+
}
210+
});
211+
}
212+
213+
void enumerateProcessesUsingBlock(void (^enumerator)(pid_t pid, NSString* executablePath, BOOL* stop))
214+
{
215+
static int maxArgumentSize = 0;
216+
if (maxArgumentSize == 0) {
217+
size_t size = sizeof(maxArgumentSize);
218+
if (sysctl((int[]){ CTL_KERN, KERN_ARGMAX }, 2, &maxArgumentSize, &size, NULL, 0) == -1) {
219+
perror("sysctl argument size");
220+
maxArgumentSize = 4096; // Default
221+
}
222+
}
223+
int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL};
224+
struct kinfo_proc *info;
225+
size_t length;
226+
int count;
227+
228+
if (sysctl(mib, 3, NULL, &length, NULL, 0) < 0)
229+
return;
230+
if (!(info = malloc(length)))
231+
return;
232+
if (sysctl(mib, 3, info, &length, NULL, 0) < 0) {
233+
free(info);
234+
return;
235+
}
236+
count = length / sizeof(struct kinfo_proc);
237+
for (int i = 0; i < count; i++) {
238+
@autoreleasepool {
239+
pid_t pid = info[i].kp_proc.p_pid;
240+
if (pid == 0) {
241+
continue;
242+
}
243+
size_t size = maxArgumentSize;
244+
char* buffer = (char *)malloc(length);
245+
if (sysctl((int[]){ CTL_KERN, KERN_PROCARGS2, pid }, 3, buffer, &size, NULL, 0) == 0) {
246+
NSString* executablePath = [NSString stringWithCString:(buffer+sizeof(int)) encoding:NSUTF8StringEncoding];
247+
248+
BOOL stop = NO;
249+
enumerator(pid, executablePath, &stop);
250+
if(stop)
251+
{
252+
free(buffer);
253+
break;
254+
}
255+
}
256+
free(buffer);
257+
}
258+
}
259+
free(info);
260+
}
261+
262+
@end

0 commit comments

Comments
 (0)