Add Vimball (vba) as supported filetype
[MacVim.git] / src / MacVim / AuthorizedShellCommand.m
blob5148efbf46fc011ab1cfd29b935ab5b266f0f77d
1 /* vi:set ts=8 sts=4 sw=4 ft=objc:
2  *
3  * VIM - Vi IMproved            by Bram Moolenaar
4  *                              MacVim GUI port by Bjorn Winckler
5  *
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.
9  */
11  * AuthorizedCommand
12  *
13  * Runs a set of shell commands which may require authorization. Displays a
14  * gui dialog to ask the user for authorized access.
15  */
17 #import "AuthorizedShellCommand.h"
18 #import <Security/AuthorizationTags.h>
21 @implementation AuthorizedShellCommand
23 - (AuthorizedShellCommand *)initWithCommands:(NSArray *)theCommands
25     if (![super init])
26         return nil;
28     commands = [theCommands retain];
29     return self;
32 - (void)dealloc
34     [super dealloc];
35     [commands release]; 
38 - (OSStatus)run
40     OSStatus err;
41     int i;
42     const char** arguments = NULL;
43     AuthorizationFlags flags = kAuthorizationFlagDefaults;
45     err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
46             flags, &authorizationRef);
47     if (err != errAuthorizationSuccess)
48         return err;
50     if ((err = [self askUserForPermission]) != errAuthorizationSuccess) {
51         goto cleanup;
52     }
54     NSEnumerator* myIterator = [commands objectEnumerator];
55     NSDictionary* currCommand;
57     while (currCommand = [myIterator nextObject])
58     {
59         /* do something useful with currCommand */
60         FILE *ioPipe = NULL;
61         char junk[256];
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];
70         }
71         arguments[i] = NULL;
73         err = AuthorizationExecuteWithPrivileges (authorizationRef, toolPath,
74                 kAuthorizationFlagDefaults, (char*const*)arguments, &ioPipe);
75         if (err != errAuthorizationSuccess)
76             goto cleanup;
78 #if 0
79         // We use the pipe to signal us when the command has completed
80         char *p;
81         do {
82             p = fgets(junk, sizeof(junk), ioPipe);
83         } while (p);
84 #else
85         for(;;)
86         {
87             int bytesRead = read (fileno (ioPipe),
88                     junk, sizeof (junk));
89             if (bytesRead < 1) break;
90             write (fileno (stdout), junk, bytesRead);
91         }
92 #endif
94         if (arguments != NULL) {
95             free(arguments);
96             arguments = NULL;
97         }
98         fclose(ioPipe);
99     }
103 cleanup:
104     AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
105     authorizationRef = 0;
107     if (arguments != NULL)
108         free(arguments);
110     return err;
113 - (OSStatus)askUserForPermission
115     int i;
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.
123     //
124     // If you don't set `value` correctly, you'll get an
125     // `errAuthorizationToolEnvironmentError` when you try to execute the
126     // command.
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;
135     }
137     AuthorizationRights rights = {
138         [commands count], authItems
139     };
140     
141     OSStatus err = AuthorizationCopyRights(authorizationRef, &rights, NULL,
142             kAuthorizationFlagInteractionAllowed |
143             kAuthorizationFlagPreAuthorize |
144             kAuthorizationFlagExtendRights
145             , NULL);
147     free(authItems);
149     return err;
152 @end
154 NSString *MMCommand   = @"MMCommand";
155 NSString *MMArguments = @"MMArguments";