15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/launchd.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_launch_data.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace mac {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageForJob sends a single message to launchd with a simple dictionary
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mapping |operation| to |job_label|, and returns the result of calling
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// launch_msg to send that message. On failure, returns NULL. The caller
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// assumes ownership of the returned launch_data_t object.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)launch_data_t MessageForJob(const std::string& job_label,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const char* operation) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // launch_data_alloc returns something that needs to be freed.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedLaunchData message(launch_data_alloc(LAUNCH_DATA_DICTIONARY));
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!message) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "launch_data_alloc";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // launch_data_new_string returns something that needs to be freed, but
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the dictionary will assume ownership when launch_data_dict_insert is
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called, so put it in a scoper and .release() it when given to the
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dictionary.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedLaunchData job_label_launchd(launch_data_new_string(job_label.c_str()));
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!job_label_launchd) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "launch_data_new_string";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!launch_data_dict_insert(message,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               job_label_launchd.release(),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               operation)) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return launch_msg(message);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pid_t PIDForJob(const std::string& job_label) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedLaunchData response(MessageForJob(job_label, LAUNCH_KEY_GETJOB));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  launch_data_type_t response_type = launch_data_get_type(response);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_type != LAUNCH_DATA_DICTIONARY) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (response_type == LAUNCH_DATA_ERRNO) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "PIDForJob: error " << launch_data_get_errno(response);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "PIDForJob: expected dictionary, got " << response_type;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  launch_data_t pid_data = launch_data_dict_lookup(response,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   LAUNCH_JOBKEY_PID);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pid_data)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (launch_data_get_type(pid_data) != LAUNCH_DATA_INTEGER) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "PIDForJob: expected integer";
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return launch_data_get_integer(pid_data);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace mac
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
76