diff options
-rw-r--r-- | Source/SPAppController.h | 5 | ||||
-rw-r--r-- | Source/SPAppController.m | 59 | ||||
-rw-r--r-- | Source/SPCopyTable.m | 2 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.h | 7 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.m | 26 | ||||
-rw-r--r-- | Source/SPStringAdditions.h | 1 | ||||
-rw-r--r-- | Source/SPStringAdditions.m | 35 | ||||
-rw-r--r-- | Source/SPTextViewAdditions.m | 2 |
8 files changed, 131 insertions, 6 deletions
diff --git a/Source/SPAppController.h b/Source/SPAppController.h index d9763766..d96af12f 100644 --- a/Source/SPAppController.h +++ b/Source/SPAppController.h @@ -50,6 +50,8 @@ NSMutableDictionary *bundleKeyEquivalents; NSMutableDictionary *installedBundleUUIDs; + NSMutableArray *runningBASHprocesses; + } // Window management @@ -95,6 +97,9 @@ - (NSArray *)bundleCategoriesForScope:(NSString*)scope; - (NSArray *)bundleItemsForScope:(NSString*)scope; - (NSDictionary *)bundleKeyEquivalentsForScope:(NSString*)scope; +- (void)registerBASHCommand:(NSDictionary*)commandDict; +- (void)unRegisterBASHCommand:(NSInteger)pid; +- (NSArray*)runningBASHProcesses; - (void)handleEventWithURL:(NSURL*)url; diff --git a/Source/SPAppController.m b/Source/SPAppController.m index 55eb4e17..12b9e9a4 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -57,6 +57,7 @@ bundleUsedScopes = [[NSMutableArray alloc] initWithCapacity:1]; bundleKeyEquivalents = [[NSMutableDictionary alloc] initWithCapacity:1]; installedBundleUUIDs = [[NSMutableDictionary alloc] initWithCapacity:1]; + runningBASHprocesses = [[NSMutableArray alloc] init]; [NSApp setDelegate:self]; } @@ -780,7 +781,7 @@ return; } - NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil error:&err]; + NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil callerDocument:self withName:([cmdData objectForKey:SPBundleFileNameKey])?[cmdData objectForKey:SPBundleFileNameKey]:@"" error:&err]; [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; @@ -831,6 +832,26 @@ } +- (void)registerBASHCommand:(NSDictionary*)commandDict +{ + [runningBASHprocesses addObject:commandDict]; +} + +- (void)unRegisterBASHCommand:(NSInteger)pid +{ + for(id cmd in runningBASHprocesses) { + if([[cmd objectForKey:@"pid"] integerValue] == pid) { + [runningBASHprocesses removeObject:cmd]; + break; + } + } +} + +- (NSArray*)runningBASHProcesses +{ + return (NSArray*)runningBASHprocesses; +} + #pragma mark - #pragma mark Window management @@ -1507,6 +1528,41 @@ } } +/** + * If Sequel Pro is terminating kill all running BASH scripts + */ +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +{ + + // Kill all registered BASH commands + for (NSWindow *aWindow in [NSApp orderedWindows]) { + if([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) { + for(SPDatabaseDocument *doc in [[aWindow windowController] documents]) { + for(NSDictionary* cmd in [doc runningBASHProcesses]) { + NSInteger pid = [[cmd objectForKey:@"pid"] intValue]; + NSTask *killTask = [[NSTask alloc] init]; + [killTask setLaunchPath:@"/bin/sh"]; + [killTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"kill -9 -%ld", pid], nil]]; + [killTask launch]; + [killTask waitUntilExit]; + [killTask release]; + } + } + } + } + for(NSDictionary* cmd in [self runningBASHProcesses]) { + NSInteger pid = [[cmd objectForKey:@"pid"] intValue]; + NSTask *killTask = [[NSTask alloc] init]; + [killTask setLaunchPath:@"/bin/sh"]; + [killTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"kill -9 -%ld", pid], nil]]; + [killTask launch]; + [killTask waitUntilExit]; + [killTask release]; + } + return YES; + +} + #pragma mark - /** @@ -1521,6 +1577,7 @@ if(bundleCategories) [bundleCategories release]; if(bundleKeyEquivalents) [bundleKeyEquivalents release]; if(installedBundleUUIDs) [installedBundleUUIDs release]; + if (runningBASHprocesses) [runningBASHprocesses release]; [prefsController release], prefsController = nil; diff --git a/Source/SPCopyTable.m b/Source/SPCopyTable.m index 6b746099..f06c4700 100644 --- a/Source/SPCopyTable.m +++ b/Source/SPCopyTable.m @@ -923,7 +923,7 @@ NSInteger MENU_EDIT_COPY_AS_SQL = 2003; return; } - NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil error:&err]; + NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil callerDocument:[[NSApp delegate] frontDocument] withName:([cmdData objectForKey:SPBundleFileNameKey])?[cmdData objectForKey:SPBundleFileNameKey]:@"" error:&err]; [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; diff --git a/Source/SPDatabaseDocument.h b/Source/SPDatabaseDocument.h index e4d12346..16330b39 100644 --- a/Source/SPDatabaseDocument.h +++ b/Source/SPDatabaseDocument.h @@ -188,7 +188,9 @@ NSDictionary *spfSession; NSMutableDictionary *spfPreferences; NSMutableDictionary *spfDocData; - + + NSMutableArray *runningBASHprocesses; + NSString *keyChainID; NSThread *printThread; @@ -355,6 +357,9 @@ // Scripting - (void)handleSchemeCommand:(NSDictionary*)commandDict; +- (void)registerBASHCommand:(NSDictionary*)commandDict; +- (void)unRegisterBASHCommand:(NSInteger)pid; +- (NSArray*)runningBASHProcesses; - (NSDictionary*)shellVariables; // State saving and setting diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index 4b52b39d..23805b12 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -116,6 +116,7 @@ spfSession = nil; spfPreferences = [[NSMutableDictionary alloc] init]; spfDocData = [[NSMutableDictionary alloc] init]; + runningBASHprocesses = [[NSMutableArray alloc] init]; titleAccessoryView = nil; taskProgressWindow = nil; @@ -2400,6 +2401,7 @@ */ - (void)applicationWillTerminate:(NSNotification *)notification { + // Auto-save preferences to spf file based connection if([self fileURL] && [[[self fileURL] path] length] && ![self isUntitled]) if(_isConnected && ![self saveDocumentWithFilePath:nil inBackground:YES onlyPreferences:YES contextInfo:nil]) { @@ -2408,7 +2410,7 @@ } [tablesListInstance selectionShouldChangeInTableView:nil]; - + // Note that this call does not need to be removed in release builds as leaks analysis output is only // dumped if [[SPLogger logger] setDumpLeaksOnTermination]; has been called first. [[SPLogger logger] dumpLeaks]; @@ -4738,6 +4740,26 @@ NSLog(@"received: %@", commandDict); } +- (void)registerBASHCommand:(NSDictionary*)commandDict +{ + [runningBASHprocesses addObject:commandDict]; +} + +- (void)unRegisterBASHCommand:(NSInteger)pid +{ + for(id cmd in runningBASHprocesses) { + if([[cmd objectForKey:@"pid"] integerValue] == pid) { + [runningBASHprocesses removeObject:cmd]; + break; + } + } +} + +- (NSArray*)runningBASHProcesses +{ + return (NSArray*)runningBASHprocesses; +} + - (NSDictionary*)shellVariables { NSMutableDictionary *env = [NSMutableDictionary dictionary]; @@ -4989,6 +5011,7 @@ */ - (void)dealloc { + // Unregister observers [prefs removeObserver:self forKeyPath:SPDisplayTableViewVerticalGridlines]; [prefs removeObserver:tableSourceInstance forKeyPath:SPDisplayTableViewVerticalGridlines]; @@ -5037,6 +5060,7 @@ if (taskProgressWindow) [taskProgressWindow release]; if (serverSupport) [serverSupport release]; if (processID) [processID release]; + if (runningBASHprocesses) [runningBASHprocesses release]; [super dealloc]; } diff --git a/Source/SPStringAdditions.h b/Source/SPStringAdditions.h index e9e3784c..b0e085aa 100644 --- a/Source/SPStringAdditions.h +++ b/Source/SPStringAdditions.h @@ -77,6 +77,7 @@ static inline id NSMutableAttributedStringAttributeAtIndex (NSMutableAttributedS - (CGFloat)levenshteinDistanceWithWord:(NSString *)stringB; +- (NSString *)runBashCommandWithEnvironment:(NSDictionary*)shellEnvironment atCurrentDirectoryPath:(NSString*)path callerDocument:(id)caller withName:(NSString*)name error:(NSError**)theError; - (NSString *)runBashCommandWithEnvironment:(NSDictionary*)shellEnvironment atCurrentDirectoryPath:(NSString*)path error:(NSError**)theError; @end diff --git a/Source/SPStringAdditions.m b/Source/SPStringAdditions.m index 907ebc05..658baadb 100644 --- a/Source/SPStringAdditions.m +++ b/Source/SPStringAdditions.m @@ -444,10 +444,14 @@ * * @param path The current directory for the bash command. If path is nil, the current directory is inherited from the process that created the receiver (normally /). * + * @param caller The SPDatabaseDocument which invoked that command to register the command for cancelling; if nil the command won't be registered. + * + * @param name The menu title of the command. + * * @param theError If not nil and the bash command failed it contains the returned error message as NSLocalizedDescriptionKey * */ -- (NSString *)runBashCommandWithEnvironment:(NSDictionary*)shellEnvironment atCurrentDirectoryPath:(NSString*)path error:(NSError**)theError +- (NSString *)runBashCommandWithEnvironment:(NSDictionary*)shellEnvironment atCurrentDirectoryPath:(NSString*)path callerDocument:(id)caller withName:(NSString*)name error:(NSError**)theError { BOOL userTerminated = NO; @@ -544,6 +548,16 @@ [bashTask setStandardError:stderr_pipe]; NSFileHandle *stderr_file = [stderr_pipe fileHandleForReading]; [bashTask launch]; + NSInteger pid = -1; + if(caller != nil && [caller respondsToSelector:@selector(registerBASHCommand:)]) { + // register command + pid = [bashTask processIdentifier]; + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:pid], @"pid", + name, @"name", + [[NSDate date] descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]], @"starttime", + nil]; + [caller registerBASHCommand:dict]; + } // Listen to ⌘. to terminate while(1) { @@ -569,6 +583,9 @@ [bashTask waitUntilExit]; + // unregister BASH command if it was registered + if(pid >= 0) [caller unRegisterBASHCommand:pid]; + if(userTerminated) { if(bashTask) [bashTask release]; NSBeep(); @@ -639,6 +656,22 @@ } /** + * Run self as BASH command(s) and return the result. + * This task can be interrupted by pressing ⌘. + * + * @param shellEnvironment A dictionary of environment variable values whose keys are the variable names. + * + * @param path The current directory for the bash command. If path is nil, the current directory is inherited from the process that created the receiver (normally /). + * + * @param theError If not nil and the bash command failed it contains the returned error message as NSLocalizedDescriptionKey + * + */ +- (NSString *)runBashCommandWithEnvironment:(NSDictionary*)shellEnvironment atCurrentDirectoryPath:(NSString*)path error:(NSError**)theError +{ + return [self runBashCommandWithEnvironment:shellEnvironment atCurrentDirectoryPath:path callerDocument:nil withName:@"" error:theError]; +} + +/** * Returns the minimum of a, b and c. */ - (NSInteger)smallestOf:(NSInteger)a andOf:(NSInteger)b andOf:(NSInteger)c diff --git a/Source/SPTextViewAdditions.m b/Source/SPTextViewAdditions.m index 0c9fe630..f75505df 100644 --- a/Source/SPTextViewAdditions.m +++ b/Source/SPTextViewAdditions.m @@ -603,7 +603,7 @@ return; } - NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil error:&err]; + NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil callerDocument:[[NSApp delegate] frontDocument] withName:([cmdData objectForKey:SPBundleFileNameKey])?[cmdData objectForKey:SPBundleFileNameKey]:@"" error:&err]; [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; |