Looking for opinions on authorization frameworks for Pallet

Ian Wadham iandw.au at gmail.com
Wed Aug 5 17:25:42 PDT 2015

On 06/08/2015, at 4:14 AM, Kyle Sammons wrote:

> Hey everyone,
> Currently I'm at a fork in the road for the Revitalizing Pallet GSoC
> project, and was hoping to crowd source some ideas about how to deal
> with the Apple authorization framework used to get super user privileges
> to allow 'port' to execute correctly under the hood. This task is the
> last major one on my GSoC queue. There are three possible roads to go
> down here; I don't know which one is the "best" or "correct" one, hence
> the crowd sourcing here.

Here is another possibility, which I used in Fossick…  Note that I went the
command-line route and used "tail -f" to receive output asynchronously.
You may not need that if you have gone the other route.  The guts of the
authorisation is to use AppleScript.  Hope this helps.

 * This method uses AppleScript to run a privileged Unix script asynchronously
 * in the background, with output to a file (e.g. a script containing MacPorts'
 * "port install <software item>" command).  The NSTask object defined above
 * uses "tail -f" to collect the output as it occurs.  The return string is nil
 * if the script started OK or contains an error text if it failed.  AppleScript
 * is run "with administrator privileges", which means that it pops up the usual
 * Apple request for an admin password when installing non-Apple software.
- (NSString *) runPrivilegedScript: (NSString *) filePath
                            output: (NSString *) outputFilePath;

- (NSString *) runPrivilegedScript: (NSString *) filePath
                      output: (NSString *) outputFilePath
    NSDictionary * error;
    NSString * script = [NSString stringWithFormat: @"do shell script " \
                         "\"'%@' >'%@' 2>&1 &\" " \
                         "with administrator privileges " \
                         "without altering line endings",
                         filePath, outputFilePath];
    NSLog(@"SCRIPT: %@", script);
    NSAppleScript * appleScript = [[NSAppleScript new] initWithSource:script];
    if ([appleScript executeAndReturnError:&error]) {
        NSLog(@"AppleScript running! '%@' >'%@' 2>&1 &", filePath, outputFilePath);

        // Start the output-watcher.
        self.task = [[NSTask alloc] init];
        [self.task setLaunchPath:@"/usr/bin/tail"];
        [self.task setArguments:[NSArray arrayWithObjects:
                            @"-f", outputFilePath, nil]];
        self.tailOfOutput = [NSPipe pipe];
        self.errorOutput  = [NSPipe pipe];
        [self.task setStandardOutput: tailOfOutput];
        [self.task setStandardError:  errorOutput];
        [self.task setStandardInput: [NSPipe pipe]]; // No standard input.
        [self.task launch];
        [[self.tailOfOutput fileHandleForReading] readInBackgroundAndNotify];
        [[NSNotificationCenter defaultCenter]
                  addObserver: self
                     selector: @selector (receiveOutput:)
                         name: NSFileHandleReadCompletionNotification
                       object: nil];                              
        return nil;
    else {
        NSLog(@"Failed to run AppleScript!\n%@", error);
        return [error description];
    // TODO:  "User cancelled." is a possible error reason (i.e. hit Cancel
    //        instead of entering a password).  OS X seems to allow unlimited
    //        failed attempts to enter the password.

> 0. Do nothing; leave the current code in place, but continue to ignore
> it; require the user to run it with superuser privileges;

Cheers, Ian W.

More information about the macports-dev mailing list