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])
59 /* do something useful with currCommand */
63 const char* toolPath = [[currCommand objectForKey:MMCommand] UTF8String];
64 NSArray* argumentStrings = [currCommand objectForKey:MMArguments];
65 arguments = (const char**)malloc(
66 ([argumentStrings count] + 1) * sizeof(char*));
68 for (i = 0; i < [argumentStrings count]; ++i) {
69 arguments[i] = [[argumentStrings objectAtIndex:i] UTF8String];
73 err = AuthorizationExecuteWithPrivileges (authorizationRef, toolPath,
74 kAuthorizationFlagDefaults, (char*const*)arguments, &ioPipe);
75 if (err != errAuthorizationSuccess)
79 // We use the pipe to signal us when the command has completed
82 p = fgets(junk, sizeof(junk), ioPipe);
87 int bytesRead = read (fileno (ioPipe),
89 if (bytesRead < 1) break;
90 write (fileno (stdout), junk, bytesRead);
94 if (arguments != NULL) {
104 AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
105 authorizationRef = 0;
107 if (arguments != NULL)
113 - (OSStatus)askUserForPermission
117 assert(authorizationRef != 0);
119 // The documentation for AuthorizationItem says that `value` should be
120 // the path to the full posix path for kAuthorizationRightExecute. But
121 // the installer sample "Calling a Privileged Installer" sets it to NULL.
122 // Gotta love Apple's documentation.
124 // If you don't set `value` correctly, you'll get an
125 // `errAuthorizationToolEnvironmentError` when you try to execute the
127 AuthorizationItem* authItems =
128 malloc([commands count] * sizeof(AuthorizationItem));
129 for (i = 0; i < [commands count]; ++i) {
130 authItems[i].name = kAuthorizationRightExecute;
131 authItems[i].value = (void*)
132 [[[commands objectAtIndex:i] objectForKey:MMCommand] UTF8String];
133 authItems[i].valueLength = strlen(authItems[i].value);
134 authItems[i].flags = 0;
137 AuthorizationRights rights = {
138 [commands count], authItems
141 OSStatus err = AuthorizationCopyRights(authorizationRef, &rights, NULL,
142 kAuthorizationFlagInteractionAllowed |
143 kAuthorizationFlagPreAuthorize |
144 kAuthorizationFlagExtendRights
154 NSString *MMCommand = @"MMCommand";
155 NSString *MMArguments = @"MMArguments";