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 #import <Foundation/Foundation.h>
 
  35 #import <AppKit/NSWorkspace.h>
 
  38 // RN:  This is a prelimenary implementation - simple
 
  39 // launching and process redirection works,
 
  40 // but with the piping tests in the exec sample
 
  41 // SIGPIPE is triggered...
 
  44 class wxPipeInputStream : public wxInputStream
 
  47     wxPipeInputStream(NSPipe* thePipe) :
 
  49             m_theHandle([m_thePipe fileHandleForReading])
 
  59     virtual size_t OnSysRead(void *buffer, size_t size)
 
  61         NSData* theData = [m_theHandle readDataOfLength:size];
 
  62         memcpy(buffer, [theData bytes], [theData length]);
 
  63         return [theData length];
 
  68     NSFileHandle* m_theHandle;
 
  71 class wxPipeOutputStream : public wxOutputStream
 
  74     wxPipeOutputStream(NSPipe* thePipe) :
 
  76             m_theHandle([m_thePipe fileHandleForWriting])
 
  87     virtual size_t OnSysWrite(const void *buffer, size_t bufsize)
 
  89         NSData* theData = [NSData dataWithBytesNoCopy:(void*)buffer
 
  91         [m_theHandle writeData:theData];
 
  96     NSFileHandle* m_theHandle;
 
  99 @interface wxTaskHandler : NSObject
 
 104 -(id)init:(void*)handle processIdentifier:(long)pid;
 
 105 - (void)termHandler:(NSNotification *)aNotification;
 
 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]);
 
 139 long wxExecute(const wxString& command,
 
 143     NSTask* theTask = [[NSTask alloc] init];
 
 145     if (handle && handle->IsRedirected())
 
 147         NSPipe* theStdinPipe = [[NSPipe alloc] init];
 
 148         NSPipe* theStderrPipe = [[NSPipe alloc] init];
 
 149         NSPipe* theStdoutPipe = [[NSPipe alloc] init];
 
 151         [theTask setStandardInput:theStdinPipe];
 
 152         [theTask setStandardError:theStderrPipe];
 
 153         [theTask setStandardOutput:theStdoutPipe];
 
 155         handle->SetPipeStreams(new wxPipeInputStream(theStdoutPipe),
 
 156                                new wxPipeOutputStream(theStdinPipe),
 
 157                                new wxPipeInputStream(theStderrPipe) );
 
 160     NSArray* theQuoteArguments =
 
 161         [wxNSStringWithWxString(command) componentsSeparatedByString:@"\""];
 
 163     NSMutableArray* theSeparatedArguments =
 
 164         [NSMutableArray arrayWithCapacity:10];
 
 166     for (unsigned i = 0; i < [theQuoteArguments count]; ++i)
 
 168         [theSeparatedArguments addObjectsFromArray:
 
 169             [[theQuoteArguments objectAtIndex:i] componentsSeparatedByString:@" "]
 
 172         if(++i < [theQuoteArguments count])
 
 173             [theSeparatedArguments addObject:[theQuoteArguments objectAtIndex:i]];
 
 176     [theTask setLaunchPath:[theSeparatedArguments objectAtIndex:0]];
 
 177     [theTask setArguments:theSeparatedArguments];
 
 180     if(sync & wxEXEC_ASYNC)
 
 182         [[wxTaskHandler alloc]init:handle
 
 183                               processIdentifier:[theTask processIdentifier]];
 
 189         [theTask waitUntilExit];
 
 191         return [theTask terminationStatus];