// // Perforce_ServerConfig.m // Perforce Server // // Created by Mike Ashmore on 3/3/10. // Copyright 2010 Mike Ashmore. All rights reserved. // #import "Perforce_ServerConfig.h" NSString *plistPath = @"/Library/LaunchDaemons/com.perforce.p4d.plist"; @implementation Perforce_ServerConfig @synthesize p4rootPath, p4logPath, p4port; - (BOOL) authenticatedRunCommand:(NSString *)command { BOOL ret = NO; char *buf = NULL; asprintf(&buf, [command UTF8String]); if(!buf) { return NO; } char* arguments[] = { "-c", buf, NULL }; if(AuthorizationExecuteWithPrivileges(auth, "/bin/sh", kAuthorizationFlagDefaults, arguments, NULL) == errAuthorizationSuccess) { int status; int pid = wait(&status); if(pid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) ret = YES; } free(buf); return ret; } - (BOOL) installPlist { NSDictionary *launchdPlist = [self launchdPrefList]; [launchdPlist writeToFile:@"/tmp/com.perforce.p4d.plist" atomically:YES]; return [self authenticatedRunCommand:[@"cp /tmp/com.perforce.p4d.plist " stringByAppendingString:plistPath]]; } - (BOOL) isRunning { BOOL running; // Run a shell command to check with launchctl if the com.perforce.p4d job is loaded NSArray *args = [NSArray arrayWithObjects:@"-c", @"launchctl list | grep com.perforce.p4d", nil]; NSTask *runCheck = [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:args]; [runCheck waitUntilExit]; // if grep doesn't see a line from launchctl indicating the com.perforce.p4d job is loaded, the command's exit status will be nonzero running = ([runCheck terminationStatus] == 0); return running; } - (void) startServer { NSFileManager *fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:plistPath]) { [self installPlist]; } [self authenticatedRunCommand:[@"launchctl load " stringByAppendingString:plistPath]]; } - (void) stopServer { [self authenticatedRunCommand:[@"launchctl unload " stringByAppendingString:plistPath]]; [self authenticatedRunCommand:[@"rm " stringByAppendingString:plistPath]]; } - (void) awakeFromNib { self.p4rootPath = [@"~/Documents/p4d" stringByStandardizingPath]; self.p4logPath = [@"~/Documents/p4d/log" stringByStandardizingPath]; self.p4port = [NSNumber numberWithInt:1666]; auth = nil; // create an empty authorization reference for later use by commands that need it if (AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagInteractionAllowed, &auth) != errAuthorizationSuccess) { auth = nil; } } - (NSDictionary *) launchdPrefList { NSBundle *mb = [NSBundle bundleWithIdentifier:@"com.perforce.p4d"]; NSString *launchdPlistTemplatePath = [mb pathForResource:@"com.perforce.p4d.plist" ofType:nil]; NSDictionary *launchdTemplate = [NSDictionary dictionaryWithContentsOfFile:launchdPlistTemplatePath]; NSString *p4dPath = [mb pathForResource:@"p4d" ofType:nil]; // Only one program argument, the path to the server. NSArray *programArgs = [NSArray arrayWithObject:p4dPath]; [launchdTemplate setValue:programArgs forKey:@"ProgramArguments"]; // and the environment variables we're setting ... NSDictionary *environment = [NSDictionary dictionaryWithObjectsAndKeys: self.p4rootPath, @"P4ROOT", self.p4logPath, @"P4LOG", [self.p4port stringValue], @"P4PORT", nil]; [launchdTemplate setValue:environment forKey:@"EnvironmentVariables"]; return launchdTemplate; } - (void) dealloc { [defaultsController release]; [super dealloc]; } @end