1 /* vi:set ts=8 sts=4 sw=4 ft=objc:
3 * VIM - Vi IMproved by Bram Moolenaar
4 * MacVim GUI port by Bjorn Winckler
6 * Do ":help uganda" in Vim to read copying and usage conditions.
7 * Do ":help credits" in Vim to see a list of people who contributed.
8 * See README.txt for an overview of the Vim source code.
13 * Runs a set of shell commands which may require authorization. Displays a
14 * gui dialog to ask the user for authorized access.
17 #import "AuthorizedShellCommand.h"
18 #import <Security/AuthorizationTags.h>
21 @implementation AuthorizedShellCommand
23 - (AuthorizedShellCommand *)initWithCommands:(NSArray *)theCommands
28 commands = [theCommands retain];
42 const char** arguments = NULL;
43 AuthorizationFlags flags = kAuthorizationFlagDefaults;
45 err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
46 flags, &authorizationRef);
47 if (err != errAuthorizationSuccess)
50 if ((err = [self askUserForPermission]) != errAuthorizationSuccess) {
54 NSEnumerator* myIterator = [commands objectEnumerator];
55 NSDictionary* currCommand;
57 while ((currCommand = [myIterator nextObject])) {
58 /* do something useful with currCommand */
62 const char* toolPath = [[currCommand objectForKey:MMCommand] UTF8String];
63 NSArray* argumentStrings = [currCommand objectForKey:MMArguments];
64 arguments = (const char**)malloc(
65 ([argumentStrings count] + 1) * sizeof(char*));
67 for (i = 0; i < [argumentStrings count]; ++i) {
68 arguments[i] = [[argumentStrings objectAtIndex:i] UTF8String];
72 err = AuthorizationExecuteWithPrivileges (authorizationRef, toolPath,
73 kAuthorizationFlagDefaults, (char*const*)arguments, &ioPipe);
74 if (err != errAuthorizationSuccess)
78 // We use the pipe to signal us when the command has completed
81 p = fgets(junk, sizeof(junk), ioPipe);
86 int bytesRead = read (fileno (ioPipe),
88 if (bytesRead < 1) break;
89 write (fileno (stdout), junk, bytesRead);
93 if (arguments != NULL) {
103 AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
104 authorizationRef = 0;
106 if (arguments != NULL)
112 - (OSStatus)askUserForPermission
116 assert(authorizationRef != 0);
118 // The documentation for AuthorizationItem says that `value` should be
119 // the path to the full posix path for kAuthorizationRightExecute. But
120 // the installer sample "Calling a Privileged Installer" sets it to NULL.
121 // Gotta love Apple's documentation.
123 // If you don't set `value` correctly, you'll get an
124 // `errAuthorizationToolEnvironmentError` when you try to execute the
126 AuthorizationItem* authItems =
127 malloc([commands count] * sizeof(AuthorizationItem));
128 for (i = 0; i < [commands count]; ++i) {
129 authItems[i].name = kAuthorizationRightExecute;
130 authItems[i].value = (void*)
131 [[[commands objectAtIndex:i] objectForKey:MMCommand] UTF8String];
132 authItems[i].valueLength = strlen(authItems[i].value);
133 authItems[i].flags = 0;
136 AuthorizationRights rights = {
137 [commands count], authItems
140 OSStatus err = AuthorizationCopyRights(authorizationRef, &rights, NULL,
141 kAuthorizationFlagInteractionAllowed |
142 kAuthorizationFlagPreAuthorize |
143 kAuthorizationFlagExtendRights
153 NSString *MMCommand = @"MMCommand";
154 NSString *MMArguments = @"MMArguments";