/* Copyright (C) 2002-2003, Jeffrey D. Argast. The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. Permission is hereby granted to use, copy, modify, and distribute this software or portions thereof for any purpose, without fee, subject to these conditions: (1) If any part of the source code is distributed, then this statement must be included, with this copyright and no-warranty notice unaltered. (2) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. */ #import "AppEnvironment.h" #import "AppUtils.h" #import "MessageDefs.h" /* static NSArray* gPath; static NSString* gPerforceHost; static NSString* gPerforcePort; static NSString* gPerforceUser; static NSString* gPerforceClient; static NSString* gPerforceDiff; static NSString* gPerforceMerge; static NSString* gPerforceEditor; static NSString* gPerforcePasswd; */ static AppEnvironment* gAppEnv = nil; static NSArray* ParsePath (NSString* pathString); static NSString* kEqualSign = @"="; static NSString* kNewLine = @"\n"; static NSString* kStopString = @":"; static NSString* kMissingEnv = @"!"; static NSString* kOverridePathKey = @"OverridePathEnv"; static NSString* kPathOverrideEnvKey = @"PathOverrideEnv"; @implementation AppEnvironment + (void) initialize { NSMutableDictionary* defaultValues = [NSMutableDictionary dictionary]; [defaultValues setObject:[NSNumber numberWithBool:NO] forKey:kOverridePathKey]; [[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues]; } + (void) startup { gAppEnv = [[AppEnvironment alloc] init]; NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; gAppEnv->fIsPathOverridden = [userDefaults boolForKey:kOverridePathKey]; gAppEnv->fOverridePathEnv = [[userDefaults objectForKey:kPathOverrideEnvKey] retain]; // Get the environment from our helper app. The helper app sources .login // to add any user defined paths NSString* execPath = [[NSBundle mainBundle] pathForAuxiliaryExecutable:@"gettermenv"]; if ( execPath ) { NSTask* getEnvTask = [[[NSTask alloc] init] autorelease]; NSPipe* stdOutPipe = [NSPipe pipe]; NSFileHandle* stdOut = [stdOutPipe fileHandleForReading]; [getEnvTask setLaunchPath:execPath]; [getEnvTask setStandardOutput:stdOutPipe]; [getEnvTask launch]; NSData* data = [stdOut readDataToEndOfFile]; NSString* envString = [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]; if ( [envString length] > 0 ) { NSString* resultString; NSScanner* envScanner = [NSScanner scannerWithString:envString]; // Get the PATH [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; if ( ![resultString isEqualToString:kMissingEnv] ) { [envScanner scanUpToString:kNewLine intoString:&resultString]; [self setPath:resultString]; gAppEnv->fStartupPathEnv = [resultString copy]; } else { [self setPath:nil]; gAppEnv->fStartupPathEnv = [[NSString alloc] initWithString:@""]; } // Get the HOST [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; [envScanner scanUpToString:kNewLine intoString:&resultString]; if ( ![resultString isEqualToString:kMissingEnv] ) { [self setPerforceHost:resultString]; } else { [self setPerforceHost:nil]; } // Get the PORT [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; [envScanner scanUpToString:kNewLine intoString:&resultString]; if ( ![resultString isEqualToString:kMissingEnv] ) { [self setPerforcePort:resultString]; } else { [self setPerforcePort:nil]; } // Get the USER [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; [envScanner scanUpToString:kNewLine intoString:&resultString]; if ( ![resultString isEqualToString:kMissingEnv] ) { [self setPerforceUser:resultString]; } else { [self setPerforceUser:nil]; } // Get the CLIENT [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; [envScanner scanUpToString:kNewLine intoString:&resultString]; if ( ![resultString isEqualToString:kMissingEnv] ) { [self setPerforceClient:resultString]; } else { [self setPerforceClient:nil]; } // Get the DIFF [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; [envScanner scanUpToString:kNewLine intoString:&resultString]; if ( ![resultString isEqualToString:kMissingEnv] ) { [self setPerforceDiff:resultString]; } else { [self setPerforceDiff:nil]; } // Get the MERGE [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; [envScanner scanUpToString:kNewLine intoString:&resultString]; if ( ![resultString isEqualToString:kMissingEnv] ) { [self setPerforceMerge:resultString]; } else { [self setPerforceMerge:nil]; } // Get the EDITOR [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; [envScanner scanUpToString:kNewLine intoString:&resultString]; if ( ![resultString isEqualToString:kMissingEnv] ) { // special case bbedit -w if ( [resultString isEqualToString:@"bbedit -w"] ) { [self setPerforceEditor:@"bbedit"]; } else { [self setPerforceEditor:resultString]; } } else { [self setPerforceEditor:nil]; } // Get the PASSWD [envScanner scanUpToString:kEqualSign intoString:&resultString]; [envScanner scanString:kEqualSign intoString:nil]; [envScanner scanUpToString:kNewLine intoString:&resultString]; if ( ![resultString isEqualToString:kMissingEnv] ) { [self setPerforcePasswd:resultString]; } else { [self setPerforcePasswd:nil]; } } else { // something bad has happened so just set everything to empty [self setPath:nil]; [self setPerforceHost:nil]; [self setPerforcePort:nil]; [self setPerforceUser:nil]; [self setPerforceClient:nil]; [self setPerforceDiff:nil]; [self setPerforceMerge:nil]; [self setPerforceEditor:nil]; [self setPerforcePasswd:nil]; gAppEnv->fStartupPathEnv = [[NSString alloc] initWithString:@""]; } } else { NSLog (@"cannot find aux application"); } if ( !gAppEnv->fOverridePathEnv ) { gAppEnv->fOverridePathEnv = [gAppEnv->fStartupPathEnv copy]; } if ( gAppEnv->fIsPathOverridden ) { [self setPath:gAppEnv->fOverridePathEnv]; } } + (NSString*) startupPath { return gAppEnv->fStartupPathEnv; } + (void) setPathOverride:(NSString*)newPath makeActive:(BOOL)override { if ( (gAppEnv->fIsPathOverridden != override) || (![gAppEnv->fOverridePathEnv isEqualToString:newPath]) ) { [gAppEnv->fOverridePathEnv release]; if ( newPath ) { gAppEnv->fOverridePathEnv = [newPath copy]; } else { gAppEnv->fOverridePathEnv = [[NSString alloc] initWithString:@""]; } [[NSUserDefaults standardUserDefaults] setObject:gAppEnv->fOverridePathEnv forKey:kPathOverrideEnvKey]; gAppEnv->fIsPathOverridden = override; [[NSUserDefaults standardUserDefaults] setBool:gAppEnv->fIsPathOverridden forKey:kOverridePathKey]; if ( gAppEnv->fIsPathOverridden ) { [self setPath:gAppEnv->fOverridePathEnv]; } else { [self setPath:gAppEnv->fStartupPathEnv]; } SendNotification (kRefreshAllViews); } } + (NSString*) overridePath { return gAppEnv->fOverridePathEnv; } + (void) setPath:(NSString*)newPath { [gAppEnv->fPath release]; [gAppEnv->fCurrentPathEnv release]; if ( newPath ) { gAppEnv->fCurrentPathEnv = [newPath copy]; gAppEnv->fPath = [ParsePath(newPath) retain]; } else { gAppEnv->fCurrentPathEnv = [[NSString alloc] initWithString:@""]; gAppEnv->fPath = [[NSArray alloc] init]; } setenv ("PATH", [gAppEnv->fCurrentPathEnv cString], 1); } + (NSString*) pathEnv { return gAppEnv->fCurrentPathEnv; } + (NSArray*) path { return gAppEnv->fPath; } + (BOOL) isPathOverridden { return gAppEnv->fIsPathOverridden; } + (void) setPerforceHost:(NSString*) host { [gAppEnv->fPerforceHost release]; if ( host ) { gAppEnv->fPerforceHost = [host retain]; } else { gAppEnv->fPerforceHost = [[NSString alloc] initWithString:@""]; } if ( gAppEnv->fPerforceHost && ([gAppEnv->fPerforceHost length] > 0) ) { setenv ("P4HOST", [gAppEnv->fPerforceHost cString], 1); } else { unsetenv ("P4HOST"); } } + (NSString*) perforceHost { return gAppEnv->fPerforceHost; } + (void) setPerforcePort:(NSString*) port { [gAppEnv->fPerforcePort release]; if ( port ) { gAppEnv->fPerforcePort = [port retain]; } else { gAppEnv->fPerforcePort = [[NSString alloc] initWithString:@""]; } if ( gAppEnv->fPerforcePort && ([gAppEnv->fPerforcePort length] > 0) ) { setenv ("P4PORT", [gAppEnv->fPerforcePort cString], 1); } else { unsetenv ("P4PORT"); } } + (NSString*) perforcePort { return gAppEnv->fPerforcePort; } + (void) setPerforceUser:(NSString*) user { [gAppEnv->fPerforceUser release]; if ( user ) { gAppEnv->fPerforceUser = [user retain]; } else { gAppEnv->fPerforceUser = [[NSString alloc] initWithString:@""]; } if ( gAppEnv->fPerforceUser && ([gAppEnv->fPerforceUser length] > 0) ) { setenv ("P4USER", [gAppEnv->fPerforceUser cString], 1); } else { unsetenv ("P4USER"); } } + (NSString*) perforceUser { return gAppEnv->fPerforceUser; } + (void) setPerforceClient:(NSString*) client { [gAppEnv->fPerforceClient release]; if ( client ) { gAppEnv->fPerforceClient = [client retain]; } else { gAppEnv->fPerforceClient = [[NSString alloc] initWithString:@""]; } if ( gAppEnv->fPerforceClient && ([gAppEnv->fPerforceClient length] > 0) ) { setenv ("P4CLIENT", [gAppEnv->fPerforceClient cString], 1); } else { unsetenv ("P4CLIENT"); } } + (NSString*) perforceClient { return gAppEnv->fPerforceClient; } + (void) setPerforceDiff:(NSString*) diff { [gAppEnv->fPerforceDiff release]; if ( diff ) { gAppEnv->fPerforceDiff = [diff retain]; } else { gAppEnv->fPerforceDiff = [[NSString alloc] initWithString:@""]; } if ( gAppEnv->fPerforceDiff && ([gAppEnv->fPerforceDiff length] > 0) ) { setenv ("P4DIFF", [gAppEnv->fPerforceDiff cString], 1); } else { unsetenv ("P4DIFF"); } } + (NSString*) perforceDiff { return gAppEnv->fPerforceDiff; } + (void) setPerforceMerge:(NSString*) merge { [gAppEnv->fPerforceMerge release]; if ( merge ) { gAppEnv->fPerforceMerge = [merge retain]; } else { gAppEnv->fPerforceMerge = [[NSString alloc] initWithString:@""]; } if ( gAppEnv->fPerforceMerge && ([gAppEnv->fPerforceMerge length] > 0) ) { setenv ("P4MERGE", [gAppEnv->fPerforceMerge cString], 1); } else { unsetenv ("P4MERGE"); } } + (NSString*) perforceMerge { return gAppEnv->fPerforceMerge; } + (void) setPerforceEditor:(NSString*) editor { [gAppEnv->fPerforceEditor release]; if ( editor ) { gAppEnv->fPerforceEditor = [editor retain]; } else { gAppEnv->fPerforceEditor = [[NSString alloc] initWithString:@""]; } if ( gAppEnv->fPerforceEditor && ([gAppEnv->fPerforceEditor length] > 0) ) { setenv ("P4EDITOR", [gAppEnv->fPerforceEditor cString], 1); } else { unsetenv ("P4EDITOR"); } } + (NSString*) perforceEditor { return gAppEnv->fPerforceEditor; } + (void) setPerforcePasswd:(NSString*) passwd { [gAppEnv->fPerforcePasswd release]; if ( passwd ) { gAppEnv->fPerforcePasswd = [passwd retain]; } else { gAppEnv->fPerforcePasswd = [[NSString alloc] initWithString:@""]; } if ( gAppEnv->fPerforcePasswd && ([gAppEnv->fPerforcePasswd length] > 0) ) { setenv ("P4PASSWD", [gAppEnv->fPerforcePasswd cString], 1); } else { unsetenv ("P4PASSWD"); } } + (NSString*) perforcePasswd { return gAppEnv->fPerforcePasswd; } + (void) setUnicodeServer:(BOOL) unicodeServer { gAppEnv->fUnicodeServer = unicodeServer; if ( gAppEnv->fUnicodeServer ) { setenv ("P4CHARSET", "utf8", 1); } else { unsetenv ("P4CHARSET"); } } + (BOOL) unicodeServer { return gAppEnv->fUnicodeServer; } @end NSArray* ParsePath (NSString* pathString) { NSScanner* pathScanner = [NSScanner scannerWithString:pathString]; NSMutableArray* pathArray = [[[NSMutableArray alloc] init] autorelease]; NSString* resultString = nil; while ( [pathScanner scanUpToString:kStopString intoString:&resultString] ) { [pathArray addObject:resultString]; [pathScanner scanString:kStopString intoString:nil]; } return pathArray; }