Running sudo command from swift

Hey everyone,


I'm trying to execute:

sudo defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "Your login window message text goes here"

in my macOS program. Basically, I wan't to be able to change the Login Window text.


I've tried:

let process = Process()
process.launchPath = "/usr/bin/env"
process.arguments = ["sudo", "defaults", "write", "/Library/Preferences/com.apple.loginwindow", "LoginwindowText", "\"Your login window message text goes here\""]
      
process.launch()
process.waitUntilExit()

But get an "Operation Not Permitted" error


Does anyone know how I can do this? Or more specifically does anyone know of a way to alter the defaults in com.apple.loginwindow.


I'm fairly new to this, so any advice is appreciated 🙂 I am using Swift 4, with Xcode 9.1


Thanks!

The immediate cause of your problem is that

sudo
reads its password from
stdin
and, when you run it with
Process
, it inherits
stdin
from your app, which is not wired up to anything useful. You could potentially get around this by ‘puppetstringing’
sudo
(using
expect
) but you still need to ask the user for their password, which isn’t something that normal app-level code should be doing.

How you proceed from here really depends on what sort of app your building:

  • If you’re targeting the Mac App Store then this isn’t going to work. Mac App Store apps are not allowed to escalate privileges and this task requires that.

  • If you’re building simple project for your own use, the easy option would to be use

    AuthorizationExecuteWithPrivileges
    . That routine has been deprecated, so I wouldn’t want to base a product on it, but it still works and it’s really easy.
  • If you’re building a product that you plan to ship far and wide, you’ll need to look at alternatives to

    AuthorizationExecuteWithPrivileges
    , which are substantially more complex.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello BobJobRob,

Another option here is AppleScript. Via AppleScript, you can all shell scripts and have them run as if you had used sudo with:


do shell script "something" with administrator privileges


(see developer.apple.com/library/content/technotes/tn2065/_index.html)


The easiest way to get to that via Swift is to run a command as you you are doing above, but without the sudo. Instead of performing your operation, run "osascript -e" and give it your AppleScript command. So essentially you are running a command line tool, to call AppleScript, to call another command line tool.


That's the easy part. I really wouldn't recommend stuffing values into some other app's defaults. People like to recommend that kind of stuff on the internet. But it may have been posted a decade ago. There is no way to know if it will work today or in the future. Apple has documentation on how to do this via the UI (see support.apple.com/HT203580 and support.apple.com/HT202277 for a similar feature). But that doesn't change anything. Apple can update the procedure and documentation at any time. It is always risky messing around with someone else's apps, especially Apple's. Apple has a literal army of programmers. They can and do change the OS faster than you can keep up. You would have to test this feature in each beta before it gets released to make sure it will work. You will need some way to handle the inevitable day that it stops working. You can file a bug and maybe in a build or two it will get fixed. But what are your plans for the meantime?

Running sudo command from swift
 
 
Q