1

I would like to know how to write Objective-C or C code to unload (stop) a LaunchDaemon. The LaunchDaemon that I want to unload is running as root user.

My question is basically the same as this one: How to Load LaunchDaemon plist from my Mac Application. The only difference is that he/she is trying to load, but I want to unload.

Community
  • 1
  • 1
ytw
  • 1,335
  • 2
  • 20
  • 42
  • C code: `setuid(0); system("launchctl unload /Path/to/daemon.plist");` –  Apr 09 '13 at 21:20
  • Thanks, H2CO3. But that doesn't seem to work. – ytw Apr 09 '13 at 21:27
  • Are you sure your program has root privileges? –  Apr 09 '13 at 21:29
  • It has admin privilege. My program can delete a .plist file in /Library/LaunchDaemons. Before I delete it, I want to unload it first. – ytw Apr 09 '13 at 21:31
  • Did you try the AuthorizationExecuteWithPrivileges as in code from the link? The fact that application has privileges doesn't mean that it will exec launchctl as root. You should do it explicitly. – cody Apr 10 '13 at 06:55
  • @cody `AuthorizationExecuteWithPrivileges` has been deprecated for a while, as discussed in this question: http://stackoverflow.com/questions/6841937/authorizationexecutewithprivileges-is-deprecated –  May 31 '13 at 06:55
  • @GrahamLee, I know, thanks. That wasn't a suggestion to use this function, that was a question. – cody May 31 '13 at 07:07
  • @H2CO3 you can only `setuid(0)` in a process that already had UID 0. –  May 31 '13 at 13:10

2 Answers2

2

You can use applescript

do shell script "launchctl unload /Library/LaunchDaemons/com.yourcompany.app.plist" with administrator privileges
Parag Bafna
  • 22,812
  • 8
  • 71
  • 144
2

From C you can use the SMJobRemove function. If the job is in the system launchd context (i.e. it's in /Library/LaunchDaemons and is loaded—if not launched—at system startup) then you'll need to use Authorization Services to acquire the kSMRightModifySystemDaemons right, and pass the authorization reference to this function.

    AuthorizationItem authItem = { .name = kSMRightModifySystemDaemons,
        .valueLength = 0,
        .value = NULL,
        .flags = kAuthorizationFlagDefaults };
    AuthorizationRights authRights  = { .count = 1,
        .items = &authItem };

    AuthorizationRef authorization = NULL;
    OSStatus authResult = AuthorizationCreate(&authRights,
                                          kAuthorizationEmptyEnvironment,
                                          kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights,
                                          &authorization);
    if (authResult != errAuthorizationSuccess) {
        NSLog(@"couldn't create AuthorizationRef: error %i", authResult);
    } else {
        CFErrorRef error = NULL;
        BOOL removeResult = SMJobRemove(kSMDomainSystemLaunchd, jobLabel, authorization, waitOrNot, &error);
        AuthorizationFree(authorization, kAuthorizationFlagDefaults);
        // handle either success or failure
    }

The waitOrNot flag should be set to YES if you want to block until the job has been unloaded—this could potentially take a long time.

  • Thanks for the suggestion. I've already used Parag Bafna's answer long ago, but forgot to mark it as the answer. – ytw May 31 '13 at 17:12