Browse Source

better drm

pull/1/head
Burrit0z 4 years ago
parent
commit
882867fee6
6 changed files with 409 additions and 18 deletions
  1. +2
    -0
      DragonMake
  2. +9
    -0
      Kai.h
  3. +123
    -17
      Kai.xm
  4. +1
    -1
      Layout/DEBIAN/control
  5. +187
    -0
      MobileGestalt.h
  6. +87
    -0
      NSTask.h

+ 2
- 0
DragonMake View File

@@ -8,6 +8,8 @@ kai:
- Kai.xm
frameworks:
- BatteryCenter
libs:
- MobileGestalt

kaiPrefs:
dir: kaiprefs

+ 9
- 0
Kai.h View File

@@ -3,6 +3,8 @@
#include <stdio.h>
#import <objc/runtime.h>
#import <UIKit/UIKit.h>
#import "MobileGestalt.h"
#import "NSTask.h"

#define KAISelf ((CSAdjunctListView *)self) //for use when calling self in KAITarget
//#define KAIBatteryStack UHDUEIHGCEBCHYDEICVKEVSAGJKBCXAHJGKVXHAS //lmao
@@ -22,6 +24,13 @@
@interface SBIconController : UIViewController
@end

@interface SBCoverSheetPrimarySlidingViewController : UIViewController
@end

@interface UIDevice (kai)
-(id)sf_udidString;
-(id)_currentProduct;
@end
BOOL isUpdating = NO;

//prefs

+ 123
- 17
Kai.xm View File

@@ -180,24 +180,114 @@

%group drm

%hook SBIconController
%hook SBCoverSheetPrimarySlidingViewController

-(void)viewDidAppear:(BOOL)arg1 {
UIAlertController* alert2 = [UIAlertController alertControllerWithTitle:@"Unauthorized"
message:@"At this time, only paying users of Multipla have access to kai beta. If you are interested in getting access to kai beta, you can purchase and install Multipla from Chariz."
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* yes = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
UIAlertAction* buy = [UIAlertAction actionWithTitle:@"Buy Multipla" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"https://chariz.com/buy/multipla"]];
}];
[alert2 addAction:yes];
[alert2 addAction:buy];
[self presentViewController:alert2 animated:YES completion:nil];
if(![[NSFileManager defaultManager] fileExistsAtPath:@"/var/mobile/Documents/kai.txt"])
[[NSFileManager defaultManager] createFileAtPath:@"/var/mobile/Documents/kai.txt" contents:nil attributes:nil];

CFStringRef response = (CFStringRef)MGCopyAnswer(kMGUniqueDeviceID);
NSString *udid = (__bridge NSString *)response;
NSString *contents = [NSString stringWithContentsOfFile:@"/var/mobile/Documents/kai.txt" encoding:NSUTF8StringEncoding error:nil];
if(![contents isEqualToString:udid]) {

UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Downloading kai License..."
message:@"You must have bought Multipla to use the kai beta."
preferredStyle:UIAlertControllerStyleAlert];

//Here is the dev key renai sent me: DfHPCsLPWt7HxMnivCl20LjrAHI42NfU
NSString *EVTDD = @"20LjrAHI"; //four
NSString *DEVTU = @"42NfU"; //five
NSString *DEGY = @"DfHPC"; //one
NSString *ECYUIF = @"sLPWt7Hx"; //two
NSString *DVWVR = @"MnivCl"; //three

//NEW
NSDictionary *jsonBodyDict = @{@"authorization":[NSString stringWithFormat:@"%@%@%@%@%@", DEGY, ECYUIF, DVWVR, EVTDD, DEVTU], @"platform":@"chariz", @"udid":udid, @"model":[UIDevice.currentDevice _currentProduct], @"identifier":@"xyz.burritoz.thomz.multipla"};
NSError *genError;
NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:&genError];

NSMutableURLRequest *request = [NSMutableURLRequest new];
request.HTTPMethod = @"POST";
if(genError==nil) {
[request setURL:[NSURL URLWithString:@"https://renai.me/api/v1/ios/validate"]];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPBody:jsonBodyData];
}

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
if(error == nil) {
[alert dismissViewControllerAnimated:YES completion:nil];
NSError *newError;
NSDictionary *forJSONObject = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&newError];
//NSLog(@"[Multipla]: Got %@ from link: %@ with post: %@", forJSONObject, request.URL,jsonBodyDict);
NSDictionary *subDict = [forJSONObject objectForKey:@"data"];
NSString *status = [NSString stringWithFormat:@"%@", [subDict objectForKey:@"check"]];
NSString *c = @"completed";
if([status isEqualToString:c]) {

[udid writeToFile:@"/var/mobile/Documents/kai.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
[alert dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert2 = [UIAlertController alertControllerWithTitle:@"License Downloaded"
message:@"Thank you for testing kai. Would you like to respring to use the tweak now, or wait until later?"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* no = [UIAlertAction actionWithTitle:@"Later" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];

UIAlertAction* yes = [UIAlertAction actionWithTitle:@"Respring" style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
NSTask *t = [[NSTask alloc] init];
[t setLaunchPath:@"usr/bin/killall"];
[t setArguments:[NSArray arrayWithObjects:@"backboardd", nil]];
[t launch];
}];
[alert2 addAction:no];
[alert2 addAction:yes];
[self presentViewController:alert2 animated:YES completion:nil];

} else {
[alert dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert2 = [UIAlertController alertControllerWithTitle:@"Pirated 🏴‍☠️"
message:@"Woops! Chariz is saying your device has not purchased Multipla! You must have purchased Multipla to use the kai beta. Please make sure to link your device to your Chariz account!"
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* yes = [UIAlertAction actionWithTitle:@"I understand" style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
}];
[alert2 addAction:yes];
[self presentViewController:alert2 animated:YES completion:nil];
}
} else {
[alert dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert2 = [UIAlertController alertControllerWithTitle:@"Error"
message:@"Woops! Looks like kai was unable to connect to the server. Please check your internet connection and respring to try again."
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* yes = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action) {
}];
[alert2 addAction:yes];
[self presentViewController:alert2 animated:YES completion:nil];
}


}];

[self presentViewController:alert animated:YES completion:nil];
[task resume];
}

}

%end

%end
@@ -218,9 +308,25 @@

Class CSCls = kCFCoreFoundationVersionNumber > 1600 ? ([objc_getClass("CSCoverSheetViewController") class]) : ([objc_getClass("SBDashBoardViewController") class]);

if([[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/xyz.burritoz.thomz.multipla.list"] && [[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/xyz.burritoz.thomz.multipla.md5sums"] && enabled) {
CFStringRef response = (CFStringRef)MGCopyAnswer(kMGUniqueDeviceID);
NSString *udid = (__bridge NSString *)response;

BOOL licenseValid = NO;
BOOL licenseDownloaded = NO;
if([[NSFileManager defaultManager] fileExistsAtPath:@"/var/mobile/Documents/kai.txt"]) licenseDownloaded = YES;
NSError *openError;
NSString *contents;

if(licenseDownloaded) contents = [NSString stringWithContentsOfFile:@"/var/mobile/Documents/kai.txt" encoding:NSUTF8StringEncoding error:&openError];
if(openError == nil) {
if([udid isEqualToString:contents]) {
licenseValid = YES;
}
}

if([[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/xyz.burritoz.thomz.multipla.list"] && [[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/xyz.burritoz.thomz.multipla.md5sums"] && enabled && licenseDownloaded && licenseValid) {
%init(main, KAITarget = cls, KAICSTarget = CSCls); //BIG BRAIN BRO!!
} else {
} else if(!licenseDownloaded || !licenseValid) {
%init(drm);
}
}

+ 1
- 1
Layout/DEBIAN/control View File

@@ -1,6 +1,6 @@
Package: com.burritoz.kai
Name: Kai
Version: 0.2.5~alpha
Version: 0.2.6~alpha
Architecture: iphoneos-arm
Description: Show charging banners on your lock screen!
Maintainer: burrit0z

+ 187
- 0
MobileGestalt.h View File

@@ -0,0 +1,187 @@
/*
* libMobileGestalt header.
* Mobile gestalt functions as a QA system. You ask it a question, and it gives you the answer! :)
*
* Copyright (c) 2013-2014 Cykey (David Murray)
* Improved by @PoomSmart (2020)
* All rights reserved.
*/

#ifndef LIBMOBILEGESTALT_H_
#define LIBMOBILEGESTALT_H_

#include <CoreFoundation/CoreFoundation.h>

#if __cplusplus
extern "C" {
#endif
#pragma mark - API
CFPropertyListRef MGCopyAnswer(CFStringRef property);
CFPropertyListRef MGCopyAnswerWithError(CFStringRef property, int *error);
CFPropertyListRef MGCopyMultipleAnswers(CFArrayRef properties, CFDictionaryRef unk);
bool MGGetBoolAnswer(CFStringRef property);
/*
* Not all questions are assignable.
* For example, kMGUserAssignedDeviceName is assignable but
* kMGProductType is not.
*/
int MGSetAnswer(CFStringRef property, CFTypeRef answer);
#pragma mark - Identifying Information
static const CFStringRef kMGDiskUsage = CFSTR("DiskUsage");
static const CFStringRef kMGModelNumber = CFSTR("ModelNumber");
static const CFStringRef kMGSIMTrayStatus = CFSTR("SIMTrayStatus");
static const CFStringRef kMGSerialNumber = CFSTR("SerialNumber");
static const CFStringRef kMGMLBSerialNumber = CFSTR("MLBSerialNumber");
static const CFStringRef kMGUniqueDeviceID = CFSTR("UniqueDeviceID");
static const CFStringRef kMGUniqueDeviceIDData = CFSTR("UniqueDeviceIDData");
static const CFStringRef kMGUniqueChipID = CFSTR("UniqueChipID");
static const CFStringRef kMGInverseDeviceID = CFSTR("InverseDeviceID");
static const CFStringRef kMGDiagnosticsData = CFSTR("DiagData");
static const CFStringRef kMGDieID = CFSTR("DieId");
static const CFStringRef kMGCPUArchitecture = CFSTR("CPUArchitecture");
static const CFStringRef kMGPartitionType = CFSTR("PartitionType");
static const CFStringRef kMGUserAssignedDeviceName = CFSTR("UserAssignedDeviceName");
#pragma mark - Bluetooth Information
static const CFStringRef kMGBluetoothAddress = CFSTR("BluetoothAddress");
#pragma mark - Battery Information
static const CFStringRef kMGRequiredBatteryLevelForSoftwareUpdate = CFSTR("RequiredBatteryLevelForSoftwareUpdate");
static const CFStringRef kMGBatteryIsFullyCharged = CFSTR("BatteryIsFullyCharged");
static const CFStringRef kMGBatteryIsCharging = CFSTR("BatteryIsCharging");
static const CFStringRef kMGBatteryCurrentCapacity = CFSTR("BatteryCurrentCapacity");
static const CFStringRef kMGExternalPowerSourceConnected = CFSTR("ExternalPowerSourceConnected");
#pragma mark - Baseband Information
static const CFStringRef kMGBasebandSerialNumber = CFSTR("BasebandSerialNumber");
static const CFStringRef kMGBasebandCertId = CFSTR("BasebandCertId");
static const CFStringRef kMGBasebandChipId = CFSTR("BasebandChipId");
static const CFStringRef kMGBasebandFirmwareManifestData = CFSTR("BasebandFirmwareManifestData");
static const CFStringRef kMGBasebandFirmwareVersion = CFSTR("BasebandFirmwareVersion");
static const CFStringRef kMGBasebandKeyHashInformation = CFSTR("BasebandKeyHashInformation");
#pragma mark - Telephony Information
static const CFStringRef kMGCarrierBundleInfo = CFSTR("CarrierBundleInfoArray");
static const CFStringRef kMGCarrierInstallCapability = CFSTR("CarrierInstallCapability");
static const CFStringRef kMGInternationalMobileEquipmentIdentity = CFSTR("InternationalMobileEquipmentIdentity");
static const CFStringRef kMGMobileSubscriberCountryCode = CFSTR("MobileSubscriberCountryCode");
static const CFStringRef kMGMobileSubscriberNetworkCode = CFSTR("MobileSubscriberNetworkCode");
#pragma mark - Device Information
static const CFStringRef kMGChipID = CFSTR("ChipID");
static const CFStringRef kMGComputerName = CFSTR("ComputerName");
static const CFStringRef kMGDeviceVariant = CFSTR("DeviceVariant");
static const CFStringRef kMGHWModel = CFSTR("HWModelStr");
static const CFStringRef kMGBoardId = CFSTR("BoardId");
static const CFStringRef kMGHardwarePlatform = CFSTR("HardwarePlatform");
static const CFStringRef kMGDeviceName = CFSTR("DeviceName");
static const CFStringRef kMGDeviceColor = CFSTR("DeviceColor");
static const CFStringRef kMGDeviceClassNumber = CFSTR("DeviceClassNumber");
static const CFStringRef kMGDeviceClass = CFSTR("DeviceClass");
static const CFStringRef kMGBuildVersion = CFSTR("BuildVersion");
static const CFStringRef kMGProductName = CFSTR("ProductName");
static const CFStringRef kMGProductType = CFSTR("ProductType");
static const CFStringRef kMGProductVersion = CFSTR("ProductVersion");
static const CFStringRef kMGFirmwareNonce = CFSTR("FirmwareNonce");
static const CFStringRef kMGFirmwareVersion = CFSTR("FirmwareVersion");
static const CFStringRef kMGFirmwarePreflightInfo = CFSTR("FirmwarePreflightInfo");
static const CFStringRef kMGIntegratedCircuitCardIdentifier = CFSTR("IntegratedCircuitCardIdentifier");
static const CFStringRef kMGAirplaneMode = CFSTR("AirplaneMode");
static const CFStringRef kMGAllowYouTube = CFSTR("AllowYouTube");
static const CFStringRef kMGAllowYouTubePlugin = CFSTR("AllowYouTubePlugin");
static const CFStringRef kMGMinimumSupportediTunesVersion = CFSTR("MinimumSupportediTunesVersion");
static const CFStringRef kMGProximitySensorCalibration = CFSTR("ProximitySensorCalibration");
static const CFStringRef kMGRegionCode = CFSTR("RegionCode");
static const CFStringRef kMGRegionInfo = CFSTR("RegionInfo");
static const CFStringRef kMGRegulatoryIdentifiers = CFSTR("RegulatoryIdentifiers");
static const CFStringRef kMGSBAllowSensitiveUI = CFSTR("SBAllowSensitiveUI");
static const CFStringRef kMGSBCanForceDebuggingInfo = CFSTR("SBCanForceDebuggingInfo");
static const CFStringRef kMGSDIOManufacturerTuple = CFSTR("SDIOManufacturerTuple");
static const CFStringRef kMGSDIOProductInfo = CFSTR("SDIOProductInfo");
static const CFStringRef kMGShouldHactivate = CFSTR("ShouldHactivate");
static const CFStringRef kMGSigningFuse = CFSTR("SigningFuse");
static const CFStringRef kMGSoftwareBehavior = CFSTR("SoftwareBehavior");
static const CFStringRef kMGSoftwareBundleVersion = CFSTR("SoftwareBundleVersion");
static const CFStringRef kMGSupportedDeviceFamilies = CFSTR("SupportedDeviceFamilies");
static const CFStringRef kMSupportedKeyboards = CFSTR("SupportedKeyboards");
static const CFStringRef kMGTotalSystemAvailable = CFSTR("TotalSystemAvailable");
#pragma mark - Capability Information
static const CFStringRef kMGAllDeviceCapabilities = CFSTR("AllDeviceCapabilities");
static const CFStringRef kMGAppleInternalInstallCapability = CFSTR("AppleInternalInstallCapability");
static const CFStringRef kMGExternalChargeCapability = CFSTR("ExternalChargeCapability");
static const CFStringRef kMGForwardCameraCapability = CFSTR("ForwardCameraCapability");
static const CFStringRef kMGPanoramaCameraCapability = CFSTR("PanoramaCameraCapability");
static const CFStringRef kMGRearCameraCapability = CFSTR("RearCameraCapability");
static const CFStringRef kMGHasAllFeaturesCapability = CFSTR("HasAllFeaturesCapability");
static const CFStringRef kMGHasBaseband = CFSTR("HasBaseband");
static const CFStringRef kMGHasInternalSettingsBundle = CFSTR("HasInternalSettingsBundle");
static const CFStringRef kMGHasSpringBoard = CFSTR("HasSpringBoard");
static const CFStringRef kMGInternalBuild = CFSTR("InternalBuild");
static const CFStringRef kMGIsSimulator = CFSTR("IsSimulator");
static const CFStringRef kMGIsThereEnoughBatteryLevelForSoftwareUpdate = CFSTR("IsThereEnoughBatteryLevelForSoftwareUpdate");
static const CFStringRef kMGIsUIBuild = CFSTR("IsUIBuild");
#pragma mark - Regional Behaviour
static const CFStringRef kMGRegionalBehaviorAll = CFSTR("RegionalBehaviorAll");
static const CFStringRef kMGRegionalBehaviorChinaBrick = CFSTR("RegionalBehaviorChinaBrick");
static const CFStringRef kMGRegionalBehaviorEUVolumeLimit = CFSTR("RegionalBehaviorEUVolumeLimit");
static const CFStringRef kMGRegionalBehaviorGB18030 = CFSTR("RegionalBehaviorGB18030");
static const CFStringRef kMGRegionalBehaviorGoogleMail = CFSTR("RegionalBehaviorGoogleMail");
static const CFStringRef kMGRegionalBehaviorNTSC = CFSTR("RegionalBehaviorNTSC");
static const CFStringRef kMGRegionalBehaviorNoPasscodeLocationTiles = CFSTR("RegionalBehaviorNoPasscodeLocationTiles");
static const CFStringRef kMGRegionalBehaviorNoVOIP = CFSTR("RegionalBehaviorNoVOIP");
static const CFStringRef kMGRegionalBehaviorNoWiFi = CFSTR("RegionalBehaviorNoWiFi");
static const CFStringRef kMGRegionalBehaviorShutterClick = CFSTR("RegionalBehaviorShutterClick");
static const CFStringRef kMGRegionalBehaviorVolumeLimit = CFSTR("RegionalBehaviorVolumeLimit");
#pragma mark - Wireless Information
static const CFStringRef kMGActiveWirelessTechnology = CFSTR("ActiveWirelessTechnology");
static const CFStringRef kMGWifiAddress = CFSTR("WifiAddress");
static const CFStringRef kMGWifiAddressData = CFSTR("WifiAddressData");
static const CFStringRef kMGWifiVendor = CFSTR("WifiVendor");
#pragma mark - FaceTime Information
static const CFStringRef kMGFaceTimeBitRate2G = CFSTR("FaceTimeBitRate2G");
static const CFStringRef kMGFaceTimeBitRate3G = CFSTR("FaceTimeBitRate3G");
static const CFStringRef kMGFaceTimeBitRateLTE = CFSTR("FaceTimeBitRateLTE");
static const CFStringRef kMGFaceTimeBitRateWiFi = CFSTR("FaceTimeBitRateWiFi");
static const CFStringRef kMGFaceTimeDecodings = CFSTR("FaceTimeDecodings");
static const CFStringRef kMGFaceTimeEncodings = CFSTR("FaceTimeEncodings");
static const CFStringRef kMGFaceTimePreferredDecoding = CFSTR("FaceTimePreferredDecoding");
static const CFStringRef kMGFaceTimePreferredEncoding = CFSTR("FaceTimePreferredEncoding");
#pragma mark - More Device Capabilities
static const CFStringRef kMGDeviceSupportsFaceTime = CFSTR("DeviceSupportsFaceTime");
static const CFStringRef kMGDeviceSupportsTethering = CFSTR("DeviceSupportsTethering");
static const CFStringRef kMGDeviceSupportsSimplisticRoadMesh = CFSTR("DeviceSupportsSimplisticRoadMesh");
static const CFStringRef kMGDeviceSupportsNavigation = CFSTR("DeviceSupportsNavigation");
static const CFStringRef kMGDeviceSupportsLineIn = CFSTR("DeviceSupportsLineIn");
static const CFStringRef kMGDeviceSupports9Pin = CFSTR("DeviceSupports9Pin");
static const CFStringRef kMGDeviceSupports720p = CFSTR("DeviceSupports720p");
static const CFStringRef kMGDeviceSupports4G = CFSTR("DeviceSupports4G");
static const CFStringRef kMGDeviceSupports3DMaps = CFSTR("DeviceSupports3DMaps");
static const CFStringRef kMGDeviceSupports3DImagery = CFSTR("DeviceSupports3DImagery");
static const CFStringRef kMGDeviceSupports1080p = CFSTR("DeviceSupports1080p");
#if __cplusplus
}
#endif

#endif /* LIBMOBILEGESTALT_H_ */

+ 87
- 0
NSTask.h View File

@@ -0,0 +1,87 @@
/* NSTask.h
Copyright (c) 1996-2017, Apple Inc. All rights reserved.
*/

#import <Foundation/NSObject.h>
#import <Foundation/NSNotification.h>

@class NSArray<ObjectType>, NSDictionary<KeyType, ObjectType>, NSString;

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSInteger, NSTaskTerminationReason) {
NSTaskTerminationReasonExit = 1,
NSTaskTerminationReasonUncaughtSignal = 2
} NS_ENUM_AVAILABLE(10_6, NA);

@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 NS_DESIGNATED_INITIALIZER;

// these methods can only be set before a launch
@property (nullable, copy) NSURL *executableURL API_AVAILABLE(macos(10.13)) API_UNAVAILABLE(ios, watchos, tvos);
@property (nullable, copy) NSArray<NSString *> *arguments;
@property (nullable, copy) NSDictionary<NSString *, NSString *> *environment; // if not set, use current
@property (nullable, copy) NSURL *currentDirectoryURL API_AVAILABLE(macos(10.13)) API_UNAVAILABLE(ios, watchos, tvos);

// standard I/O channels; could be either an NSFileHandle or an NSPipe
@property (nullable, retain) id standardInput;
@property (nullable, retain) id standardOutput;
@property (nullable, retain) id standardError;

// actions
- (BOOL)launchAndReturnError:(out NSError **_Nullable)error API_AVAILABLE(macos(10.13)) API_UNAVAILABLE(ios, watchos, tvos);

- (void)interrupt; // Not always possible. Sends SIGINT.
- (void)terminate; // Not always possible. Sends SIGTERM.

- (BOOL)suspend;
- (BOOL)resume;

// status
@property (readonly) int processIdentifier;
@property (readonly, getter=isRunning) BOOL running;

@property (readonly) int terminationStatus;
@property (readonly) NSTaskTerminationReason terminationReason API_AVAILABLE(macos(10.6)) API_UNAVAILABLE(ios, watchos, tvos);

/*
A block to be invoked when the process underlying the NSTask terminates. Setting the block to nil is valid, and stops the previous block from being invoked, as long as it hasn't started in any way. The NSTask is passed as the argument to the block so the block does not have to capture, and thus retain, it. The block is copied when set. Only one termination handler block can be set at any time. The execution context in which the block is invoked is undefined. If the NSTask has already finished, the block is executed immediately/soon (not necessarily on the current thread). If a terminationHandler is set on an NSTask, the NSTaskDidTerminateNotification notification is not posted for that task. Also note that -waitUntilExit won't wait until the terminationHandler has been fully executed. You cannot use this property in a concrete subclass of NSTask which hasn't been updated to include an implementation of the storage and use of it.
*/
@property (nullable, copy) void (^terminationHandler)(NSTask *) API_AVAILABLE(macos(10.7)) API_UNAVAILABLE(ios, watchos, tvos);

@property NSQualityOfService qualityOfService API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0)); // read-only after the task is launched

@end

@interface NSTask (NSTaskConveniences)

+ (nullable NSTask *)launchedTaskWithExecutableURL:(NSURL *)url arguments:(NSArray<NSString *> *)arguments error:(out NSError ** _Nullable)error terminationHandler:(void (^_Nullable)(NSTask *))terminationHandler API_AVAILABLE(macos(10.13)) API_UNAVAILABLE(ios, watchos, tvos);

- (void)waitUntilExit;
// poll the runLoop in defaultMode until task completes

@end

@interface NSTask (NSDeprecated)

@property (nullable, copy) NSString *launchPath;
@property (copy) NSString *currentDirectoryPath; // if not set, use current

- (void)launch;

+ (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray<NSString *> *)arguments;
// convenience; create and launch

@end

FOUNDATION_EXPORT NSNotificationName const NSTaskDidTerminateNotification;

NS_ASSUME_NONNULL_END

Loading…
Cancel
Save