1706f2543Smrg/* Copyright (c) 2008 Apple Inc.
2706f2543Smrg *
3706f2543Smrg * Permission is hereby granted, free of charge, to any person
4706f2543Smrg * obtaining a copy of this software and associated documentation files
5706f2543Smrg * (the "Software"), to deal in the Software without restriction,
6706f2543Smrg * including without limitation the rights to use, copy, modify, merge,
7706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software,
8706f2543Smrg * and to permit persons to whom the Software is furnished to do so,
9706f2543Smrg * subject to the following conditions:
10706f2543Smrg *
11706f2543Smrg * The above copyright notice and this permission notice shall be
12706f2543Smrg * included in all copies or substantial portions of the Software.
13706f2543Smrg *
14706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17706f2543Smrg * NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
18706f2543Smrg * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20706f2543Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21706f2543Smrg * DEALINGS IN THE SOFTWARE.
22706f2543Smrg *
23706f2543Smrg * Except as contained in this notice, the name(s) of the above
24706f2543Smrg * copyright holders shall not be used in advertising or otherwise to
25706f2543Smrg * promote the sale, use or other dealings in this Software without
26706f2543Smrg * prior written authorization.
27706f2543Smrg */
28706f2543Smrg
29706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
30706f2543Smrg#include <dix-config.h>
31706f2543Smrg#endif
32706f2543Smrg
33706f2543Smrg#include <launch.h>
34706f2543Smrg#include <stdio.h>
35706f2543Smrg#include <errno.h>
36706f2543Smrg
37706f2543Smrg#include "launchd_fd.h"
38706f2543Smrg
39706f2543Smrgint launchd_display_fd(void) {
40706f2543Smrg    launch_data_t sockets_dict, checkin_request, checkin_response;
41706f2543Smrg    launch_data_t listening_fd_array, listening_fd;
42706f2543Smrg
43706f2543Smrg    /* Get launchd fd */
44706f2543Smrg    if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) {
45706f2543Smrg        fprintf(stderr,"launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string.\n");
46706f2543Smrg        return ERROR_FD;
47706f2543Smrg    }
48706f2543Smrg
49706f2543Smrg    if ((checkin_response = launch_msg(checkin_request)) == NULL) {
50706f2543Smrg        fprintf(stderr,"launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %s\n",strerror(errno));
51706f2543Smrg        return ERROR_FD;
52706f2543Smrg    }
53706f2543Smrg
54706f2543Smrg    if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
55706f2543Smrg        // ignore EACCES, which is common if we weren't started by launchd
56706f2543Smrg        if (launch_data_get_errno(checkin_response) != EACCES)
57706f2543Smrg            fprintf(stderr,"launchd check-in failed: %s\n", strerror(launch_data_get_errno(checkin_response)));
58706f2543Smrg        return ERROR_FD;
59706f2543Smrg    }
60706f2543Smrg
61706f2543Smrg    sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS);
62706f2543Smrg    if (NULL == sockets_dict) {
63706f2543Smrg        fprintf(stderr,"launchd check-in: no sockets found to answer requests on!\n");
64706f2543Smrg        return ERROR_FD;
65706f2543Smrg    }
66706f2543Smrg
67706f2543Smrg    if (launch_data_dict_get_count(sockets_dict) > 1) {
68706f2543Smrg        fprintf(stderr,"launchd check-in: some sockets will be ignored!\n");
69706f2543Smrg        return ERROR_FD;
70706f2543Smrg    }
71706f2543Smrg
72706f2543Smrg    listening_fd_array = launch_data_dict_lookup(sockets_dict, LAUNCHD_ID_PREFIX":0");
73706f2543Smrg    if (NULL == listening_fd_array) {
74706f2543Smrg        listening_fd_array = launch_data_dict_lookup(sockets_dict, ":0");
75706f2543Smrg        if (NULL == listening_fd_array) {
76706f2543Smrg            fprintf(stderr,"launchd check-in: No known sockets found to answer requests on! \"%s:0\" and \":0\" failed.\n", LAUNCHD_ID_PREFIX);
77706f2543Smrg            return ERROR_FD;
78706f2543Smrg        }
79706f2543Smrg    }
80706f2543Smrg
81706f2543Smrg    if (launch_data_array_get_count(listening_fd_array)!=1) {
82706f2543Smrg        fprintf(stderr,"launchd check-in: Expected 1 socket from launchd, got %u)\n",
83706f2543Smrg                (unsigned)launch_data_array_get_count(listening_fd_array));
84706f2543Smrg        return ERROR_FD;
85706f2543Smrg    }
86706f2543Smrg
87706f2543Smrg    listening_fd=launch_data_array_get_index(listening_fd_array, 0);
88706f2543Smrg    return launch_data_get_fd(listening_fd);
89706f2543Smrg}
90