Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

requesting `root` access from user to update `/etc/paths.d`

my app installer uses the standard open DMG, drag to 'Applications' for installation, but I want to update $PATH so my app can be used from the command line.

I think the right way to do this is to call a script on the first time my application runs that creates a file myapp in /etc/paths.d with the text /Applications/myapp/bin followed by a newline(ascii 13):

rm /etc/paths.d/myapp
echo "/Applications/myapp/bin" > /etc/paths.d/myapp

currently I'm getting errors;

rm: /etc/paths.d/myapp: No such file or directory
./myapp.sh: line 2: /etc/paths.d/myapp: Permission denied

I need to trigger a request for the user to type the admin password but I'm not sure how to do that in a way this clearly inform the user what changes I am making to their system and why. (I can add it to the manual but who reads that)

Any suggestions?

PS I need to do the same on linux(hopefully similar) and Windows, but if I can get MacOS sorted hopefully I'll know where to start.

like image 834
Stephen Avatar asked Oct 23 '20 09:10

Stephen


1 Answers

AuthorizationExecuteWithPrivileges is deprecated for a long time, but still present and working in macOS 11 (Big Sur / 10.16). STPrivilegedTask demonstrates how to call the function in a "safe" manner - that is, to properly handle the case where the function might be removed in a future version of the OS.

Usage is something like this (error checking etc is omitted for brevity). This will create a symlink of your executable in /usr/local/bin with the name "my-app":

    AuthorizationRef authorizationRef;
    OSStatus err;

    const char* tool = "/bin/ln";
    char *args[] = {
        "-sf", 
        [[[NSBundle mainBundle] executablePath] UTF8String],
        "/usr/local/bin/my-app", 
        nil
    };

    AuthorizationCreate(nil, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);

    err = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, nil);

    switch (err)
    {
        case errAuthorizationCanceled:
            // user cancelled prompt
            break;
        case errAuthorizationSuccess:
            // success
            break;
        default:
            // an error occurred
            break;
    }

    AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);

How you use that, is up to you - you could place it behind a menu item ("Install Command Line Tools") like cmake does. If you want to install this at launch time, I'd suggest prompting the user first (and allowing them the option to "don't ask me again").

like image 130
TheNextman Avatar answered Nov 03 '22 14:11

TheNextman