mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 15:11:34 +00:00 
			
		
		
		
	Fix for #1905: PythonLauncher not working correctly on OSX 10.5/Leopard
This fixes both Python Launchar and the terminalcommand module.
This commit is contained in:
		
							parent
							
								
									6780a9dd9f
								
							
						
					
					
						commit
						f2ef92cee7
					
				
					 4 changed files with 45 additions and 103 deletions
				
			
		| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
# Generated from 'AEDataModel.h'
 | 
			
		||||
 | 
			
		||||
def FOUR_CHAR_CODE(x): return x
 | 
			
		||||
typeApplicationBundleID = FOUR_CHAR_CODE('bund')
 | 
			
		||||
typeBoolean = FOUR_CHAR_CODE('bool')
 | 
			
		||||
typeChar = FOUR_CHAR_CODE('TEXT')
 | 
			
		||||
typeSInt16 = FOUR_CHAR_CODE('shor')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,7 @@
 | 
			
		|||
 | 
			
		||||
def run(command):
 | 
			
		||||
    """Run a shell command in a new Terminal.app window."""
 | 
			
		||||
    termAddress = AE.AECreateDesc(typeApplSignature, TERMINAL_SIG)
 | 
			
		||||
    termAddress = AE.AECreateDesc(typeApplicationBundleID, "com.apple.Terminal")
 | 
			
		||||
    theEvent = AE.AECreateAppleEvent(kAECoreSuite, kAEDoScript, termAddress,
 | 
			
		||||
                                     kAutoGenerateReturnID, kAnyTransactionID)
 | 
			
		||||
    commandDesc = AE.AECreateDesc(typeChar, command)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,8 +121,8 @@
 | 
			
		|||
        return YES;
 | 
			
		||||
    } else {
 | 
			
		||||
        [self run];
 | 
			
		||||
        [self close];
 | 
			
		||||
        return NO;
 | 
			
		||||
	[self performSelector:@selector(close) withObject:nil afterDelay:0.0];
 | 
			
		||||
        return YES;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,108 +11,49 @@
 | 
			
		|||
#import <ApplicationServices/ApplicationServices.h>
 | 
			
		||||
#import "doscript.h"
 | 
			
		||||
 | 
			
		||||
/* I assume I could pick these up from somewhere, but where... */
 | 
			
		||||
#define CREATOR 'trmx'
 | 
			
		||||
 | 
			
		||||
#define ACTIVATE_CMD 'misc'
 | 
			
		||||
#define ACTIVATE_SUITE 'actv'
 | 
			
		||||
 | 
			
		||||
#define DOSCRIPT_CMD 'dosc'
 | 
			
		||||
#define DOSCRIPT_SUITE 'core'
 | 
			
		||||
#define WITHCOMMAND 'cmnd'
 | 
			
		||||
 | 
			
		||||
/* ... and there's probably also a better way to do this... */
 | 
			
		||||
#define START_TERMINAL "/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal &"
 | 
			
		||||
 | 
			
		||||
extern int 
 | 
			
		||||
doscript(const char *command)
 | 
			
		||||
{
 | 
			
		||||
    OSErr err;
 | 
			
		||||
    AppleEvent theAEvent, theReply;
 | 
			
		||||
    AEAddressDesc terminalAddress;
 | 
			
		||||
    AEDesc commandDesc;
 | 
			
		||||
    OSType terminalCreator = CREATOR;
 | 
			
		||||
	char *bundleID = "com.apple.Terminal";
 | 
			
		||||
	AppleEvent evt, res;
 | 
			
		||||
	AEDesc desc;
 | 
			
		||||
	OSStatus err;
 | 
			
		||||
 | 
			
		||||
    /* set up locals  */
 | 
			
		||||
    AECreateDesc(typeNull, NULL, 0, &theAEvent);
 | 
			
		||||
    AECreateDesc(typeNull, NULL, 0, &terminalAddress);
 | 
			
		||||
    AECreateDesc(typeNull, NULL, 0, &theReply);
 | 
			
		||||
    AECreateDesc(typeNull, NULL, 0, &commandDesc);
 | 
			
		||||
	[[NSWorkspace sharedWorkspace] launchApplication:@"/Applications/Utilities/Terminal.app/"];
 | 
			
		||||
 | 
			
		||||
    /* create the "activate" event for Terminal */
 | 
			
		||||
    err = AECreateDesc(typeApplSignature, (Ptr) &terminalCreator,
 | 
			
		||||
            sizeof(terminalCreator), &terminalAddress);
 | 
			
		||||
    if (err != noErr) {
 | 
			
		||||
        NSLog(@"doscript: AECreateDesc: error %d\n", err);
 | 
			
		||||
        goto bail;
 | 
			
		||||
    }
 | 
			
		||||
    err = AECreateAppleEvent(ACTIVATE_SUITE, ACTIVATE_CMD,
 | 
			
		||||
            &terminalAddress, kAutoGenerateReturnID,
 | 
			
		||||
            kAnyTransactionID, &theAEvent);
 | 
			
		||||
    
 | 
			
		||||
    if (err != noErr) {
 | 
			
		||||
        NSLog(@"doscript: AECreateAppleEvent(activate): error %d\n", err);
 | 
			
		||||
        goto bail;
 | 
			
		||||
    }
 | 
			
		||||
    /* send the event  */
 | 
			
		||||
    err = AESend(&theAEvent, &theReply, kAEWaitReply,
 | 
			
		||||
            kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
 | 
			
		||||
    if ( err == -600 ) {
 | 
			
		||||
        int count=10;
 | 
			
		||||
        /* If it failed with "no such process" try to start Terminal */
 | 
			
		||||
        err = system(START_TERMINAL);
 | 
			
		||||
        if ( err ) {
 | 
			
		||||
            NSLog(@"doscript: system(): %s\n", strerror(errno));
 | 
			
		||||
            goto bail;
 | 
			
		||||
        }
 | 
			
		||||
        do {
 | 
			
		||||
            sleep(1);
 | 
			
		||||
            /* send the event again */
 | 
			
		||||
            err = AESend(&theAEvent, &theReply, kAEWaitReply,
 | 
			
		||||
                    kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
 | 
			
		||||
        } while (err == -600 && --count > 0);
 | 
			
		||||
        if ( err == -600 )
 | 
			
		||||
            NSLog(@"doscript: Could not activate Terminal\n");
 | 
			
		||||
    }
 | 
			
		||||
    if (err != noErr) {
 | 
			
		||||
        NSLog(@"doscript: AESend(activate): error %d\n", err);
 | 
			
		||||
        goto bail;
 | 
			
		||||
	// Build event
 | 
			
		||||
	err = AEBuildAppleEvent(kAECoreSuite, kAEDoScript,
 | 
			
		||||
	                         typeApplicationBundleID,
 | 
			
		||||
	                         bundleID, strlen(bundleID),
 | 
			
		||||
	                         kAutoGenerateReturnID,
 | 
			
		||||
	                         kAnyTransactionID,
 | 
			
		||||
	                         &evt, NULL,
 | 
			
		||||
	                         "'----':utf8(@)", strlen(command),
 | 
			
		||||
	                         command);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		NSLog(@"AEBuildAppleEvent failed: %d\n", err);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    /* create the "doscript with command" event for Terminal */
 | 
			
		||||
    err = AECreateAppleEvent(DOSCRIPT_SUITE, DOSCRIPT_CMD,
 | 
			
		||||
            &terminalAddress, kAutoGenerateReturnID,
 | 
			
		||||
            kAnyTransactionID, &theAEvent);
 | 
			
		||||
    if (err != noErr) {
 | 
			
		||||
        NSLog(@"doscript: AECreateAppleEvent(doscript): error %d\n", err);
 | 
			
		||||
        goto bail;
 | 
			
		||||
	// Send event and check for any Apple Event Manager errors
 | 
			
		||||
	err = AESendMessage(&evt, &res, kAEWaitReply, kAEDefaultTimeout);
 | 
			
		||||
	AEDisposeDesc(&evt);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		NSLog(@"AESendMessage failed: %d\n", err);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	// Check for any application errors
 | 
			
		||||
	err = AEGetParamDesc(&res, keyErrorNumber, typeSInt32, &desc);
 | 
			
		||||
	AEDisposeDesc(&res);
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		AEGetDescData(&desc, &err, sizeof(err));
 | 
			
		||||
		NSLog(@"Terminal returned an error: %d", err);
 | 
			
		||||
		AEDisposeDesc(&desc);
 | 
			
		||||
	} else if (err == errAEDescNotFound) {
 | 
			
		||||
		err = noErr;
 | 
			
		||||
	} else {
 | 
			
		||||
		NSLog(@"AEGetPArmDesc returned an error: %d", err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    /* add the command to the apple event */
 | 
			
		||||
    err = AECreateDesc(typeChar, command, strlen(command), &commandDesc);
 | 
			
		||||
    if (err != noErr) {
 | 
			
		||||
        NSLog(@"doscript: AECreateDesc(command): error %d\n", err);
 | 
			
		||||
        goto bail;
 | 
			
		||||
    }
 | 
			
		||||
    err = AEPutParamDesc(&theAEvent, WITHCOMMAND, &commandDesc);
 | 
			
		||||
    if (err != noErr) {
 | 
			
		||||
        NSLog(@"doscript: AEPutParamDesc: error %d\n", err);
 | 
			
		||||
        goto bail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* send the command event to Terminal.app */
 | 
			
		||||
    err = AESend(&theAEvent, &theReply, kAEWaitReply,
 | 
			
		||||
            kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
 | 
			
		||||
    
 | 
			
		||||
    if (err != noErr) {
 | 
			
		||||
        NSLog(@"doscript: AESend(docommand): error %d\n", err);
 | 
			
		||||
        goto bail;
 | 
			
		||||
    }
 | 
			
		||||
    /* clean up and leave */
 | 
			
		||||
bail:
 | 
			
		||||
    AEDisposeDesc(&commandDesc);
 | 
			
		||||
    AEDisposeDesc(&theAEvent);
 | 
			
		||||
    AEDisposeDesc(&terminalAddress);
 | 
			
		||||
    AEDisposeDesc(&theReply);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue