2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
21 #include <sys/types.h>
22 #include <sys/select.h>
23 #include <sys/event.h>
24 #include <sys/socket.h>
39 #if !TARGET_OS_EMBEDDED
40 #include <bsm/audit.h>
41 #include <bsm/audit_session.h>
42 #endif // !TARGET_OS_EMBEDDED
48 static void find_fds(launch_data_t o
, const char *key
__attribute__((unused
)), void *context
__attribute__((unused
)))
54 switch (launch_data_get_type(o
)) {
56 fd
= launch_data_get_fd(o
);
59 fcntl(fd
, F_SETFD
, 1);
60 EV_SET(&kev
, fd
, EVFILT_READ
, EV_ADD
, 0, 0, NULL
);
61 if (kevent(kq
, &kev
, 1, NULL
, 0, NULL
) == -1)
62 syslog(LOG_DEBUG
, "kevent(%d): %m", fd
);
64 case LAUNCH_DATA_ARRAY
:
65 for (i
= 0; i
< launch_data_array_get_count(o
); i
++)
66 find_fds(launch_data_array_get_index(o
, i
), NULL
, NULL
);
68 case LAUNCH_DATA_DICTIONARY
:
69 launch_data_dict_iterate(o
, find_fds
, NULL
);
76 int main(int argc
__attribute__((unused
)), char *argv
[])
78 struct timespec timeout
= { 10, 0 };
79 struct sockaddr_storage ss
;
80 socklen_t slen
= (socklen_t
)sizeof ss
;
82 int r
, ec
= EXIT_FAILURE
;
83 launch_data_t tmp
, resp
, msg
= launch_data_alloc(LAUNCH_DATA_STRING
);
84 const char *prog
= argv
[1];
85 bool w
= false, dupstdout
= true, dupstderr
= true;
87 launch_data_set_string(msg
, LAUNCH_KEY_CHECKIN
);
89 openlog(getprogname(), LOG_PERROR
|LOG_PID
|LOG_CONS
, LOG_LAUNCHD
);
93 if ((resp
= launch_msg(msg
)) == NULL
) {
94 syslog(LOG_ERR
, "launch_msg(%s): %m", LAUNCH_KEY_CHECKIN
);
98 launch_data_free(msg
);
100 tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_SOCKETS
);
102 find_fds(tmp
, NULL
, NULL
);
104 syslog(LOG_ERR
, "No FDs found to answer requests on!");
108 tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_TIMEOUT
);
110 timeout
.tv_sec
= (int)launch_data_get_integer(tmp
);
112 tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_PROGRAM
);
114 prog
= launch_data_get_string(tmp
);
116 tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_INETDCOMPATIBILITY
);
118 tmp
= launch_data_dict_lookup(tmp
, LAUNCH_JOBINETDCOMPATIBILITY_WAIT
);
120 w
= launch_data_get_bool(tmp
);
123 if (launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_STANDARDOUTPATH
))
126 if (launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_STANDARDERRORPATH
))
130 signal(SIGCHLD
, SIG_IGN
);
133 if ((r
= kevent(kq
, NULL
, 0, &kev
, 1, &timeout
)) == -1) {
134 syslog(LOG_DEBUG
, "kevent(): %m");
142 dup2((int)kev
.ident
, STDIN_FILENO
);
144 dup2((int)kev
.ident
, STDOUT_FILENO
);
146 dup2((int)kev
.ident
, STDERR_FILENO
);
147 execv(prog
, argv
+ 1);
148 syslog(LOG_ERR
, "execv(): %m");
152 if ((r
= accept((int)kev
.ident
, (struct sockaddr
*)&ss
, &slen
)) == -1) {
153 if (errno
== EWOULDBLOCK
)
155 syslog(LOG_WARNING
, "accept(): %m");
158 if (ss
.ss_family
== AF_INET
|| ss
.ss_family
== AF_INET6
) {
159 char fromhost
[NI_MAXHOST
];
160 char fromport
[NI_MAXSERV
];
163 gni_r
= getnameinfo((struct sockaddr
*)&ss
, slen
,
164 fromhost
, (socklen_t
) sizeof fromhost
,
165 fromport
, (socklen_t
) sizeof fromport
,
166 NI_NUMERICHOST
| NI_NUMERICSERV
);
169 syslog(LOG_WARNING
, "%s: getnameinfo(): %s", prog
, gai_strerror(gni_r
));
171 syslog(LOG_INFO
, "%s: Connection from: %s on port: %s", prog
, fromhost
, fromport
);
174 syslog(LOG_WARNING
, "%s: getnameinfo() only supports IPv4/IPv6. Connection from address family: %u", prog
, ss
.ss_family
);
179 syslog(LOG_WARNING
, "fork(): %m");
180 if (errno
!= ENOMEM
) {
193 #if !TARGET_OS_EMBEDDED
194 if ((tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_SESSIONCREATE
)) && launch_data_get_bool(tmp
)) {
195 auditinfo_addr_t auinfo
= {
196 .ai_termid
= { .at_type
= AU_IPv4
},
197 .ai_asid
= AU_ASSIGN_ASID
,
201 if (setaudit_addr(&auinfo
, sizeof(auinfo
)) == 0) {
203 snprintf(session
, sizeof(session
), "%x", auinfo
.ai_asid
);
204 setenv("SECURITYSESSIONID", session
, 1);
206 syslog(LOG_NOTICE
, "%s: Setting Audit Session ID failed: %d", prog
, errno
);
209 #endif // !TARGET_OS_EMBEDDED
210 fcntl(r
, F_SETFL
, 0);
211 fcntl(r
, F_SETFD
, 1);
212 dup2(r
, STDIN_FILENO
);
214 dup2(r
, STDOUT_FILENO
);
216 dup2(r
, STDERR_FILENO
);
217 signal(SIGCHLD
, SIG_DFL
);
218 execv(prog
, argv
+ 1);
219 syslog(LOG_ERR
, "execv(): %m");