1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/cocoa/utilsexec.mm
3 // Purpose: Execution-related utilities for wxCocoa
7 // Copyright: (c) Ryan Norton
8 // Licence: wxWindows licence
9 // Notes: This code may be useful on platforms other than Darwin.
10 // On Darwin we share the CoreFoundation code with wxMac.
11 /////////////////////////////////////////////////////////////////////////////
13 #include "wx/wxprec.h"
23 #include "wx/stream.h"
24 #endif // wxUSE_STREAMS
27 #include "wx/process.h"
29 #include "wx/cocoa/string.h"
31 #include "wx/cocoa/objc/objc_uniquifying.h"
33 #import <Foundation/Foundation.h>
34 #import <AppKit/NSWorkspace.h>
37 // RN: This is a prelimenary implementation - simple
38 // launching and process redirection works,
39 // but with the piping tests in the exec sample
40 // SIGPIPE is triggered...
43 class wxPipeInputStream : public wxInputStream
46 wxPipeInputStream(NSPipe* thePipe) :
48 m_theHandle([m_thePipe fileHandleForReading])
58 virtual size_t OnSysRead(void *buffer, size_t size)
60 NSData* theData = [m_theHandle readDataOfLength:size];
61 memcpy(buffer, [theData bytes], [theData length]);
62 return [theData length];
67 NSFileHandle* m_theHandle;
70 class wxPipeOutputStream : public wxOutputStream
73 wxPipeOutputStream(NSPipe* thePipe) :
75 m_theHandle([m_thePipe fileHandleForWriting])
86 virtual size_t OnSysWrite(const void *buffer, size_t bufsize)
88 NSData* theData = [NSData dataWithBytesNoCopy:(void*)buffer
90 [m_theHandle writeData:theData];
95 NSFileHandle* m_theHandle;
98 @interface wxTaskHandler : NSObject
103 -(id)init:(void*)handle processIdentifier:(long)pid;
104 - (void)termHandler:(NSNotification *)aNotification;
106 WX_DECLARE_GET_OBJC_CLASS(wxTaskHandler,NSObject)
108 @implementation wxTaskHandler : NSObject
110 -(id)init:(void*)handle processIdentifier:(long)pid
117 [[NSNotificationCenter defaultCenter] addObserver:self
118 selector:@selector(termHandler:)
119 name:NSTaskDidTerminateNotification
124 - (void)termHandler:(NSNotification *)aNotification
126 NSTask* theTask = [aNotification object];
128 if ([theTask processIdentifier] == m_pid)
130 ((wxProcess*)m_handle)->OnTerminate([theTask processIdentifier],
131 [theTask terminationStatus]);
138 WX_IMPLEMENT_GET_OBJC_CLASS(wxTaskHandler,NSObject)
140 long wxExecute(const wxString& command,
143 const wxExecuteEnv *env)
145 NSTask* theTask = [[NSTask alloc] init];
147 if (handle && handle->IsRedirected())
149 NSPipe* theStdinPipe = [[NSPipe alloc] init];
150 NSPipe* theStderrPipe = [[NSPipe alloc] init];
151 NSPipe* theStdoutPipe = [[NSPipe alloc] init];
153 [theTask setStandardInput:theStdinPipe];
154 [theTask setStandardError:theStderrPipe];
155 [theTask setStandardOutput:theStdoutPipe];
157 handle->SetPipeStreams(new wxPipeInputStream(theStdoutPipe),
158 new wxPipeOutputStream(theStdinPipe),
159 new wxPipeInputStream(theStderrPipe) );
162 NSArray* theQuoteArguments =
163 [wxNSStringWithWxString(command) componentsSeparatedByString:@"\""];
165 NSMutableArray* theSeparatedArguments =
166 [NSMutableArray arrayWithCapacity:10];
168 for (unsigned i = 0; i < [theQuoteArguments count]; ++i)
170 [theSeparatedArguments addObjectsFromArray:
171 [[theQuoteArguments objectAtIndex:i] componentsSeparatedByString:@" "]
174 if(++i < [theQuoteArguments count])
175 [theSeparatedArguments addObject:[theQuoteArguments objectAtIndex:i]];
178 [theTask setLaunchPath:[theSeparatedArguments objectAtIndex:0]];
179 [theTask setArguments:theSeparatedArguments];
182 if(sync & wxEXEC_ASYNC)
184 [[WX_GET_OBJC_CLASS(wxTaskHandler) alloc]init:handle
185 processIdentifier:[theTask processIdentifier]];
191 [theTask waitUntilExit];
193 return [theTask terminationStatus];