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"
17 #include "wx/unix/execute.h"
22 #pragma implementation
27 #include "wx/process.h"
28 #include "wx/stream.h"
30 #include "wx/cocoa/string.h"
32 #import <Foundation/Foundation.h>
33 #import <AppKit/NSWorkspace.h>
36 // RN: This is a prelimenary implementation - simple
37 // launching and process redirection works,
38 // but with the piping tests in the exec sample
39 // SIGPIPE is triggered...
42 class wxPipeInputStream : public wxInputStream
45 wxPipeInputStream(NSPipe* thePipe) :
47 m_theHandle([m_thePipe fileHandleForReading])
57 virtual size_t OnSysRead(void *buffer, size_t size)
59 NSData* theData = [m_theHandle readDataOfLength:size];
60 memcpy(buffer, [theData bytes], [theData length]);
61 return [theData length];
66 NSFileHandle* m_theHandle;
69 class wxPipeOutputStream : public wxOutputStream
72 wxPipeOutputStream(NSPipe* thePipe) :
74 m_theHandle([m_thePipe fileHandleForWriting])
85 virtual size_t OnSysWrite(const void *buffer, size_t bufsize)
87 NSData* theData = [NSData dataWithBytesNoCopy:(void*)buffer
89 [m_theHandle writeData:theData];
94 NSFileHandle* m_theHandle;
97 @interface wxTaskHandler : NSObject
102 -(id)init:(void*)handle processIdentifier:(long)pid;
103 - (void)termHandler:(NSNotification *)aNotification;
106 @implementation wxTaskHandler : NSObject
108 -(id)init:(void*)handle processIdentifier:(long)pid
115 [[NSNotificationCenter defaultCenter] addObserver:self
116 selector:@selector(termHandler:)
117 name:NSTaskDidTerminateNotification
122 - (void)termHandler:(NSNotification *)aNotification
124 NSTask* theTask = [aNotification object];
126 if ([theTask processIdentifier] == m_pid)
128 ((wxProcess*)m_handle)->OnTerminate([theTask processIdentifier],
129 [theTask terminationStatus]);
137 long wxExecute(const wxString& command,
141 NSTask* theTask = [[NSTask alloc] init];
143 if (handle && handle->IsRedirected())
145 NSPipe* theStdinPipe = [[NSPipe alloc] init];
146 NSPipe* theStderrPipe = [[NSPipe alloc] init];
147 NSPipe* theStdoutPipe = [[NSPipe alloc] init];
149 [theTask setStandardInput:theStdinPipe];
150 [theTask setStandardError:theStderrPipe];
151 [theTask setStandardOutput:theStdoutPipe];
153 handle->SetPipeStreams(new wxPipeInputStream(theStdoutPipe),
154 new wxPipeOutputStream(theStdinPipe),
155 new wxPipeInputStream(theStderrPipe) );
158 NSArray* theQuoteArguments =
159 [wxNSStringWithWxString(command) componentsSeparatedByString:@"\""];
161 NSMutableArray* theSeperatedArguments =
162 [NSMutableArray arrayWithCapacity:10];
164 for (unsigned i = 0; i < [theQuoteArguments count]; ++i)
166 [theSeperatedArguments addObjectsFromArray:
167 [[theQuoteArguments objectAtIndex:i] componentsSeparatedByString:@" "]
170 if(++i < [theQuoteArguments count])
171 [theSeperatedArguments addObject:[theQuoteArguments objectAtIndex:i]];
174 [theTask setLaunchPath:[theSeperatedArguments objectAtIndex:0]];
175 [theTask setArguments:theSeperatedArguments];
178 if(sync & wxEXEC_ASYNC)
180 [[wxTaskHandler alloc]init:handle
181 processIdentifier:[theTask processIdentifier]];
187 [theTask waitUntilExit];
189 return [theTask terminationStatus];