From 6fa3aa41df7a103424dc621cc278a53dc062fc57 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 28 Feb 2022 00:00:37 +0100 Subject: [PATCH] run(): add support for logging/redirect This patch adds support for optional logging of output from all run() commands. For run_interactive() we've opted to log instead of just redirect, meaning output on error is till on console but also in log. Signed-off-by: Joachim Wiberg --- plugins/bootmisc.c | 2 +- plugins/procps.c | 10 ++-- plugins/x11-common.c | 4 +- src/exec.c | 126 ++++++++++++++++++++++++++++--------------- src/finit.c | 2 +- src/helpers.h | 2 +- src/sig.c | 8 +-- 7 files changed, 97 insertions(+), 57 deletions(-) diff --git a/plugins/bootmisc.c b/plugins/bootmisc.c index 93ccb87d..9262cfa0 100644 --- a/plugins/bootmisc.c +++ b/plugins/bootmisc.c @@ -198,7 +198,7 @@ static void setup(void *arg) mksubsys("/var/run/sudo", 0711, "root", "root"); mksubsys("/var/run/sudo/ts", 0700, "root", "root"); if (whichp("restorecon")) - run("restorecon /var/run/sudo /var/run/sudo/ts"); + run("restorecon /var/run/sudo /var/run/sudo/ts", "restorecon"); umask(prev); } diff --git a/plugins/procps.c b/plugins/procps.c index 117cbb59..0e3a062b 100644 --- a/plugins/procps.c +++ b/plugins/procps.c @@ -34,9 +34,7 @@ static void setup(void *arg) { - size_t i; glob_t gl; - char buf[160]; if (rescue) { _d("Skipping %s plugin in rescue mode.", __FILE__); @@ -51,9 +49,13 @@ static void setup(void *arg) glob("/mnt/sysctl.d/*.conf", GLOB_APPEND, NULL, &gl); glob("/etc/sysctl.conf", GLOB_APPEND, NULL, &gl); if (gl.gl_pathc > 0) { + size_t i; + for (i = 0; i < gl.gl_pathc; i++) { - snprintf(buf, sizeof(buf), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]); - run(buf); + char cmd[160]; + + snprintf(cmd, sizeof(cmd), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]); + run(cmd, "sysctl"); } globfree(&gl); } diff --git a/plugins/x11-common.c b/plugins/x11-common.c index 77a8c280..b2a198d0 100644 --- a/plugins/x11-common.c +++ b/plugins/x11-common.c @@ -58,7 +58,7 @@ static void setup(void *arg) if ((fd = open("/var/run/console/console.lock", O_CREAT|O_WRONLY|O_TRUNC, 0644)) >= 0) { write(fd, username, strlen(username)); close(fd); - run("pam_console_apply"); + run("pam_console_apply", "pam-console"); } #endif @@ -66,7 +66,7 @@ static void setup(void *arg) makedir("/tmp/.ICE-unix", 01777); if (whichp("restorecon")) - run("restorecon /tmp/.ICE-unix /tmp/.X11-unix"); + run("restorecon /tmp/.ICE-unix /tmp/.X11-unix", "restorecon"); umask(prev); } diff --git a/src/exec.c b/src/exec.c index aaf3b099..70e0e79e 100644 --- a/src/exec.c +++ b/src/exec.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -70,74 +71,110 @@ int complete(char *cmd, int pid) return status; } -int run(char *cmd) +static int do_redirect(void) +{ + FILE *fp; + + fp = fopen("/dev/null", "w"); + if (fp) { + int fd = fileno(fp); + + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + + return fclose(fp); + } + + return -1; +} + +/* + * Run 'cmd' and wait for completion. If 'log' is not NULL any output + * from the command is logged with the given string as prefix, use "" to + * skip. If 'log' is NULL all output is redirected to /dev/null, which + * is what this function originally did. + */ +int run(char *cmd, char *log) { int status, result, i = 0; - char *args[NUM_ARGS + 1], *arg, *backup; + char *args[NUM_ARGS + 1], *arg; + char *backup = NULL; pid_t pid; - /* We must create a copy that is possible to modify. */ - backup = arg = strdup(cmd); - if (!arg) - return 1; /* Failed allocating a string to be modified. */ + if (!log) { + /* We must create a copy that is possible to modify. */ + backup = arg = strdup(cmd); + if (!arg) + return 1; - /* Split command line into tokens of an argv[] array. */ - args[i++] = strsep(&arg, "\t "); - while (arg && i < NUM_ARGS) { - /* Handle run("su -c \"dbus-daemon --system\" messagebus"); - * => "su", "-c", "\"dbus-daemon --system\"", "messagebus" */ - if (*arg == '\'' || *arg == '"') { - char *p, delim[2] = " "; + /* Split command line into tokens of an argv[] array. */ + args[i++] = strsep(&arg, "\t "); + while (arg && i < NUM_ARGS) { + /* Handle run("su -c \"dbus-daemon --system\" messagebus"); + * => "su", "-c", "\"dbus-daemon --system\"", "messagebus" */ + if (*arg == '\'' || *arg == '"') { + char *p, delim[2] = " "; - delim[0] = arg[0]; - args[i++] = arg++; - strsep(&arg, delim); - p = arg - 1; - *p = *delim; - *arg++ = 0; - } else { - args[i++] = strsep(&arg, "\t "); + delim[0] = arg[0]; + args[i++] = arg++; + strsep(&arg, delim); + p = arg - 1; + *p = *delim; + *arg++ = 0; + } else { + args[i++] = strsep(&arg, "\t "); + } } - } - args[i] = NULL; + args[i] = NULL; - if (i == NUM_ARGS && arg) { - _e("Command too long: %s", cmd); - free(backup); - errno = EOVERFLOW; - return 1; + if (i == NUM_ARGS && arg) { + _e("Command too long: %s", cmd); + free(backup); + errno = EOVERFLOW; + return 1; + } } pid = fork(); if (0 == pid) { - FILE *fp; + int rc = EX_OSERR; setsid(); + sig_unblock(); + if (!log) { + do_redirect(); + execvp(args[0], args); + } else { + char *pfx = *log ? ": " : ""; + FILE *pp; - /* Always redirect stdio for run() */ - fp = fopen("/dev/null", "w"); - if (fp) { - int fd = fileno(fp); + pp = popen(cmd, "r"); + if (pp) { + char buf[256]; - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); + while (fgets(buf, sizeof(buf), pp)) { + chomp(buf); + logit(LOG_NOTICE, "%s%s%s", log, pfx, buf); + } + + rc = pclose(pp); + } } - sig_unblock(); - execvp(args[0], args); - - _exit(1); /* Only if execv() fails. */ + _exit(rc); } else if (-1 == pid) { _pe("%s", args[0]); - free(backup); + if (backup) + free(backup); return -1; } status = complete(args[0], pid); if (-1 == status) { - free(backup); + if (backup) + free(backup); return 1; } @@ -152,7 +189,8 @@ int run(char *cmd) * change their return code accordingly. --Jocke */ } - free(backup); + if (backup) + free(backup); return result; } @@ -186,7 +224,7 @@ int run_interactive(char *cmd, char *fmt, ...) } /* Run cmd ... */ - status = run(cmd); + status = run(cmd, ""); /* Restore stderr/stdout */ if (fp && !debug) { diff --git a/src/finit.c b/src/finit.c index 500645e9..ffa9dd99 100644 --- a/src/finit.c +++ b/src/finit.c @@ -333,7 +333,7 @@ static void fs_mount_all(void) _d("Calling extra mount hook, after mount -a ..."); plugin_run_hooks(HOOK_MOUNT_POST); - run("swapon -ea"); + run("swapon -ea", "swapon"); _d("Finalize, ensure common file systems are available ..."); fs_finalize(); diff --git a/src/helpers.h b/src/helpers.h index 839a2952..58e742fc 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -96,7 +96,7 @@ void networking (int updown); int in_container (void); int complete (char *cmd, int pid); -int run (char *cmd); +int run (char *cmd, char *log); int run_interactive (char *cmd, char *fmt, ...); int exec_runtask (char *cmd, char *args[]); pid_t run_getty (char *tty, char *cmd, char *args[], int noclear, int nowait, struct rlimit rlimit[]); diff --git a/src/sig.c b/src/sig.c index 49a2d673..5a12aaa1 100644 --- a/src/sig.c +++ b/src/sig.c @@ -313,16 +313,16 @@ void do_shutdown(shutop_t op) /* Unmount any tmpfs before unmounting swap ... */ unmount_tmpfs(); - run("swapoff -e -a"); + run("swapoff -e -a", "swapoff"); /* ... unmount remaining regular file systems. */ unmount_regular(); /* We sit on / so we must remount it ro, try all the things! */ sync(); - run("mount -n -o remount,ro -t dummytype dummydev /"); - run("mount -n -o remount,ro dummydev /"); - run("mount -n -o remount,ro /"); + run("mount -n -o remount,ro -t dummytype dummydev /", "mount"); + run("mount -n -o remount,ro dummydev /", "mount"); + run("mount -n -o remount,ro /", "mount"); /* Call mdadm to mark any RAID array(s) as clean before halting. */ mdadm_wait();