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