千家信息网

system 函数被废除的替代方法

发表于:2024-11-30 作者:千家信息网编辑
千家信息网最后更新 2024年11月30日,做越狱应用和插件开发,经常会调用 system 去执行系统命令,早在 Xcode 7,使用 system 函数提示警告:'system' is deprecated: first deprecated
千家信息网最后更新 2024年11月30日system 函数被废除的替代方法

做越狱应用和插件开发,经常会调用 system 去执行系统命令,早在 Xcode 7,使用 system 函数提示警告:

'system' is deprecated: first deprecated in iOS 8.0 - Use posix_spawn APIs installd

只是警告,还是可以正常编译和使用,但是升级到 Xcode 9,system 函数就从 SDK 中移除了,不能再使用了,提示:

'system' is unavailable: not available on iOS

替代的方法一般有三种,第一种是使用 posix_spawn,代码如下:

pid_t pid;char *argv[] = {  "/bin/ls",  //path  "-al",     //parameter1  "/",       //parameter2  NULL}; posix_spawn(&pid, argv[0], NULL, NULL, argv, NULL); printf("pid=%d,child pid = %d\n",getpid(),pid); int stat;waitpid(pid,&stat,0);printf("stat is %d\n",stat);

第二种是使用 NSTask,代码如下:

NSTask *task = [[NSTask alloc] init];task.launchPath = @"/bin/ls";task.arguments = [NSArray arrayWithObjects:                  @"-al",                  @"/",                  nil];[task launch];[task waitUntilExit];

NSTask.h 头文件信息如下:

#import  @class NSString, NSArray, NSDictionary; @interface NSTask : NSObject // Create an NSTask which can be run at a later time// An NSTask can only be run once. Subsequent attempts to// run an NSTask will raise.// Upon task death a notification will be sent//   { Name = NSTaskDidTerminateNotification; object = task; }// - (instancetype)init; // set parameters// these methods can only be done before a launch// if not set, use current// if not set, use current // set standard I/O channels; may be either an NSFileHandle or an NSPipe- (void)setStandardInput:(id)input;- (void)setStandardOutput:(id)output;- (void)setStandardError:(id)error; // get parameters@property (NS_NONATOMIC_IOSONLY, copy) NSString *launchPath;@property (NS_NONATOMIC_IOSONLY, copy) NSArray *arguments;@property (NS_NONATOMIC_IOSONLY, copy) NSDictionary *environment;@property (NS_NONATOMIC_IOSONLY, copy) NSString *currentDirectoryPath; // get standard I/O channels; could be either an NSFileHandle or an NSPipe- (id)standardInput;- (id)standardOutput;- (id)standardError; // actions- (void)launch; - (void)interrupt; // Not always possible. Sends SIGINT.- (void)terminate; // Not always possible. Sends SIGTERM. @property (NS_NONATOMIC_IOSONLY, readonly) BOOL suspend;@property (NS_NONATOMIC_IOSONLY, readonly) BOOL resume; // status@property (NS_NONATOMIC_IOSONLY, readonly) int processIdentifier; @property (NS_NONATOMIC_IOSONLY, getter=isRunning, readonly) BOOL running; @property (NS_NONATOMIC_IOSONLY, readonly) int terminationStatus; @end @interface NSTask (NSTaskConveniences) + (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments;// convenience; create and launch - (void)waitUntilExit;// poll the runLoop in defaultMode until task completes @end FOUNDATION_EXPORT NSString * const NSTaskDidTerminateNotification;

如果非要调用 system 函数不可,那就使用第三种方法,找到 system 函数地址直接调用,方法参见: 动态调用函数,具体代码如下:

typedef int (*my_system) (const char *str);int call_system(const char *str){        //动态库路径    char *dylib_path = "/usr/lib/libSystem.dylib";    //打开动态库    void *handle = dlopen(dylib_path, RTLD_GLOBAL | RTLD_NOW);    if (handle == NULL) {        //打开动态库出错        fprintf(stderr, "%s\n", dlerror());    } else {        //获取 system 地址        my_system system = dlsym(handle, "system");                //地址获取成功则调用        if (system) {                        int ret = system(str);            return ret;        }        dlclose(handle); //关闭句柄    }        return -1;}

这样 call_system 函数就相当于 system 的功能了,替换即可。


原文地址:https://www.exchen.net/ios-hacker-system-%E5%87%BD%E6%95%B0%E8%A2%AB%E5%BA%9F%E9%99%A4%E7%9A%84%E6%9B%BF%E4%BB%A3%E6%96%B9%E6%B3%95.html


0