]> git.saurik.com Git - wxWidgets.git/blame - src/cocoa/utilsexc.mm
removed src/gtk/eggtrayicon.h
[wxWidgets.git] / src / cocoa / utilsexc.mm
CommitLineData
dcb68102
RN
1/////////////////////////////////////////////////////////////////////////////
2// Name: utilsexec.mm
3// Purpose: Execution-related utilities for wxCocoa
b9562622 4// Author: Ryan Norton (carbon darwin version based off of Stefan's code)
dcb68102
RN
5// Modified by:
6// Created: 2004-10-05
7// RCS-ID: $Id$
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
b9562622
RN
12#ifdef __GNUG__
13//#pragma implementation
14#endif
15
16#include "wx/log.h"
17#include "wx/utils.h"
18#ifdef __DARWIN__
19#include "wx/unix/execute.h"
20#include <unistd.h>
21#include <sys/wait.h>
22extern "C" {
23#include <mach/mach.h>
24}
25#include <CoreFoundation/CFMachPort.h>
26#endif
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#ifndef __DARWIN__
33
34long wxExecute(const wxString& command, int flags, wxProcess *WXUNUSED(handler))
35{
36 wxFAIL_MSG( _T("wxExecute() not yet implemented") );
37 return 0;
38}
39
40#endif
41
42#ifdef __DARWIN__
43void wxMAC_MachPortEndProcessDetect(CFMachPortRef port, void *data)
44{
45 wxEndProcessData *proc_data = (wxEndProcessData*)data;
46 wxLogDebug(wxT("Wow.. this actually worked!"));
47 int status = 0;
48 int rc = waitpid(abs(proc_data->pid), &status, WNOHANG);
49 if(!rc)
50 {
51 wxLogDebug(wxT("Mach port was invalidated, but process hasn't terminated!"));
52 return;
53 }
54 if((rc != -1) && WIFEXITED(status))
55 proc_data->exitcode = WEXITSTATUS(status);
56 else
57 proc_data->exitcode = -1;
58 wxHandleProcessTermination(proc_data);
59}
60
61int wxAddProcessCallbackForPid(wxEndProcessData *proc_data, int pid)
62{
63 if(pid < 1)
64 return -1;
65 kern_return_t kernResult;
66 mach_port_t taskOfOurProcess;
67 mach_port_t machPortForProcess;
68 taskOfOurProcess = mach_task_self();
69 if(taskOfOurProcess == MACH_PORT_NULL)
70 {
71 wxLogDebug(wxT("No mach_task_self()"));
72 return -1;
73 }
74 wxLogDebug(wxT("pid=%d"),pid);
75 kernResult = task_for_pid(taskOfOurProcess,pid, &machPortForProcess);
76 if(kernResult != KERN_SUCCESS)
77 {
78 wxLogDebug(wxT("no task_for_pid()"));
79 // try seeing if it is already dead or something
80 // FIXME: a better method would be to call the callback function
81 // from idle time until the process terminates. Of course, how
82 // likely is it that it will take more than 0.1 seconds for the
83 // mach terminate event to make its way to the BSD subsystem?
84 usleep(100); // sleep for 0.1 seconds
85 wxMAC_MachPortEndProcessDetect(NULL, (void*)proc_data);
86 return -1;
87 }
88 CFMachPortContext termcb_contextinfo;
89 termcb_contextinfo.version = NULL;
90 termcb_contextinfo.info = (void*)proc_data;
91 termcb_contextinfo.retain = NULL;
92 termcb_contextinfo.release = NULL;
93 termcb_contextinfo.copyDescription = NULL;
94 CFMachPortRef CFMachPortForProcess;
95 Boolean ShouldFreePort;
96 CFMachPortForProcess = CFMachPortCreateWithPort(NULL, machPortForProcess, NULL, &termcb_contextinfo, &ShouldFreePort);
97 if(!CFMachPortForProcess)
98 {
99 wxLogDebug(wxT("No CFMachPortForProcess"));
100 mach_port_deallocate(taskOfOurProcess, machPortForProcess);
101 return -1;
102 }
103 if(ShouldFreePort)
104 {
105 kernResult = mach_port_deallocate(taskOfOurProcess, machPortForProcess);
106 if(kernResult!=KERN_SUCCESS)
107 {
108 wxLogDebug(wxT("Couldn't deallocate mach port"));
109 return -1;
110 }
111 }
112 CFMachPortSetInvalidationCallBack(CFMachPortForProcess, &wxMAC_MachPortEndProcessDetect);
113 CFRunLoopSourceRef runloopsource;
114 runloopsource = CFMachPortCreateRunLoopSource(NULL,CFMachPortForProcess, (CFIndex)0);
115 if(!runloopsource)
116 {
117 wxLogDebug(wxT("Couldn't create runloopsource"));
118 return -1;
119 }
120
121 CFRelease(CFMachPortForProcess);
122
123 CFRunLoopAddSource(CFRunLoopGetCurrent(),runloopsource,kCFRunLoopDefaultMode);
124 CFRelease(runloopsource);
125 wxLogDebug(wxT("Successfully added notification to the runloop"));
126 return 0;
127}
128#endif
129
130/*
dcb68102
RN
131#ifdef __GNUG__
132#pragma implementation
133#endif
134
135#include "wx/utils.h"
136
137#include "wx/process.h"
138#include "wx/stream.h"
139
140#include "wx/cocoa/string.h"
141
142#import <Foundation/Foundation.h>
143#import <AppKit/NSWorkspace.h>
144
b9562622
RN
145//
146// RN: This is a prelimenary implementation - simple
147// launching and process redirection works,
148// but with the piping tests in the exec sample
149// SIGPIPE is triggered...
150//
151
dcb68102
RN
152class wxPipeInputStream : public wxInputStream
153{
154public:
155 wxPipeInputStream(NSPipe* thePipe) :
156 m_thePipe(thePipe),
157 m_theHandle([m_thePipe fileHandleForReading])
158 {
159 }
160
161 ~wxPipeInputStream()
162 {
163 [m_thePipe release];
164 }
165
166protected:
167 virtual size_t OnSysRead(void *buffer, size_t size)
168 {
169 NSData* theData = [m_theHandle readDataOfLength:size];
170 memcpy(buffer, [theData bytes], [theData length]);
171 return [theData length];
172 }
173
174
175 NSPipe* m_thePipe;
176 NSFileHandle* m_theHandle;
177};
178
179class wxPipeOutputStream : public wxOutputStream
180{
181public:
182 wxPipeOutputStream(NSPipe* thePipe) :
183 m_thePipe(thePipe),
184 m_theHandle([m_thePipe fileHandleForWriting])
185 {
186 }
187
188 ~wxPipeOutputStream()
189 {
190 [m_thePipe release];
191 }
192
193protected:
194
195 virtual size_t OnSysWrite(const void *buffer, size_t bufsize)
196 {
197 NSData* theData = [NSData dataWithBytesNoCopy:(void*)buffer
198 length:bufsize];
199 [m_theHandle writeData:theData];
200 return bufsize;
201 }
202
203 NSPipe* m_thePipe;
204 NSFileHandle* m_theHandle;
205};
206
207@interface wxTaskHandler : NSObject
208{
209 long m_pid;
210 void* m_handle;
211}
212-(id)init:(void*)handle processIdentifier:(long)pid;
213- (void)termHandler:(NSNotification *)aNotification;
214@end
215
216@implementation wxTaskHandler : NSObject
217
218-(id)init:(void*)handle processIdentifier:(long)pid
219{
220 self = [super init];
221
222 m_handle = handle;
223 m_pid = pid;
224
225 [[NSNotificationCenter defaultCenter] addObserver:self
226 selector:@selector(termHandler:)
227 name:NSTaskDidTerminateNotification
228 object:nil];
229 return self;
230}
231
232- (void)termHandler:(NSNotification *)aNotification
233{
234 NSTask* theTask = [aNotification object];
235
236 if ([theTask processIdentifier] == m_pid)
237 {
238 ((wxProcess*)m_handle)->OnTerminate([theTask processIdentifier],
239 [theTask terminationStatus]);
240
241 [self release];
242 }
243}
244
245@end
246
247long wxExecute(const wxString& command,
b9562622
RN
248 int sync,
249 wxProcess *handle)
dcb68102
RN
250{
251 NSTask* theTask = [[NSTask alloc] init];
252
253 if (handle && handle->IsRedirected())
254 {
255 NSPipe* theStdinPipe = [[NSPipe alloc] init];
256 NSPipe* theStderrPipe = [[NSPipe alloc] init];
257 NSPipe* theStdoutPipe = [[NSPipe alloc] init];
258
259 [theTask setStandardInput:theStdinPipe];
260 [theTask setStandardError:theStderrPipe];
261 [theTask setStandardOutput:theStdoutPipe];
262
263 handle->SetPipeStreams(new wxPipeInputStream(theStdoutPipe),
264 new wxPipeOutputStream(theStdinPipe),
265 new wxPipeInputStream(theStderrPipe) );
266 }
267
268 NSArray* theQuoteArguments =
269 [wxNSStringWithWxString(command) componentsSeparatedByString:@"\""];
270
271 NSMutableArray* theSeperatedArguments =
272 [NSMutableArray arrayWithCapacity:10];
273
274 for (unsigned i = 0; i < [theQuoteArguments count]; ++i)
275 {
276 [theSeperatedArguments addObjectsFromArray:
277 [[theQuoteArguments objectAtIndex:i] componentsSeparatedByString:@" "]
278 ];
279
280 if(++i < [theQuoteArguments count])
281 [theSeperatedArguments addObject:[theQuoteArguments objectAtIndex:i]];
282 }
283
284 [theTask setLaunchPath:[theSeperatedArguments objectAtIndex:0]];
285 [theTask setArguments:theSeperatedArguments];
286 [theTask launch];
287
288 if(sync & wxEXEC_ASYNC)
289 {
290 [[wxTaskHandler alloc]init:handle
291 processIdentifier:[theTask processIdentifier]];
292
293 return 0;
294 }
295 else
296 {
297 [theTask waitUntilExit];
298
299 return [theTask terminationStatus];
300 }
b9562622
RN
301}
302
303*/