commit bc4e3777df5d5d4560d21948b0980ff83e456530 Author: hrbrmstr Date: Sat Mar 13 12:44:17 2021 -0500 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17a7406 --- /dev/null +++ b/.gitignore @@ -0,0 +1,93 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject + +iOSInjectionProject/ + +### Xcode ### +# Xcode +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) + +## Xcode Patch +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno + +### Xcode Patch ### +**/xcshareddata/WorkspaceSettings.xcsettings diff --git a/archinfo.xcodeproj/project.pbxproj b/archinfo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..03fc0e7 --- /dev/null +++ b/archinfo.xcodeproj/project.pbxproj @@ -0,0 +1,332 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 01C9200B25FD06D20097CD09 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C9200A25FD06D20097CD09 /* main.swift */; }; + 01C9201325FD07020097CD09 /* procHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 01C9201225FD07020097CD09 /* procHelper.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 01C9200525FD06D20097CD09 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 01C9200725FD06D20097CD09 /* archinfo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = archinfo; sourceTree = BUILT_PRODUCTS_DIR; }; + 01C9200A25FD06D20097CD09 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 01C9201125FD07000097CD09 /* archinfo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "archinfo-Bridging-Header.h"; sourceTree = ""; }; + 01C9201225FD07020097CD09 /* procHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = procHelper.m; sourceTree = ""; }; + 01C9201625FD07160097CD09 /* procHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = procHelper.h; sourceTree = ""; }; + 01C9201925FD0A3C0097CD09 /* libbsm.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbsm.tbd; path = usr/lib/libbsm.tbd; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 01C9200425FD06D20097CD09 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 01C91FFE25FD06D20097CD09 = { + isa = PBXGroup; + children = ( + 01C9200925FD06D20097CD09 /* archinfo */, + 01C9200825FD06D20097CD09 /* Products */, + 01C9201825FD0A3B0097CD09 /* Frameworks */, + ); + sourceTree = ""; + }; + 01C9200825FD06D20097CD09 /* Products */ = { + isa = PBXGroup; + children = ( + 01C9200725FD06D20097CD09 /* archinfo */, + ); + name = Products; + sourceTree = ""; + }; + 01C9200925FD06D20097CD09 /* archinfo */ = { + isa = PBXGroup; + children = ( + 01C9201625FD07160097CD09 /* procHelper.h */, + 01C9201225FD07020097CD09 /* procHelper.m */, + 01C9200A25FD06D20097CD09 /* main.swift */, + 01C9201125FD07000097CD09 /* archinfo-Bridging-Header.h */, + ); + path = archinfo; + sourceTree = ""; + }; + 01C9201825FD0A3B0097CD09 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 01C9201925FD0A3C0097CD09 /* libbsm.tbd */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 01C9200625FD06D20097CD09 /* archinfo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 01C9200E25FD06D20097CD09 /* Build configuration list for PBXNativeTarget "archinfo" */; + buildPhases = ( + 01C9200325FD06D20097CD09 /* Sources */, + 01C9200425FD06D20097CD09 /* Frameworks */, + 01C9200525FD06D20097CD09 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = archinfo; + productName = archinfo; + productReference = 01C9200725FD06D20097CD09 /* archinfo */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 01C91FFF25FD06D20097CD09 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1250; + LastUpgradeCheck = 1250; + TargetAttributes = { + 01C9200625FD06D20097CD09 = { + CreatedOnToolsVersion = 12.5; + LastSwiftMigration = 1250; + }; + }; + }; + buildConfigurationList = 01C9200225FD06D20097CD09 /* Build configuration list for PBXProject "archinfo" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 01C91FFE25FD06D20097CD09; + productRefGroup = 01C9200825FD06D20097CD09 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 01C9200625FD06D20097CD09 /* archinfo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 01C9200325FD06D20097CD09 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 01C9200B25FD06D20097CD09 /* main.swift in Sources */, + 01C9201325FD07020097CD09 /* procHelper.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 01C9200C25FD06D20097CD09 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.3; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = NO; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 01C9200D25FD06D20097CD09 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.3; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 01C9200F25FD06D20097CD09 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = CBY22P58G8; + ENABLE_HARDENED_RUNTIME = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/archinfo", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "archinfo/archinfo-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 01C9201025FD06D20097CD09 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = CBY22P58G8; + ENABLE_HARDENED_RUNTIME = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/archinfo", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "archinfo/archinfo-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 01C9200225FD06D20097CD09 /* Build configuration list for PBXProject "archinfo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 01C9200C25FD06D20097CD09 /* Debug */, + 01C9200D25FD06D20097CD09 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 01C9200E25FD06D20097CD09 /* Build configuration list for PBXNativeTarget "archinfo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 01C9200F25FD06D20097CD09 /* Debug */, + 01C9201025FD06D20097CD09 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 01C91FFF25FD06D20097CD09 /* Project object */; +} diff --git a/archinfo/archinfo-Bridging-Header.h b/archinfo/archinfo-Bridging-Header.h new file mode 100644 index 0000000..966818c --- /dev/null +++ b/archinfo/archinfo-Bridging-Header.h @@ -0,0 +1,7 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import +#include "procHelper.h" + diff --git a/archinfo/main.swift b/archinfo/main.swift new file mode 100644 index 0000000..9bfc553 --- /dev/null +++ b/archinfo/main.swift @@ -0,0 +1,10 @@ +// +// main.swift +// archinfo +// +// Created by boB Rudis on 3/13/21. +// + +import Foundation + +print(processListToJSON(allProcesses()) ?? "{}") diff --git a/archinfo/procHelper.h b/archinfo/procHelper.h new file mode 100644 index 0000000..b109adb --- /dev/null +++ b/archinfo/procHelper.h @@ -0,0 +1,19 @@ +// +// procHelper.h +// RSwitch +// +// Created by hrbrmstr on 8/25/19. +// Copyright © 2019 Bob Rudis. All rights reserved. +// + +#ifndef procHelper_h +#define procHelper_h + +#include +#import + +NSString* archInfo(pid_t pid); +NSArray* allProcesses(void); +NSString *processListToJSON(NSArray * processListDict); + +#endif /* procHelper_h */ diff --git a/archinfo/procHelper.m b/archinfo/procHelper.m new file mode 100644 index 0000000..0977a21 --- /dev/null +++ b/archinfo/procHelper.m @@ -0,0 +1,115 @@ +#import +#import + +#include "procHelper.h" + +// archInfo() is due to the spelunking work of Patrick Wardle +NSString* archInfo(pid_t pid) { + + size_t size; + cpu_type_t type = -1; + int mib[CTL_MAXNAME] = {0}; + size_t length = CTL_MAXNAME; + struct kinfo_proc procInfo = {0}; + if (noErr != sysctlnametomib("sysctl.proc_cputype", mib, &length)) return(@"unknown"); + + mib[length] = pid; + length++; + size = sizeof(cpu_type_t); + if (noErr != sysctl(mib, (u_int)length, &type, &size, 0, 0)) return(@"unknown"); + + if (CPU_TYPE_X86_64 == type) return(@"x86_64"); + if (CPU_TYPE_ARM64 == type) { + mib[0] = CTL_KERN; //(re)init mib + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = pid; + + length = 4; //(re)set length + + size = sizeof(procInfo); //(re)set size + + if(noErr != sysctl(mib, (u_int)length, &procInfo, &size, NULL, 0)) return(@"amd64"); //get proc info + + //'P_TRANSLATED' set? set architecture to 'Intel' + return( (P_TRANSLATED == (P_TRANSLATED & procInfo.kp_proc.p_flag)) ? @"x86_64" : @"amd64"); + + } + + return(@"unknown"); + +} + +// The below is modified code from: +// +// Copyright (c) 2020 DeepTech, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +NSArray* allProcesses(){ + + static int maxArgumentSize = 0; + + if (maxArgumentSize == 0) { + size_t size = sizeof(maxArgumentSize); + if (sysctl((int[]) { CTL_KERN, KERN_ARGMAX }, 2, &maxArgumentSize, &size, NULL, 0) == -1) { + perror("sysctl argument size"); + maxArgumentSize = 4096; // Default + } + } + + NSMutableArray *processes = [NSMutableArray array]; + int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + struct kinfo_proc *info; + size_t length; + int count; + + if (sysctl(mib, 3, NULL, &length, NULL, 0) < 0) return nil; + if (!(info = malloc(length))) return nil; + if (sysctl(mib, 3, info, &length, NULL, 0) < 0) { + free(info); + return nil; + } + + count = (int)(length / sizeof(struct kinfo_proc)); + + for (int i = 0; i < count; i++) { + pid_t pid = info[i].kp_proc.p_pid; + if (pid == 0) continue; + size_t size = maxArgumentSize; + char* buffer = (char *)malloc(length); + if (sysctl((int[]){ CTL_KERN, KERN_PROCARGS2, pid }, 3, buffer, &size, NULL, 0) == 0) { + + NSString* executable = [NSString stringWithCString:(buffer+sizeof(int)) encoding:NSUTF8StringEncoding]; + [processes addObject:[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:pid], @"pid", + executable, @"executable", + archInfo(pid), @"arch", + nil]]; + } + + free(buffer); + + } + + free(info); + + return processes; +} + +NSString *processListToJSON(NSArray * processListDict) { + NSError * err; + NSData * jsonData = [NSJSONSerialization dataWithJSONObject:processListDict options:0 error:&err]; + return([[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]); +}