* @APPLE_APACHE_LICENSE_HEADER_END@
*/
-static const char *const __rcs_file_version__ = "$Revision: 1.11 $";
+static const char *const __rcs_file_version__ = "$Revision: 23274 $";
+
+#include "config.h"
+#include "launchd_unix_ipc.h"
#include <sys/types.h>
#include <sys/queue.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
-#include <syslog.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <paths.h>
#include <string.h>
-#include "launch.h"
-#include "launch_priv.h"
+#include "liblaunch_public.h"
+#include "liblaunch_private.h"
#include "launchd.h"
+#include "launchd_runtime.h"
#include "launchd_core_logic.h"
-#include "launchd_unix_ipc.h"
extern char **environ;
-static SLIST_HEAD(, conncb) connections = { NULL };
+static LIST_HEAD(, conncb) connections;
static launch_data_t adjust_rlimits(launch_data_t in);
void
ipc_clean_up(void)
{
- if (ipc_self != getpid())
+ if (ipc_self != getpid()) {
return;
+ }
- if (-1 == unlink(sockpath))
- syslog(LOG_WARNING, "unlink(\"%s\"): %m", sockpath);
- else if (-1 == rmdir(sockdir))
- syslog(LOG_WARNING, "rmdir(\"%s\"): %m", sockdir);
+ if (-1 == unlink(sockpath)) {
+ runtime_syslog(LOG_WARNING, "unlink(\"%s\"): %m", sockpath);
+ } else if (-1 == rmdir(sockdir)) {
+ runtime_syslog(LOG_WARNING, "rmdir(\"%s\"): %m", sockdir);
+ }
}
void
-ipc_server_init(int *fds, size_t fd_cnt)
+ipc_server_init(void)
{
struct sockaddr_un sun;
mode_t oldmask;
int r, fd = -1;
char ourdir[1024];
- size_t i;
- if (ipc_inited)
+ if (ipc_inited) {
return;
-
- if (fds)
- goto add_fds;
+ }
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
stat(ourdir, &sb);
if (!S_ISDIR(sb.st_mode)) {
errno = EEXIST;
- syslog(LOG_ERR, "mkdir(\"%s\"): %m", LAUNCHD_SOCK_PREFIX);
+ runtime_syslog(LOG_ERR, "mkdir(\"%s\"): %m", LAUNCHD_SOCK_PREFIX);
goto out_bad;
}
} else {
- syslog(LOG_ERR, "mkdir(\"%s\"): %m", ourdir);
+ runtime_syslog(LOG_ERR, "mkdir(\"%s\"): %m", ourdir);
goto out_bad;
}
}
} else {
snprintf(ourdir, sizeof(ourdir), "/tmp/launchd-%u.XXXXXX", getpid());
- if (!launchd_assumes(mkdtemp(ourdir) != NULL))
+ if (!launchd_assumes(mkdtemp(ourdir) != NULL)) {
goto out_bad;
+ }
snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/sock", ourdir);
- setenv(LAUNCHD_SOCKET_ENV, sun.sun_path, 1);
}
if (unlink(sun.sun_path) == -1 && errno != ENOENT) {
- if (errno != EROFS)
- syslog(LOG_ERR, "unlink(\"thesocket\"): %m");
+ if (errno != EROFS) {
+ runtime_syslog(LOG_ERR, "unlink(\"thesocket\"): %m");
+ }
goto out_bad;
}
- if (!launchd_assumes((fd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) != -1))
+ if (!launchd_assumes((fd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) != -1)) {
goto out_bad;
+ }
oldmask = umask(S_IRWXG|S_IRWXO);
r = bind(fd, (struct sockaddr *)&sun, sizeof(sun));
umask(oldmask);
if (r == -1) {
- if (errno != EROFS)
- syslog(LOG_ERR, "bind(\"thesocket\"): %m");
+ if (errno != EROFS) {
+ runtime_syslog(LOG_ERR, "bind(\"thesocket\"): %m");
+ }
goto out_bad;
}
if (listen(fd, SOMAXCONN) == -1) {
- syslog(LOG_ERR, "listen(\"thesocket\"): %m");
+ runtime_syslog(LOG_ERR, "listen(\"thesocket\"): %m");
goto out_bad;
}
-add_fds:
- if (fds) {
- for (i = 0; i < fd_cnt; i++) {
- if (kevent_mod(fds[i], EVFILT_READ, EV_ADD, 0, 0, &kqipc_listen_callback) == -1) {
- syslog(LOG_ERR, "kevent_mod(%d, EVFILT_READ): %m", fds[i]);
- goto out_bad;
- }
- }
- } else if (kevent_mod(fd, EVFILT_READ, EV_ADD, 0, 0, &kqipc_listen_callback) == -1) {
- syslog(LOG_ERR, "kevent_mod(\"thesocket\", EVFILT_READ): %m");
+ if (kevent_mod(fd, EVFILT_READ, EV_ADD, 0, 0, &kqipc_listen_callback) == -1) {
+ runtime_syslog(LOG_ERR, "kevent_mod(\"thesocket\", EVFILT_READ): %m");
goto out_bad;
}
ipc_inited = true;
- if (!fds) {
- sockdir = strdup(ourdir);
- sockpath = strdup(sun.sun_path);
- ipc_self = getpid();
- atexit(ipc_clean_up);
- }
+ sockdir = strdup(ourdir);
+ sockpath = strdup(sun.sun_path);
+ ipc_self = getpid();
+ atexit(ipc_clean_up);
out_bad:
- if (!ipc_inited && fd != -1)
- launchd_assumes(close(fd) == 0);
+ if (!ipc_inited && fd != -1) {
+ launchd_assumes(runtime_close(fd) == 0);
+ }
}
void
-ipc_open(int fd, struct jobcb *j)
+ipc_open(int fd, job_t j)
{
struct conncb *c = calloc(1, sizeof(struct conncb));
c->kqconn_callback = ipc_callback;
c->conn = launchd_fdopen(fd);
c->j = j;
- SLIST_INSERT_HEAD(&connections, c, sle);
+ LIST_INSERT_HEAD(&connections, c, sle);
kevent_mod(fd, EVFILT_READ, EV_ADD, 0, 0, &c->kqconn_callback);
}
if (kev->filter == EVFILT_READ) {
if (launchd_msg_recv(c->conn, ipc_readmsg, c) == -1 && errno != EAGAIN) {
- if (errno != ECONNRESET)
- syslog(LOG_DEBUG, "%s(): recv: %m", __func__);
+ if (errno != ECONNRESET) {
+ runtime_syslog(LOG_DEBUG, "%s(): recv: %m", __func__);
+ }
ipc_close(c);
}
} else if (kev->filter == EVFILT_WRITE) {
r = launchd_msg_send(c->conn, NULL);
if (r == -1) {
if (errno != EAGAIN) {
- syslog(LOG_DEBUG, "%s(): send: %m", __func__);
+ runtime_syslog(LOG_DEBUG, "%s(): send: %m", __func__);
ipc_close(c);
}
} else if (r == 0) {
kevent_mod(launchd_getfd(c->conn), EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
}
} else {
- syslog(LOG_DEBUG, "%s(): unknown filter type!", __func__);
+ runtime_syslog(LOG_DEBUG, "%s(): unknown filter type!", __func__);
ipc_close(c);
}
}
setenv(key, launch_data_get_string(obj), 1);
}
+void
+ipc_close_all_with_job(job_t j)
+{
+ struct conncb *ci, *cin;
+
+ LIST_FOREACH_SAFE(ci, &connections, sle, cin) {
+ if (ci->j == j) {
+ ipc_close(ci);
+ }
+ }
+}
+
void
ipc_close_fds(launch_data_t o)
{
ipc_close_fds(launch_data_array_get_index(o, i));
break;
case LAUNCH_DATA_FD:
- if (launch_data_get_fd(o) != -1)
- launchd_assumes(close(launch_data_get_fd(o)) == 0);
+ if (launch_data_get_fd(o) != -1) {
+ launchd_assumes(runtime_close(launch_data_get_fd(o)) == 0);
+ }
break;
default:
break;
rmc.resp = launch_data_new_errno(EINVAL);
}
- if (NULL == rmc.resp)
+ if (NULL == rmc.resp) {
rmc.resp = launch_data_new_errno(ENOSYS);
+ }
ipc_close_fds(msg);
if (errno == EAGAIN) {
kevent_mod(launchd_getfd(rmc.c->conn), EVFILT_WRITE, EV_ADD, 0, 0, &rmc.c->kqconn_callback);
} else {
- syslog(LOG_DEBUG, "launchd_msg_send() == -1: %m");
+ runtime_syslog(LOG_DEBUG, "launchd_msg_send() == -1: %m");
ipc_close(rmc.c);
}
}
{
struct readmsg_context *rmc = context;
launch_data_t resp = NULL;
- struct jobcb *j;
+ job_t j;
- if (rmc->resp)
+ if (rmc->resp) {
return;
+ }
+
+ //job_log(rmc->c->j, LOG_DEBUG, "Unix IPC request: %s", cmd);
if (data == NULL) {
if (!strcmp(cmd, LAUNCH_KEY_CHECKIN)) {
} else {
resp = launch_data_new_errno(EACCES);
}
- } else if (!strcmp(cmd, LAUNCH_KEY_RELOADTTYS)) {
- update_ttys();
- resp = launch_data_new_errno(0);
} else if (!strcmp(cmd, LAUNCH_KEY_SHUTDOWN)) {
launchd_shutdown();
resp = launch_data_new_errno(0);
ipc_revoke_fds(resp);
} else if (!strcmp(cmd, LAUNCH_KEY_GETRESOURCELIMITS)) {
resp = adjust_rlimits(NULL);
- } else if (!strcmp(cmd, LAUNCH_KEY_GETUSERENVIRONMENT)) {
- char **tmpenviron = environ;
- resp = launch_data_alloc(LAUNCH_DATA_DICTIONARY);
- for (; *tmpenviron; tmpenviron++) {
- char envkey[1024];
- launch_data_t s = launch_data_alloc(LAUNCH_DATA_STRING);
- launch_data_set_string(s, strchr(*tmpenviron, '=') + 1);
- strncpy(envkey, *tmpenviron, sizeof(envkey));
- *(strchr(envkey, '=')) = '\0';
- launch_data_dict_insert(resp, s, envkey);
- }
- } else if (!strcmp(cmd, LAUNCH_KEY_GETLOGMASK)) {
- int oldmask = setlogmask(LOG_UPTO(LOG_DEBUG));
- resp = launch_data_new_integer(oldmask);
- setlogmask(oldmask);
- } else if (!strcmp(cmd, LAUNCH_KEY_GETUMASK)) {
- mode_t oldmask = umask(0);
- resp = launch_data_new_integer(oldmask);
- umask(oldmask);
} else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGESELF)) {
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
struct rusage rusage;
getrusage(RUSAGE_CHILDREN, &rusage);
resp = launch_data_new_opaque(&rusage, sizeof(rusage));
- } else if (!strcmp(cmd, LAUNCH_KEY_BATCHQUERY)) {
- resp = launch_data_alloc(LAUNCH_DATA_BOOL);
- launch_data_set_bool(resp, batch_disabler_count == 0);
}
} else if (!strcmp(cmd, LAUNCH_KEY_STARTJOB)) {
- if ((j = job_find(root_job, launch_data_get_string(data))) != NULL) {
- job_start(j);
+ if ((j = job_find(launch_data_get_string(data))) != NULL) {
+ job_dispatch(j, true);
errno = 0;
}
resp = launch_data_new_errno(errno);
} else if (!strcmp(cmd, LAUNCH_KEY_STOPJOB)) {
- if ((j = job_find(root_job, launch_data_get_string(data))) != NULL) {
+ if ((j = job_find(launch_data_get_string(data))) != NULL) {
job_stop(j);
errno = 0;
}
resp = launch_data_new_errno(errno);
} else if (!strcmp(cmd, LAUNCH_KEY_REMOVEJOB)) {
- if ((j = job_find(root_job, launch_data_get_string(data))) != NULL) {
+ if ((j = job_find(launch_data_get_string(data))) != NULL) {
job_remove(j);
errno = 0;
}
if (launch_data_get_type(data) == LAUNCH_DATA_ARRAY) {
resp = job_import_bulk(data);
} else {
- if (job_import(data))
+ if (job_import(data)) {
errno = 0;
+ }
resp = launch_data_new_errno(errno);
}
} else if (!strcmp(cmd, LAUNCH_KEY_UNSETUSERENVIRONMENT)) {
} else if (!strcmp(cmd, LAUNCH_KEY_SETRESOURCELIMITS)) {
resp = adjust_rlimits(data);
} else if (!strcmp(cmd, LAUNCH_KEY_GETJOB)) {
- if ((j = job_find(root_job, launch_data_get_string(data))) == NULL) {
+ if ((j = job_find(launch_data_get_string(data))) == NULL) {
resp = launch_data_new_errno(errno);
} else {
resp = job_export(j);
ipc_revoke_fds(resp);
}
- } else if (!strcmp(cmd, LAUNCH_KEY_GETJOBWITHHANDLES)) {
- if ((j = job_find(root_job, launch_data_get_string(data))) == NULL) {
- resp = launch_data_new_errno(errno);
- } else {
- resp = job_export(j);
- }
- } else if (!strcmp(cmd, LAUNCH_KEY_SETLOGMASK)) {
- resp = launch_data_new_integer(setlogmask(launch_data_get_integer(data)));
- } else if (!strcmp(cmd, LAUNCH_KEY_SETUMASK)) {
- resp = launch_data_new_integer(umask(launch_data_get_integer(data)));
- } else if (!strcmp(cmd, LAUNCH_KEY_SETSTDOUT)) {
- resp = launchd_setstdio(STDOUT_FILENO, data);
- } else if (!strcmp(cmd, LAUNCH_KEY_SETSTDERR)) {
- resp = launchd_setstdio(STDERR_FILENO, data);
- } else if (!strcmp(cmd, LAUNCH_KEY_BATCHCONTROL)) {
- batch_job_enable(launch_data_get_bool(data), rmc->c);
- resp = launch_data_new_errno(0);
}
rmc->resp = resp;
void
ipc_close(struct conncb *c)
{
- batch_job_enable(true, c);
-
- SLIST_REMOVE(&connections, c, conncb, sle);
- launchd_close(c->conn);
+ LIST_REMOVE(c, sle);
+ launchd_close(c->conn, runtime_close);
free(c);
}
ltmpsz = launch_data_get_opaque_size(in);
if (ltmpsz > sizeof(l)) {
- syslog(LOG_WARNING, "Too much rlimit data sent!");
+ runtime_syslog(LOG_WARNING, "Too much rlimit data sent!");
ltmpsz = sizeof(l);
}
for (i = 0; i < (ltmpsz / sizeof(struct rlimit)); i++) {
- if (ltmp[i].rlim_cur == l[i].rlim_cur && ltmp[i].rlim_max == l[i].rlim_max)
+ if (ltmp[i].rlim_cur == l[i].rlim_cur && ltmp[i].rlim_max == l[i].rlim_max) {
continue;
+ }
- if (/* XXX readcfg_pid && */ getpid() == 1) {
+ if (/* XXX readcfg_pid && */ getpid() == 1 && (i == RLIMIT_NOFILE || i == RLIMIT_NPROC)) {
int gmib[] = { CTL_KERN, KERN_MAXPROC };
int pmib[] = { CTL_KERN, KERN_MAXPROCPERUID };
const char *gstr = "kern.maxproc";
break;
case RLIMIT_NPROC:
/* kernel will not clamp to this value, we must */
- if (gval > (2048 + 20))
+ if (gval > (2048 + 20)) {
gval = 2048 + 20;
+ }
break;
default:
break;
if (gval > 0) {
launchd_assumes(sysctl(gmib, 2, NULL, NULL, &gval, sizeof(gval)) != -1);
} else {
- syslog(LOG_WARNING, "sysctl(\"%s\"): can't be zero", gstr);
+ runtime_syslog(LOG_WARNING, "sysctl(\"%s\"): can't be zero", gstr);
}
if (pval > 0) {
launchd_assumes(sysctl(pmib, 2, NULL, NULL, &pval, sizeof(pval)) != -1);
} else {
- syslog(LOG_WARNING, "sysctl(\"%s\"): can't be zero", pstr);
+ runtime_syslog(LOG_WARNING, "sysctl(\"%s\"): can't be zero", pstr);
}
}
launchd_assumes(setrlimit(i, ltmp + i) != -1);