/app/utils/CLI.m

http://github.com/tgunr/passengerpane · Objective C · 201 lines · 170 code · 30 blank · 1 comment · 30 complexity · 92213dc68d2dd1d5a55f2916de6697e5 MD5 · raw file

  1. #import "CLI.h"
  2. @implementation CLI
  3. static id sharedCLI = nil;
  4. + (id)sharedInstance{
  5. if (sharedCLI == nil) {
  6. sharedCLI = [[CLI alloc] init];
  7. }
  8. return sharedCLI;
  9. }
  10. @synthesize appDelegate, pathToCLI;
  11. - (id)init {
  12. if ((self = [super init])) {
  13. authorizationRef = NULL;
  14. }
  15. return self;
  16. }
  17. - (NSMutableArray *)listApplications {
  18. NSArray *result;
  19. Application *application;
  20. NSDictionary *attributes;
  21. NSMutableArray *applications;
  22. NSLog(@"Retrieving a list of configured applications");
  23. result = [self execute:[NSArray arrayWithObjects:@"list", @"-m", nil] elevated:NO];
  24. applications = [NSMutableArray arrayWithCapacity:[result count]];
  25. if ([result count] > 0) {
  26. for (attributes in result) {
  27. application = [[Application alloc] initWithAttributes:attributes];
  28. [application setDelegate:appDelegate];
  29. [applications addObject:application];
  30. }
  31. }
  32. return applications;
  33. }
  34. - (void) add:(Application *)application {
  35. NSMutableArray *arguments = [NSMutableArray arrayWithObjects:@"add", application.path, nil];
  36. [arguments addObjectsFromArray:[application toArgumentArray]];
  37. NSLog(@"Adding application with hostname %@ using %@", application.host, arguments);
  38. [self execute:arguments elevated:YES];
  39. [application didApplyChanges];
  40. }
  41. - (void) update:(Application *)application {
  42. NSDictionary *beforeChanges = [application beforeChanges];
  43. NSString *currentHost = [beforeChanges valueForKey:@"host"];
  44. NSMutableArray *arguments = [NSMutableArray arrayWithObjects:@"update", currentHost, nil];
  45. [arguments addObjectsFromArray:[application toArgumentArray]];
  46. NSLog(@"Updating application with hostname %@ using %@", application.host, arguments);
  47. [self execute:arguments elevated:YES];
  48. [application didApplyChanges];
  49. }
  50. - (void) delete:(Application *)application {
  51. NSLog(@"Deleting application with hostname: %@", application.host);
  52. [self execute:[NSArray arrayWithObjects:@"delete", application.host, nil] elevated:YES];
  53. }
  54. - (void) restart:(Application *)application {
  55. NSLog(@"Restarting application with hostname: %@", application.host);
  56. [self execute:[NSArray arrayWithObjects:@"restart", application.host, nil] elevated:NO];
  57. }
  58. - (void) restart {
  59. NSLog(@"Restarting Apache");
  60. [self execute:[NSArray arrayWithObject:@"restart"] elevated:YES];
  61. }
  62. - (BOOL) isPassengerModuleInstalled {
  63. NSLog(@"Checking if the Passenger module is installed");
  64. NSDictionary *info = [self execute:[NSArray arrayWithObjects:@"info", @"-m", nil] elevated:NO];
  65. if (info) {
  66. NSNumber *isInstalled = [info objectForKey:@"passenger_module_installed"];
  67. return [isInstalled boolValue];
  68. } else {
  69. NSLog(@"Failed to read info, assuming Passenger module isn't installed.");
  70. return NO;
  71. }
  72. }
  73. // Inspired by: http://svn.kismac-ng.org/kmng/trunk/Subprojects/BIGeneric/BLAuthentication.m
  74. - (id) execute:(NSArray *)arguments elevated:(BOOL)elevated {
  75. OSStatus status;
  76. char **argumentsAsCArray = NULL;
  77. unsigned int index;
  78. FILE *communicationPipe;
  79. NSFileHandle *file;
  80. NSData *data;
  81. NSError *error = nil;
  82. id result = nil;
  83. if (elevated) {
  84. if ([self isAuthorized]) {
  85. if ([arguments count] > 0) {
  86. index = 0;
  87. argumentsAsCArray = NSAllocateCollectable(sizeof(char*)*([arguments count]+1), 0);
  88. while(index < [arguments count]) {
  89. argumentsAsCArray[index++] = (char*)[[arguments objectAtIndex:index] UTF8String];
  90. }
  91. argumentsAsCArray[index] = NULL;
  92. }
  93. status = AuthorizationExecuteWithPrivileges(authorizationRef, [pathToCLI UTF8String],
  94. kAuthorizationFlagDefaults, argumentsAsCArray,
  95. &communicationPipe);
  96. if (status == PPANE_SUCCESS) {
  97. if (communicationPipe) {
  98. file = [[NSFileHandle alloc] initWithFileDescriptor:fileno(communicationPipe)];
  99. data = [file readDataToEndOfFile];
  100. [file closeFile];
  101. if ([data length] > 0) {
  102. result = [[CJSONDeserializer deserializer] deserialize:data error:&error];
  103. if (error) {
  104. NSLog(@"ppane returned invalid JSON: %@", [error description]);
  105. } else {
  106. return result;
  107. }
  108. } else {
  109. NSLog(@"ppane didn't return any information");
  110. }
  111. }
  112. } else {
  113. NSLog(@"AuthorizationExecuteWithPrivileges failed to execute ppane (%d)", status);
  114. }
  115. } else {
  116. NSLog(@"Ignoring a privileged command because the pane isn't authorized");
  117. }
  118. return [NSDictionary dictionary];
  119. } else {
  120. return [self execute:arguments];
  121. }
  122. }
  123. - (id)execute:(NSArray *)arguments {
  124. NSData *data;
  125. NSError *error = nil;
  126. id result = nil;
  127. NSPipe *stdout = [NSPipe pipe];
  128. NSTask *ppane;
  129. ppane = [[NSTask alloc] init];
  130. [ppane setLaunchPath:pathToCLI];
  131. [ppane setArguments:arguments];
  132. [ppane setStandardOutput:stdout];
  133. [ppane launch];
  134. [ppane waitUntilExit];
  135. if ([ppane terminationStatus] == PPANE_SUCCESS) {
  136. data = [[stdout fileHandleForReading] readDataToEndOfFile];
  137. if ([data length] > 0) {
  138. result = [[CJSONDeserializer deserializer] deserialize:data error:&error];
  139. if (error) {
  140. NSLog(@"ppane returned invalid JSON: %@", [error description]);
  141. } else {
  142. return result;
  143. }
  144. } else {
  145. NSLog(@"ppane didn't return any data");
  146. }
  147. } else {
  148. NSLog(@"NSTask failed to execute the command");
  149. }
  150. return [NSDictionary dictionary];
  151. }
  152. - (AuthorizationRef) authorizationRef {
  153. return authorizationRef;
  154. }
  155. - (void) setAuthorizationRef:(AuthorizationRef)ref {
  156. authorizationRef = ref;
  157. }
  158. - (void) deauthorize {
  159. authorizationRef = NULL;
  160. }
  161. - (BOOL) isAuthorized {
  162. if (authorizationRef == NULL) {
  163. return NO;
  164. } else {
  165. return YES;
  166. }
  167. }
  168. - (void) fakeAuthorize {
  169. AuthorizationCreate(nil, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
  170. }
  171. @end