// // PalletHelper.m // Pallet // // Created by Randall Hansen Wood on 16/3/2008. // Copyright 2008 __MyCompanyName__. All rights reserved. // #import "PalletHelper.h" @implementation MPPalletHelper - (id)init { self = [super init]; if (self) { } return self; } - (Boolean)exec:(NSString *)portName withTarget:(NSString *)target { NSDictionary *ports; NSEnumerator *portsEnumerator; id port; ports = [[MPMacPorts sharedInstance] search:portName]; portsEnumerator = [ports objectEnumerator]; while (port = [portsEnumerator nextObject]) { [port exec:target]; } return TRUE; } - (NSString *)pathToSelf { if (_pathToSelf == NULL) { size_t path_size = MAXPATHLEN; char* path = malloc(path_size); if (path && _NSGetExecutablePath(path, &path_size) == -1) { /* Try again with actual size */ path = realloc(path, path_size + 1); if (path && _NSGetExecutablePath(path, &path_size) != 0) { free(path); path = NULL; } } _pathToSelf = [NSString stringWithUTF8String:path]; } return _pathToSelf; } - (Boolean)repairSelf { AuthorizationRef authorization; NSString *pathToBundleResources; NSFileManager *fileManager; Boolean resultSelf = FALSE; Boolean resultBundleResources = FALSE; if ([self pathToSelf] != NULL) { pathToBundleResources = [[self pathToSelf] stringByDeletingLastPathComponent]; fileManager = [NSFileManager defaultManager]; if (AuthorizationCopyPrivilegedReference(&authorization, kAuthorizationFlagDefaults) == errAuthorizationSuccess) { // 493 is the decimal representation of the octal value 755 resultSelf = [fileManager changeFileAttributes:[NSDictionary dictionaryWithObjectsAndKeys: @"root", NSFileOwnerAccountName, @"493", NSFilePosixPermissions] atPath:[self pathToSelf]]; #ifndef DEBUGGING //Do not set ownership of the resources directory since this will break XCode resultBundleResources = [fileManager changeFileAttributes:[NSDictionary dictionaryWithObjectsAndKeys: @"root", NSFileOwnerAccountName, @"493", NSFilePosixPermissions] atPath:pathToBundleResources]; #endif //DEBUGGING } else { NSLog(@"ERROR: Unable to authenticate as administrator."); } } else { NSLog(@"ERROR: Unable to determine path to setuid tool."); } if (resultSelf && resultBundleResources) { NSLog(@"Self repair succeeded."); } else if (resultSelf) { NSLog(@"WARNING: Unable to secure Resources folder."); } else { NSLog(@"ERROR: Self repair failed. Please ensure that you are running Pallet from a volume that you can modify."); } return resultSelf; } - (Boolean)relaunchToRepairSelf { if ([self pathToSelf] != NULL) { int status; int result = EXIT_FAILURE; FILE *commPipe = NULL; char *arguments[] = { "--self-repair", NULL }; NSLog(@"Running self-repair..."); if (AuthorizationExecuteWithPrivileges(*_authorization, [[self pathToSelf] UTF8String], kAuthorizationFlagDefaults, arguments, &commPipe)) { /* Read from stdin and write to commPipe. */ fwrite(&_externalAuthorization, 1, sizeof(_externalAuthorization),commPipe); /* Flush any remaining output. */ fflush(commPipe); /* Close the communication pipe to let the child know we are done. */ fclose(commPipe); /* Wait for the child of AuthorizationExecuteWithPrivileges to exit. */ if (wait(&status) != -1 && WIFEXITED(status)) { result = WEXITSTATUS(status); } } return result; } return FALSE; } - (Boolean)getAuthorization { NSLog(@"%@", @"ga: starting"); if ((read(0, &_externalAuthorization, sizeof(_externalAuthorization)) == sizeof(_externalAuthorization)) && (AuthorizationCreateFromExternalForm(_externalAuthorization, _authorization) == errAuthorizationSuccess)) { NSLog(@"%@", @"ga: got it"); return TRUE; } NSLog(@"%@", @"ga: no go"); return FALSE; } - (Boolean)isAuthorized { AuthorizationItem right = { "org.macports.pallet.helper", 0, NULL, 0 }; AuthorizationRights rights = { 1, &right }; AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagExtendRights; bool result = getuid() == geteuid(); if(!result) { result = AuthorizationCopyRights(*_authorization, &rights, kAuthorizationEmptyEnvironment, flags, NULL) == errAuthorizationSuccess; } return result; } - (NSArray *)arguments { return [[NSProcessInfo processInfo] arguments]; } - (Boolean)hasArgument:(NSString *)argument { return [[self arguments] containsObject:argument]; } @end int main(int argc, char * const *argv) { MPPalletHelper *helper; helper = [[MPPalletHelper alloc] init]; int result = 1; if ([helper getAuthorization]) { NSLog(@"%@", @"authorized"); if ([[helper arguments] count] == 2 && [helper hasArgument:@"--self-repair"]) { NSLog(@"%@", @"repairing"); result = [helper repairSelf]; } else if (geteuid() != 0) { NSLog(@"%@", @"relaunching to repair"); result = [helper relaunchToRepairSelf]; } else { if (![helper isAuthorized]) { seteuid(geteuid()); } NSLog(@"%@", @"helping"); result = [helper exec:[[helper arguments] objectAtIndex:1] withTarget:[[helper arguments] objectAtIndex:2]]; } NSLog(@"%@", @"done"); exit(result); } NSLog(@"%@", @"Failed to read authorization from stdin\n"); exit(result); }