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];