1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/cocoa/utilsexec.mm
3 // Purpose: Execution-related utilities for wxCocoa
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 // Notes: This code may be useful on platforms other than Darwin.
11 // On Darwin we share the CoreFoundation code with wxMac.
12 /////////////////////////////////////////////////////////////////////////////
14 #include "wx/wxprec.h"
20 #include "wx/unix/execute.h"
26 #include "wx/stream.h"
27 #endif // wxUSE_STREAMS
30 #include "wx/process.h"
32 #include "wx/cocoa/string.h"
34 #include "wx/cocoa/objc/objc_uniquifying.h"
36 #import <Foundation/Foundation.h>
37 #import <AppKit/NSWorkspace.h>
40 // RN: This is a prelimenary implementation - simple
41 // launching and process redirection works,
42 // but with the piping tests in the exec sample
43 // SIGPIPE is triggered...
46 class wxPipeInputStream : public wxInputStream
49 wxPipeInputStream(NSPipe* thePipe) :
51 m_theHandle([m_thePipe fileHandleForReading])
61 virtual size_t OnSysRead(void *buffer, size_t size)
63 NSData* theData = [m_theHandle readDataOfLength:size];
64 memcpy(buffer, [theData bytes], [theData length]);
65 return [theData length];
70 NSFileHandle* m_theHandle;
73 class wxPipeOutputStream : public wxOutputStream
76 wxPipeOutputStream(NSPipe* thePipe) :
78 m_theHandle([m_thePipe fileHandleForWriting])
89 virtual size_t OnSysWrite(const void *buffer, size_t bufsize)
91 NSData* theData = [NSData dataWithBytesNoCopy:(void*)buffer
93 [m_theHandle writeData:theData];
98 NSFileHandle* m_theHandle;
101 @interface wxTaskHandler : NSObject
106 -(id)init:(void*)handle processIdentifier:(long)pid;
107 - (void)termHandler:(NSNotification *)aNotification;
109 WX_DECLARE_GET_OBJC_CLASS(wxTaskHandler,NSObject)
111 @implementation wxTaskHandler : NSObject
113 -(id)init:(void*)handle processIdentifier:(long)pid
120 [[NSNotificationCenter defaultCenter] addObserver:self
121 selector:@selector(termHandler:)
122 name:NSTaskDidTerminateNotification
127 - (void)termHandler:(NSNotification *)aNotification
129 NSTask* theTask = [aNotification object];
131 if ([theTask processIdentifier] == m_pid)
133 ((wxProcess*)m_handle)->OnTerminate([theTask processIdentifier],
134 [theTask terminationStatus]);
141 WX_IMPLEMENT_GET_OBJC_CLASS(wxTaskHandler,NSObject)
143 long wxExecute(const wxString& command,
147 NSTask* theTask = [[NSTask alloc] init];
149 if (handle && handle->IsRedirected())
151 NSPipe* theStdinPipe = [[NSPipe alloc] init];
152 NSPipe* theStderrPipe = [[NSPipe alloc] init];
153 NSPipe* theStdoutPipe = [[NSPipe alloc] init];
155 [theTask setStandardInput:theStdinPipe];
156 [theTask setStandardError:theStderrPipe];
157 [theTask setStandardOutput:theStdoutPipe];
159 handle->SetPipeStreams(new wxPipeInputStream(theStdoutPipe),
160 new wxPipeOutputStream(theStdinPipe),
161 new wxPipeInputStream(theStderrPipe) );
164 NSArray* theQuoteArguments =
165 [wxNSStringWithWxString(command) componentsSeparatedByString:@"\""];
167 NSMutableArray* theSeparatedArguments =
168 [NSMutableArray arrayWithCapacity:10];
170 for (unsigned i = 0; i < [theQuoteArguments count]; ++i)
172 [theSeparatedArguments addObjectsFromArray:
173 [[theQuoteArguments objectAtIndex:i] componentsSeparatedByString:@" "]
176 if(++i < [theQuoteArguments count])
177 [theSeparatedArguments addObject:[theQuoteArguments objectAtIndex:i]];
180 [theTask setLaunchPath:[theSeparatedArguments objectAtIndex:0]];
181 [theTask setArguments:theSeparatedArguments];
184 if(sync & wxEXEC_ASYNC)
186 [[WX_GET_OBJC_CLASS(wxTaskHandler) alloc]init:handle
187 processIdentifier:[theTask processIdentifier]];
193 [theTask waitUntilExit];
195 return [theTask terminationStatus];