return 1;
}
+#ifndef THERE_IS_NO_FORK
+void
+dhcpcd_daemonised(struct dhcpcd_ctx *ctx)
+{
+ unsigned int logopts = loggetopts();
+
+ /*
+ * Stop writing to stderr.
+ * On the happy path, only the manager process writes to stderr,
+ * so this just stops wasting fprintf calls to nowhere.
+ * All other calls - ie errors in privsep processes or script output,
+ * will error when printing.
+ * If we *really* want to fix that, then we need to suck
+ * stderr/stdout in the manager process and either discard it or pass
+ * it to the launcher process and then to stderr.
+ */
+ logopts &= ~LOGERR_ERR;
+ logsetopts(logopts);
+
+ /*
+ * We need to do something with stdout/stderr to avoid SIGPIPE
+ * We know that stdin is already mapped to /dev/null
+ */
+ dup2(STDIN_FILENO, STDOUT_FILENO);
+ dup2(STDIN_FILENO, STDERR_FILENO);
+
+ ctx->options |= DHCPCD_DAEMONISED;
+}
+#endif
+
/* Returns the pid of the child, otherwise 0. */
void
dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
if (!(logopts & LOGERR_QUIET) && ctx->stderr_valid)
(void)fprintf(stderr,
"forked to background, child pid %d\n", getpid());
+
+#ifdef PRIVSEP
+ ps_daemonised(ctx);
+#else
+ dhcpcd_daemonised(ctx);
+#endif
+
i = EXIT_SUCCESS;
if (write(ctx->fork_fd, &i, sizeof(i)) == -1)
logerr("write");
eloop_event_delete(ctx->eloop, ctx->fork_fd);
close(ctx->fork_fd);
ctx->fork_fd = -1;
-
- /*
- * Stop writing to stderr.
- * On the happy path, only the manager process writes to stderr,
- * so this just stops wasting fprintf calls to nowhere.
- * All other calls - ie errors in privsep processes or script output,
- * will error when printing.
- * If we *really* want to fix that, then we need to suck
- * stderr/stdout in the manager process and either disacrd it or pass
- * it to the launcher process and then to stderr.
- */
- logopts &= ~LOGERR_ERR;
- logsetopts(logopts);
#endif
}
static int dup_null(int fd)
{
+ int fd_null = open(_PATH_DEVNULL, O_WRONLY);
int err;
- int fd_null = open(_PATH_DEVNULL, O_RDONLY);
if (fd_null == -1) {
logwarn("open %s", _PATH_DEVNULL);
return -1;
}
- if ((err = dup2(fd, fd_null)) == -1)
+ if ((err = dup2(fd_null, fd)) == -1)
logwarn("dup2 %d", fd);
- close(fd);
+ close(fd_null);
return err;
}
ctx.stdout_valid = fcntl(STDOUT_FILENO, F_GETFD) != -1;
ctx.stderr_valid = fcntl(STDERR_FILENO, F_GETFD) != -1;
+ /* Even we if we don't have input/outputs, we need to
+ * ensure they are setup for shells. */
+ if (!ctx.stdin_valid)
+ dup_null(STDIN_FILENO);
+ if (!ctx.stdout_valid)
+ dup_null(STDOUT_FILENO);
+ if (!ctx.stderr_valid)
+ dup_null(STDERR_FILENO);
+
logopts = LOGERR_LOG | LOGERR_LOG_DATE | LOGERR_LOG_PID;
if (ctx.stderr_valid)
logopts |= LOGERR_ERR;
return len;
}
+ssize_t
+ps_daemonised(struct dhcpcd_ctx *ctx)
+{
+ struct ps_process *psp;
+ ssize_t err = 0;
+
+ dhcpcd_daemonised(ctx);
+
+ /* Echo the message to all processes */
+ TAILQ_FOREACH(psp, &ctx->ps_processes, next) {
+ if (psp->psp_pid == getpid())
+ continue;
+ if (ps_sendcmd(psp->psp_ctx, psp->psp_fd, PS_DAEMONISED,
+ 0, NULL, 0) == -1)
+ err = -1;
+ }
+
+ return err;
+}
+
ssize_t
ps_recvpsmsg(struct dhcpcd_ctx *ctx, int fd, unsigned short events,
ssize_t (*callback)(void *, struct ps_msghdr *, struct msghdr *),
if (psm.psm_hdr.ps_cmd == PS_STOP) {
stop = true;
len = 0;
+ } else if (psm.psm_hdr.ps_cmd == PS_DAEMONISED) {
+ ps_daemonised(ctx);
+ return 0;
}
}
#define PS_CTL_EOF 0x0019
#define PS_LOGREOPEN 0x0020
#define PS_STOPPROCS 0x0021
+#define PS_DAEMONISED 0x0022
/* Domains */
#define PS_ROOT 0x0101
int ps_stopwait(struct dhcpcd_ctx *);
int ps_entersandbox(const char *, const char **);
int ps_managersandbox(struct dhcpcd_ctx *, const char *);
+ssize_t ps_daemonised(struct dhcpcd_ctx *);
int ps_unrollmsg(struct msghdr *, struct ps_msghdr *, const void *, size_t);
ssize_t ps_sendpsmmsg(struct dhcpcd_ctx *, int,