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,
 
 146                const wxExecuteEnv *env)
 
 148     NSTask* theTask = [[NSTask alloc] init];
 
 150     if (handle && handle->IsRedirected())
 
 152         NSPipe* theStdinPipe = [[NSPipe alloc] init];
 
 153         NSPipe* theStderrPipe = [[NSPipe alloc] init];
 
 154         NSPipe* theStdoutPipe = [[NSPipe alloc] init];
 
 156         [theTask setStandardInput:theStdinPipe];
 
 157         [theTask setStandardError:theStderrPipe];
 
 158         [theTask setStandardOutput:theStdoutPipe];
 
 160         handle->SetPipeStreams(new wxPipeInputStream(theStdoutPipe),
 
 161                                new wxPipeOutputStream(theStdinPipe),
 
 162                                new wxPipeInputStream(theStderrPipe) );
 
 165     NSArray* theQuoteArguments =
 
 166         [wxNSStringWithWxString(command) componentsSeparatedByString:@"\""];
 
 168     NSMutableArray* theSeparatedArguments =
 
 169         [NSMutableArray arrayWithCapacity:10];
 
 171     for (unsigned i = 0; i < [theQuoteArguments count]; ++i)
 
 173         [theSeparatedArguments addObjectsFromArray:
 
 174             [[theQuoteArguments objectAtIndex:i] componentsSeparatedByString:@" "]
 
 177         if(++i < [theQuoteArguments count])
 
 178             [theSeparatedArguments addObject:[theQuoteArguments objectAtIndex:i]];
 
 181     [theTask setLaunchPath:[theSeparatedArguments objectAtIndex:0]];
 
 182     [theTask setArguments:theSeparatedArguments];
 
 185     if(sync & wxEXEC_ASYNC)
 
 187         [[WX_GET_OBJC_CLASS(wxTaskHandler) alloc]init:handle
 
 188                               processIdentifier:[theTask processIdentifier]];
 
 194         [theTask waitUntilExit];
 
 196         return [theTask terminationStatus];