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"
24 #include "wx/process.h"
25 #include "wx/stream.h"
27 #include "wx/cocoa/string.h"
29 #import <Foundation/Foundation.h>
30 #import <AppKit/NSWorkspace.h>
33 // RN: This is a prelimenary implementation - simple
34 // launching and process redirection works,
35 // but with the piping tests in the exec sample
36 // SIGPIPE is triggered...
39 class wxPipeInputStream : public wxInputStream
42 wxPipeInputStream(NSPipe* thePipe) :
44 m_theHandle([m_thePipe fileHandleForReading])
54 virtual size_t OnSysRead(void *buffer, size_t size)
56 NSData* theData = [m_theHandle readDataOfLength:size];
57 memcpy(buffer, [theData bytes], [theData length]);
58 return [theData length];
63 NSFileHandle* m_theHandle;
66 class wxPipeOutputStream : public wxOutputStream
69 wxPipeOutputStream(NSPipe* thePipe) :
71 m_theHandle([m_thePipe fileHandleForWriting])
82 virtual size_t OnSysWrite(const void *buffer, size_t bufsize)
84 NSData* theData = [NSData dataWithBytesNoCopy:(void*)buffer
86 [m_theHandle writeData:theData];
91 NSFileHandle* m_theHandle;
94 @interface wxTaskHandler : NSObject
99 -(id)init:(void*)handle processIdentifier:(long)pid;
100 - (void)termHandler:(NSNotification *)aNotification;
103 @implementation wxTaskHandler : NSObject
105 -(id)init:(void*)handle processIdentifier:(long)pid
112 [[NSNotificationCenter defaultCenter] addObserver:self
113 selector:@selector(termHandler:)
114 name:NSTaskDidTerminateNotification
119 - (void)termHandler:(NSNotification *)aNotification
121 NSTask* theTask = [aNotification object];
123 if ([theTask processIdentifier] == m_pid)
125 ((wxProcess*)m_handle)->OnTerminate([theTask processIdentifier],
126 [theTask terminationStatus]);
134 long wxExecute(const wxString& command,
138 NSTask* theTask = [[NSTask alloc] init];
140 if (handle && handle->IsRedirected())
142 NSPipe* theStdinPipe = [[NSPipe alloc] init];
143 NSPipe* theStderrPipe = [[NSPipe alloc] init];
144 NSPipe* theStdoutPipe = [[NSPipe alloc] init];
146 [theTask setStandardInput:theStdinPipe];
147 [theTask setStandardError:theStderrPipe];
148 [theTask setStandardOutput:theStdoutPipe];
150 handle->SetPipeStreams(new wxPipeInputStream(theStdoutPipe),
151 new wxPipeOutputStream(theStdinPipe),
152 new wxPipeInputStream(theStderrPipe) );
155 NSArray* theQuoteArguments =
156 [wxNSStringWithWxString(command) componentsSeparatedByString:@"\""];
158 NSMutableArray* theSeparatedArguments =
159 [NSMutableArray arrayWithCapacity:10];
161 for (unsigned i = 0; i < [theQuoteArguments count]; ++i)
163 [theSeparatedArguments addObjectsFromArray:
164 [[theQuoteArguments objectAtIndex:i] componentsSeparatedByString:@" "]
167 if(++i < [theQuoteArguments count])
168 [theSeparatedArguments addObject:[theQuoteArguments objectAtIndex:i]];
171 [theTask setLaunchPath:[theSeparatedArguments objectAtIndex:0]];
172 [theTask setArguments:theSeparatedArguments];
175 if(sync & wxEXEC_ASYNC)
177 [[wxTaskHandler alloc]init:handle
178 processIdentifier:[theTask processIdentifier]];
184 [theTask waitUntilExit];
186 return [theTask terminationStatus];