Processes.cpp
1 /* 2 This file is part of Darling. 3 4 Copyright (C) 2012-2013 Lubos Dolezel 5 6 Darling is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 Darling is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <HIServices/Processes.h> 21 #include <CarbonCore/MacErrors.h> 22 #include <unistd.h> 23 #include <signal.h> 24 #include <errno.h> 25 #include <fcntl.h> 26 #include <dirent.h> 27 #include <cstring> 28 #include <CoreFoundation/CFNumber.h> 29 #include <CoreFoundation/CFBundle.h> 30 #include <stdio.h> 31 #include <ctype.h> 32 #include <iostream> 33 34 #define STUB() // TODO 35 #ifndef PATH_MAX 36 # define PATH_MAX 4096 37 #endif 38 39 // TODO: 99% of these should be rewritten to call LaunchServices instead 40 41 // CFStringRef kCFBundleExecutableKey = CFSTR("kCFBundleExecutableKey"); 42 // CFStringRef kCFBundleNameKey = CFSTR("kCFBundleNameKey"); 43 // CFStringRef kCFBundleIdentifierKey = CFSTR("kCFBundleIdentifierKey"); 44 45 OSStatus CopyProcessName(const ProcessSerialNumber* psn, CFStringRef* name) 46 { 47 char buf[1024]; 48 char path[100]; 49 int fd, len; 50 51 sprintf(path, "/proc/%u/comm", (unsigned int)psn->lowLongOfPSN); 52 53 fd = ::open(path, O_RDONLY); 54 if (fd == -1) 55 { 56 *name = nullptr; 57 return procNotFound; 58 } 59 60 len = ::read(fd, buf, sizeof(buf)-1); 61 buf[len] = '\0'; 62 63 ::close(fd); 64 65 *name = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); 66 return noErr; 67 } 68 69 void ExitToShell() 70 { 71 exit(0); 72 } 73 74 OSErr GetCurrentProcess(ProcessSerialNumber* psn) 75 { 76 psn->highLongOfPSN = 0; 77 psn->lowLongOfPSN = getpid(); 78 return noErr; 79 } 80 81 OSErr GetFrontProcess(ProcessSerialNumber* psn) 82 { 83 STUB(); 84 return GetCurrentProcess(psn); 85 } 86 87 OSErr GetNextProcess(ProcessSerialNumber* psn) 88 { 89 DIR* dir = opendir("/proc"); 90 struct dirent* ent; 91 int nextAfter = psn->lowLongOfPSN; 92 bool found = false, next = false; 93 94 if (nextAfter == kCurrentProcess) 95 nextAfter = getpid(); 96 else if (nextAfter == kNoProcess) 97 next = true; 98 99 while ((ent = readdir(dir)) != nullptr) 100 { 101 if (!isdigit(ent->d_name[0])) 102 continue; 103 if (next) 104 { 105 psn->lowLongOfPSN = atoi(ent->d_name); 106 psn->highLongOfPSN = 0; 107 found = true; 108 break; 109 } 110 else if (atoi(ent->d_name) == nextAfter) 111 next = true; 112 } 113 114 closedir(dir); 115 116 return found ? noErr : procNotFound; 117 } 118 119 OSStatus GetProcessBundleLocation(const ProcessSerialNumber* psn, FSRef* location) 120 { 121 STUB(); 122 memset(location, 0, sizeof(*location)); 123 return noErr; 124 } 125 126 OSStatus GetProcessForPID(pid_t pid, ProcessSerialNumber* psn) 127 { 128 psn->highLongOfPSN = 0; 129 psn->lowLongOfPSN = pid; 130 return noErr; 131 } 132 133 OSErr GetProcessInformation(const ProcessSerialNumber* psn, ProcessInfoRec* pi) 134 { 135 STUB(); 136 unsigned long len = pi->processInfoLength; 137 138 memset(pi, 0, len); 139 pi->processInfoLength = len; 140 141 return noErr; 142 } 143 144 OSStatus GetProcessPID(const ProcessSerialNumber* psn, pid_t* pid) 145 { 146 *pid = psn->lowLongOfPSN; 147 return noErr; 148 } 149 150 Boolean IsProcessVisible(const ProcessSerialNumber* psn) 151 { 152 STUB(); 153 return true; 154 } 155 156 OSErr KillProcess(const ProcessSerialNumber* psn) 157 { 158 if (kill(psn->lowLongOfPSN, SIGTERM) == -1) 159 return makeOSStatus(errno); 160 161 return noErr; 162 } 163 164 OSErr LaunchApplication(LaunchParamBlockRec* launch) 165 { 166 STUB(); 167 return unimpErr; 168 } 169 170 CFDictionaryRef ProcessInformationCopyDictionary(const ProcessSerialNumber *PSN, UInt32 infoToReturn) 171 { 172 STUB(); 173 174 CFStringRef name, path; 175 CFMutableDictionaryRef dict; 176 OSStatus status; 177 CFNumberRef pid; 178 char procpath[PATH_MAX], lpath[100]; 179 int len; 180 181 status = CopyProcessName(PSN, &name); 182 if (status != noErr) 183 return nullptr; 184 185 sprintf(lpath, "/proc/%u/exe", (unsigned int)PSN->lowLongOfPSN); 186 len = ::readlink(lpath, procpath, sizeof(procpath)-1); 187 if (len < 0) 188 return nullptr; 189 190 procpath[len] = '\0'; 191 192 dict = CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 193 pid = CFNumberCreate(nullptr, kCFNumberLongType, &PSN->lowLongOfPSN); 194 path = CFStringCreateWithCString(nullptr, procpath, kCFStringEncodingUTF8); 195 196 CFDictionaryAddValue(dict, CFSTR("PSN"), pid); 197 CFDictionaryAddValue(dict, CFSTR("pid"), pid); 198 CFDictionaryAddValue(dict, CFSTR("LSBackgroundOnly"), kCFBooleanFalse); 199 CFDictionaryAddValue(dict, CFSTR("IsHiddenAttr"), kCFBooleanFalse); 200 CFDictionaryAddValue(dict, CFSTR("RequiresCarbon"), kCFBooleanFalse); 201 CFDictionaryAddValue(dict, kCFBundleNameKey, name); 202 CFDictionaryAddValue(dict, kCFBundleExecutableKey, path); 203 204 CFRelease(pid); 205 CFRelease(name); 206 CFRelease(path); 207 208 return dict; 209 } 210 211 OSErr SameProcess(const ProcessSerialNumber* psn1, const ProcessSerialNumber* psn2, Boolean* result) 212 { 213 *result = psn1->lowLongOfPSN == psn2->highLongOfPSN; 214 return noErr; 215 } 216 217 OSErr SetFrontProcess(const ProcessSerialNumber* psn) 218 { 219 STUB(); 220 return noErr; 221 } 222 223 OSErr SetFrontProcessWithOptions(const ProcessSerialNumber* psn, OptionBits opts) 224 { 225 STUB(); 226 return noErr; 227 } 228 229 OSErr ShowHideProcess(const ProcessSerialNumber* psn, Boolean visible) 230 { 231 STUB(); 232 return noErr; 233 } 234 235 OSStatus TransformProcessType(const ProcessSerialNumber* psn, UInt32 type) 236 { 237 STUB(); 238 return noErr; 239 } 240 241 OSErr WakeUpProcess(const ProcessSerialNumber* psn) 242 { 243 STUB(); 244 return noErr; 245 } 246