| 1 | /* Copyright (c) 2008-2012 Apple Inc. |
| 2 | * |
| 3 | * Permission is hereby granted, free of charge, to any person |
| 4 | * obtaining a copy of this software and associated documentation files |
| 5 | * (the "Software"), to deal in the Software without restriction, |
| 6 | * including without limitation the rights to use, copy, modify, merge, |
| 7 | * publish, distribute, sublicense, and/or sell copies of the Software, |
| 8 | * and to permit persons to whom the Software is furnished to do so, |
| 9 | * subject to the following conditions: |
| 10 | * |
| 11 | * The above copyright notice and this permission notice shall be |
| 12 | * included in all copies or substantial portions of the Software. |
| 13 | * |
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 15 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 16 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 17 | * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT |
| 18 | * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 19 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 21 | * DEALINGS IN THE SOFTWARE. |
| 22 | * |
| 23 | * Except as contained in this notice, the name(s) of the above |
| 24 | * copyright holders shall not be used in advertising or otherwise to |
| 25 | * promote the sale, use or other dealings in this Software without |
| 26 | * prior written authorization. |
| 27 | */ |
| 28 | |
| 29 | #ifdef HAVE_DIX_CONFIG_H |
| 30 | #include <dix-config.h> |
| 31 | #endif |
| 32 | |
| 33 | #include <launch.h> |
| 34 | #include <asl.h> |
| 35 | #include <errno.h> |
| 36 | |
| 37 | #include "launchd_fd.h" |
| 38 | |
| 39 | extern aslclient aslc; |
| 40 | |
| 41 | int |
| 42 | launchd_display_fd(void) |
| 43 | { |
| 44 | launch_data_t sockets_dict, checkin_request, checkin_response; |
| 45 | launch_data_t listening_fd_array, listening_fd; |
| 46 | |
| 47 | /* Get launchd fd */ |
| 48 | if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == |
| 49 | NULL) { |
| 50 | asl_log( |
| 51 | aslc, NULL, ASL_LEVEL_ERR, |
| 52 | "launch_data_new_string(\"" LAUNCH_KEY_CHECKIN |
| 53 | "\") Unable to create string.\n"); |
| 54 | return ERROR_FD; |
| 55 | } |
| 56 | |
| 57 | if ((checkin_response = launch_msg(checkin_request)) == NULL) { |
| 58 | asl_log(aslc, NULL, ASL_LEVEL_WARNING, |
| 59 | "launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %s\n", |
| 60 | strerror( |
| 61 | errno)); |
| 62 | return ERROR_FD; |
| 63 | } |
| 64 | |
| 65 | if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) { |
| 66 | // ignore EACCES, which is common if we weren't started by launchd |
| 67 | if (launch_data_get_errno(checkin_response) != EACCES) |
| 68 | asl_log(aslc, NULL, ASL_LEVEL_ERR, |
| 69 | "launchd check-in failed: %s\n", |
| 70 | strerror(launch_data_get_errno( |
| 71 | checkin_response))); |
| 72 | return ERROR_FD; |
| 73 | } |
| 74 | |
| 75 | sockets_dict = launch_data_dict_lookup(checkin_response, |
| 76 | LAUNCH_JOBKEY_SOCKETS); |
| 77 | if (NULL == sockets_dict) { |
| 78 | asl_log(aslc, NULL, ASL_LEVEL_ERR, |
| 79 | "launchd check-in: no sockets found to answer requests on!\n"); |
| 80 | return ERROR_FD; |
| 81 | } |
| 82 | |
| 83 | if (launch_data_dict_get_count(sockets_dict) > 1) { |
| 84 | asl_log(aslc, NULL, ASL_LEVEL_ERR, |
| 85 | "launchd check-in: some sockets will be ignored!\n"); |
| 86 | return ERROR_FD; |
| 87 | } |
| 88 | |
| 89 | listening_fd_array = launch_data_dict_lookup(sockets_dict, |
| 90 | BUNDLE_ID_PREFIX ":0"); |
| 91 | if (NULL == listening_fd_array) { |
| 92 | listening_fd_array = launch_data_dict_lookup(sockets_dict, ":0"); |
| 93 | if (NULL == listening_fd_array) { |
| 94 | asl_log( |
| 95 | aslc, NULL, ASL_LEVEL_ERR, |
| 96 | "launchd check-in: No known sockets found to answer requests on! \"%s:0\" and \":0\" failed.\n", |
| 97 | BUNDLE_ID_PREFIX); |
| 98 | return ERROR_FD; |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | if (launch_data_array_get_count(listening_fd_array) != 1) { |
| 103 | asl_log(aslc, NULL, ASL_LEVEL_ERR, |
| 104 | "launchd check-in: Expected 1 socket from launchd, got %u)\n", |
| 105 | (unsigned)launch_data_array_get_count( |
| 106 | listening_fd_array)); |
| 107 | return ERROR_FD; |
| 108 | } |
| 109 | |
| 110 | listening_fd = launch_data_array_get_index(listening_fd_array, 0); |
| 111 | return launch_data_get_fd(listening_fd); |
| 112 | } |