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 <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2022-03-01 20:46:01 +01:00
parent ef9e9ec786
commit 6fa3aa41df
7 changed files with 97 additions and 57 deletions
+1 -1
View File
@@ -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);
}
+6 -4
View File
@@ -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);
}
+2 -2
View File
@@ -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);
}
+82 -44
View File
@@ -28,6 +28,7 @@
#include <dirent.h>
#include <err.h>
#include <stdarg.h>
#include <sysexits.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <sys/wait.h>
@@ -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) {
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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[]);
+4 -4
View File
@@ -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();