Home | History | Annotate | Download | only in mac
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/mac/launchd.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/mac/scoped_launch_data.h"
      9 
     10 namespace base {
     11 namespace mac {
     12 
     13 // MessageForJob sends a single message to launchd with a simple dictionary
     14 // mapping |operation| to |job_label|, and returns the result of calling
     15 // launch_msg to send that message. On failure, returns NULL. The caller
     16 // assumes ownership of the returned launch_data_t object.
     17 launch_data_t MessageForJob(const std::string& job_label,
     18                             const char* operation) {
     19   // launch_data_alloc returns something that needs to be freed.
     20   ScopedLaunchData message(launch_data_alloc(LAUNCH_DATA_DICTIONARY));
     21   if (!message) {
     22     LOG(ERROR) << "launch_data_alloc";
     23     return NULL;
     24   }
     25 
     26   // launch_data_new_string returns something that needs to be freed, but
     27   // the dictionary will assume ownership when launch_data_dict_insert is
     28   // called, so put it in a scoper and .release() it when given to the
     29   // dictionary.
     30   ScopedLaunchData job_label_launchd(launch_data_new_string(job_label.c_str()));
     31   if (!job_label_launchd) {
     32     LOG(ERROR) << "launch_data_new_string";
     33     return NULL;
     34   }
     35 
     36   if (!launch_data_dict_insert(message,
     37                                job_label_launchd.release(),
     38                                operation)) {
     39     return NULL;
     40   }
     41 
     42   return launch_msg(message);
     43 }
     44 
     45 pid_t PIDForJob(const std::string& job_label) {
     46   ScopedLaunchData response(MessageForJob(job_label, LAUNCH_KEY_GETJOB));
     47   if (!response) {
     48     return -1;
     49   }
     50 
     51   launch_data_type_t response_type = launch_data_get_type(response);
     52   if (response_type != LAUNCH_DATA_DICTIONARY) {
     53     if (response_type == LAUNCH_DATA_ERRNO) {
     54       LOG(ERROR) << "PIDForJob: error " << launch_data_get_errno(response);
     55     } else {
     56       LOG(ERROR) << "PIDForJob: expected dictionary, got " << response_type;
     57     }
     58     return -1;
     59   }
     60 
     61   launch_data_t pid_data = launch_data_dict_lookup(response,
     62                                                    LAUNCH_JOBKEY_PID);
     63   if (!pid_data)
     64     return 0;
     65 
     66   if (launch_data_get_type(pid_data) != LAUNCH_DATA_INTEGER) {
     67     LOG(ERROR) << "PIDForJob: expected integer";
     68     return -1;
     69   }
     70 
     71   return launch_data_get_integer(pid_data);
     72 }
     73 
     74 }  // namespace mac
     75 }  // namespace base
     76