assert(eloop != NULL);
assert(cb != NULL && cb_arg != NULL);
- if (fd == -1 || !(events & (ELE_READ | ELE_WRITE))) {
+ if (fd == -1 || !(events & (ELE_READ | ELE_WRITE | ELE_HANGUP))) {
errno = EINVAL;
return -1;
}
EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, e);
else
n--;
+#ifdef EVFILT_PROCDESC
+ if (events & ELE_HANGUP)
+ EV_SET(kep++, (uintptr_t)fd, EVFILT_PROCDESC, EV_ADD,
+ NOTE_EXIT, 0, e);
+ else
+ n--;
+#endif
if (n != 0 && _kevent(eloop->fd, ke, n, NULL, 0, NULL) == -1) {
if (added) {
TAILQ_REMOVE(&eloop->events, e, next);
#ifdef HAVE_CAPSICUM
#include <sys/capsicum.h>
+#include <sys/procdesc.h>
#include <capsicum_helpers.h>
#endif
#ifdef HAVE_UTIL_H
}
#endif
+#ifdef HAVE_CAPSICUM
+static void
+ps_processhangup(void *arg, unsigned short events)
+{
+ struct ps_process *psp = arg;
+ struct dhcpcd_ctx *ctx = psp->psp_ctx;
+
+ if (!(events & ELE_HANGUP))
+ logerrx("%s: unexpected event 0x%04x", __func__, events);
+
+ logdebugx("%s%s%s exited from PID %d",
+ psp->psp_ifname, psp->psp_ifname[0] != '\0' ? ": " : "",
+ psp->psp_name, psp->psp_pid);
+
+ ps_freeprocess(psp);
+
+ if (!(ctx->options & DHCPCD_EXITING))
+ return;
+ if (!(PS_WAITING_FOR_PROCESSES(ctx)))
+ eloop_exit(ctx->ps_eloop, EXIT_SUCCESS);
+}
+#endif
+
pid_t
ps_startprocess(struct ps_process *psp,
void (*recv_msg)(void *, unsigned short),
}
#endif
- switch (pid = fork()) {
+#ifdef HAVE_CAPSICUM
+ pid = pdfork(&psp->psp_pfd, PD_CLOEXEC);
+#else
+ pid = fork();
+#endif
+ switch (pid) {
case -1:
+#ifdef HAVE_CAPSICUM
+ logerr("pdfork");
+#else
logerr("fork");
+#endif
return -1;
case 0:
psp->psp_pid = getpid();
__func__, psp->psp_fd);
return -1;
}
+#ifdef HAVE_CAPSICUM
+ if (eloop_event_add(ctx->eloop, psp->psp_pfd, ELE_HANGUP,
+ ps_processhangup, psp) == -1)
+ {
+ logerr("%s: eloop_event_add pfd %d",
+ __func__, psp->psp_pfd);
+ return -1;
+ }
+#endif
return pid;
}
ps_process_timeout, ctx) == -1)
logerr("%s: eloop_timeout_add_sec", __func__);
eloop_enter(ctx->ps_eloop);
+
+#ifdef HAVE_CAPSICUM
+ struct ps_process *psp;
+
+ TAILQ_FOREACH(psp, &ctx->ps_processes, next) {
+ if (psp->psp_pfd == -1)
+ continue;
+ if (eloop_event_add(ctx->ps_eloop, psp->psp_pfd,
+ ELE_HANGUP, ps_processhangup, psp) == -1)
+ logerr("%s: eloop_event_add pfd %d",
+ __func__, psp->psp_pfd);
+ }
+#endif
+
waited = eloop_start(ctx->ps_eloop, &ctx->sigset);
if (waited != EXIT_SUCCESS) {
logerr("%s: eloop_start", __func__);
struct dhcpcd_ctx *ctx = psp->psp_ctx;
TAILQ_REMOVE(&ctx->ps_processes, psp, next);
+
if (psp->psp_fd != -1) {
eloop_event_delete(ctx->eloop, psp->psp_fd);
close(psp->psp_fd);
eloop_event_delete(ctx->eloop, psp->psp_work_fd);
close(psp->psp_work_fd);
}
+#ifdef HAVE_CAPSICUM
+ if (psp->psp_pfd != -1) {
+ eloop_event_delete(ctx->eloop, psp->psp_pfd);
+ if (ctx->ps_eloop != NULL)
+ eloop_event_delete(ctx->ps_eloop, psp->psp_pfd);
+ close(psp->psp_pfd);
+ }
+#endif
if (ctx->ps_root == psp)
ctx->ps_root = NULL;
if (ctx->ps_inet == psp)
psp->psp_ctx = ctx;
memcpy(&psp->psp_id, psid, sizeof(psp->psp_id));
psp->psp_work_fd = -1;
+#ifdef HAVE_CAPSICUM
+ psp->psp_pfd = -1;
+#endif
+
if (!(ctx->options & DHCPCD_MANAGER))
strlcpy(psp->psp_ifname, ctx->ifv[0], sizeof(psp->psp_name));
TAILQ_INSERT_TAIL(&ctx->ps_processes, psp, next);