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@
22 #include <Security/Authorization.h>
23 #include <Security/AuthorizationTags.h>
24 #include <Security/AuthSession.h>
26 #include <sys/types.h>
27 #include <sys/select.h>
28 #include <sys/event.h>
29 #include <sys/socket.h>
46 #if __GNUC__ >= 4 && HAVE_SECURITY
47 OSStatus
SessionCreate(SessionCreationFlags flags
, SessionAttributeBits attributes
) __attribute__((weak
));
52 static void find_fds(launch_data_t o
, const char *key
__attribute__((unused
)), void *context
__attribute__((unused
)))
58 switch (launch_data_get_type(o
)) {
60 fd
= launch_data_get_fd(o
);
63 fcntl(fd
, F_SETFD
, 1);
64 EV_SET(&kev
, fd
, EVFILT_READ
, EV_ADD
, 0, 0, NULL
);
65 if (kevent(kq
, &kev
, 1, NULL
, 0, NULL
) == -1)
66 syslog(LOG_DEBUG
, "kevent(%d): %m", fd
);
68 case LAUNCH_DATA_ARRAY
:
69 for (i
= 0; i
< launch_data_array_get_count(o
); i
++)
70 find_fds(launch_data_array_get_index(o
, i
), NULL
, NULL
);
72 case LAUNCH_DATA_DICTIONARY
:
73 launch_data_dict_iterate(o
, find_fds
, NULL
);
80 int main(int argc
__attribute__((unused
)), char *argv
[])
82 struct timespec timeout
= { 10, 0 };
83 struct sockaddr_storage ss
;
84 socklen_t slen
= (socklen_t
)sizeof ss
;
86 int r
, ec
= EXIT_FAILURE
;
87 launch_data_t tmp
, resp
, msg
= launch_data_alloc(LAUNCH_DATA_STRING
);
88 const char *prog
= argv
[1];
89 bool w
= false, dupstdout
= true, dupstderr
= true;
91 launch_data_set_string(msg
, LAUNCH_KEY_CHECKIN
);
93 openlog(getprogname(), LOG_PERROR
|LOG_PID
|LOG_CONS
, LOG_LAUNCHD
);
97 if ((resp
= launch_msg(msg
)) == NULL
) {
98 syslog(LOG_ERR
, "launch_msg(%s): %m", LAUNCH_KEY_CHECKIN
);
102 launch_data_free(msg
);
104 tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_SOCKETS
);
106 find_fds(tmp
, NULL
, NULL
);
108 syslog(LOG_ERR
, "No FDs found to answer requests on!");
112 tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_TIMEOUT
);
114 timeout
.tv_sec
= (int)launch_data_get_integer(tmp
);
116 tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_PROGRAM
);
118 prog
= launch_data_get_string(tmp
);
120 tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_INETDCOMPATIBILITY
);
122 tmp
= launch_data_dict_lookup(tmp
, LAUNCH_JOBINETDCOMPATIBILITY_WAIT
);
124 w
= launch_data_get_bool(tmp
);
127 if (launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_STANDARDOUTPATH
))
130 if (launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_STANDARDERRORPATH
))
134 signal(SIGCHLD
, SIG_IGN
);
137 if ((r
= kevent(kq
, NULL
, 0, &kev
, 1, &timeout
)) == -1) {
138 syslog(LOG_DEBUG
, "kevent(): %m");
146 dup2((int)kev
.ident
, STDIN_FILENO
);
148 dup2((int)kev
.ident
, STDOUT_FILENO
);
150 dup2((int)kev
.ident
, STDERR_FILENO
);
151 execv(prog
, argv
+ 1);
152 syslog(LOG_ERR
, "execv(): %m");
156 if ((r
= accept((int)kev
.ident
, (struct sockaddr
*)&ss
, &slen
)) == -1) {
157 if (errno
== EWOULDBLOCK
)
159 syslog(LOG_WARNING
, "accept(): %m");
162 if (ss
.ss_family
== AF_INET
|| ss
.ss_family
== AF_INET6
) {
163 char fromhost
[NI_MAXHOST
];
164 char fromport
[NI_MAXSERV
];
167 gni_r
= getnameinfo((struct sockaddr
*)&ss
, slen
,
168 fromhost
, (socklen_t
) sizeof fromhost
,
169 fromport
, (socklen_t
) sizeof fromport
,
170 NI_NUMERICHOST
| NI_NUMERICSERV
);
173 syslog(LOG_WARNING
, "%s: getnameinfo(): %s", prog
, gai_strerror(gni_r
));
175 syslog(LOG_INFO
, "%s: Connection from: %s on port: %s", prog
, fromhost
, fromport
);
178 syslog(LOG_WARNING
, "%s: getnameinfo() only supports IPv4/IPv6. Connection from address family: %u", prog
, ss
.ss_family
);
183 syslog(LOG_WARNING
, "fork(): %m");
184 if( errno
!= ENOMEM
) {
198 if ((tmp
= launch_data_dict_lookup(resp
, LAUNCH_JOBKEY_SESSIONCREATE
)) && launch_data_get_bool(tmp
)) {
200 OSStatus scr
= SessionCreate(0, 0);
202 syslog(LOG_NOTICE
, "%s: SessionCreate() failed: %d", prog
, scr
);
204 syslog(LOG_NOTICE
, "%s: SessionCreate == NULL!", prog
);
208 fcntl(r
, F_SETFL
, 0);
209 fcntl(r
, F_SETFD
, 1);
210 dup2(r
, STDIN_FILENO
);
212 dup2(r
, STDOUT_FILENO
);
214 dup2(r
, STDERR_FILENO
);
215 signal(SIGCHLD
, SIG_DFL
);
216 execv(prog
, argv
+ 1);
217 syslog(LOG_ERR
, "execv(): %m");