#include <sys/stat.h>
#include <stddef.h>
#include <sys/prctl.h>
-
#include <dbus/dbus.h>
#include "log.h"
#include "bus-errors.h"
#include "build.h"
#include "unit-name.h"
+#include "pager.h"
static const char *arg_type = NULL;
static char **arg_property = NULL;
static bool private_bus = false;
-static pid_t pager_pid = 0;
static pid_t agent_pid = 0;
static int daemon_reload(DBusConnection *bus, char **args, unsigned n);
-static void pager_open(void);
static bool on_tty(void) {
static int t = -1;
return t;
}
+static void pager_open_if_enabled(void) {
+ on_tty();
+
+ if (!arg_no_pager)
+ pager_open();
+}
+
static void spawn_ask_password_agent(void) {
pid_t parent;
return EXIT_FAILURE;
}
-static int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next) {
-
- assert(iter);
- assert(data);
-
- if (dbus_message_iter_get_arg_type(iter) != type)
- return -EIO;
-
- dbus_message_iter_get_basic(iter, data);
-
- if (!dbus_message_iter_next(iter) != !next)
- return -EIO;
-
- return 0;
-}
-
static void warn_wall(enum action action) {
static const char *table[_ACTION_MAX] = {
[ACTION_HALT] = "The system is going down for system halt NOW!",
assert(bus);
- pager_open();
+ pager_open_if_enabled();
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
" red = Conflicts\n"
" green = After\n");
- if (isatty(fileno(stdout)))
+ if (on_tty())
log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
"-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
assert(bus);
- pager_open();
+ pager_open_if_enabled();
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
dbus_message_iter_recurse(&iter, &sub);
- if (isatty(STDOUT_FILENO))
+ if (on_tty())
printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
dbus_message_iter_next(&sub);
}
- if (isatty(STDOUT_FILENO))
+ if (on_tty())
printf("\n%u jobs listed.\n", k);
r = 0;
show_properties = !streq(args[0], "status");
if (show_properties)
- pager_open();
+ pager_open_if_enabled();
if (show_properties && n <= 1) {
/* If not argument is specified inspect the manager
dbus_error_init(&error);
- pager_open();
+ pager_open_if_enabled();
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
dbus_error_init(&error);
- pager_open();
+ pager_open_if_enabled();
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
if (streq(t, "now"))
*_u = 0;
- else if (t[0] == '+') {
+ else if (!strchr(t, ':')) {
uint64_t u;
- if (safe_atou64(t + 1, &u) < 0)
+ if (safe_atou64(t, &u) < 0)
return -EINVAL;
*_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
return verbs[i].dispatch(bus, argv + optind, left);
}
-static int send_shutdownd(usec_t t, char mode, bool warn, const char *message) {
+static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
int fd = -1;
struct msghdr msghdr;
struct iovec iovec;
zero(c);
c.elapse = t;
c.mode = mode;
+ c.dry_run = dry_run;
c.warn_wall = warn;
if (message)
arg_action == ACTION_HALT ? 'H' :
arg_action == ACTION_POWEROFF ? 'P' :
'r',
+ arg_dry,
!arg_no_wall,
m);
free(m);
return 0;
}
-static void pager_open(void) {
- int fd[2];
- const char *pager;
- pid_t parent_pid;
-
- if (pager_pid > 0)
- return;
-
- if (!on_tty() || arg_no_pager)
- return;
-
- if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER")))
- if (!*pager || streq(pager, "cat"))
- return;
-
- /* Determine and cache number of columns before we spawn the
- * pager so that we get the value from the actual tty */
- columns();
-
- if (pipe(fd) < 0) {
- log_error("Failed to create pager pipe: %m");
- return;
- }
-
- parent_pid = getpid();
-
- pager_pid = fork();
- if (pager_pid < 0) {
- log_error("Failed to fork pager: %m");
- close_pipe(fd);
- return;
- }
-
- /* In the child start the pager */
- if (pager_pid == 0) {
-
- dup2(fd[0], STDIN_FILENO);
- close_pipe(fd);
-
- setenv("LESS", "FRSX", 0);
-
- /* Make sure the pager goes away when the parent dies */
- if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
- _exit(EXIT_FAILURE);
-
- /* Check whether our parent died before we were able
- * to set the death signal */
- if (getppid() != parent_pid)
- _exit(EXIT_SUCCESS);
-
- if (pager) {
- execlp(pager, pager, NULL);
- execl("/bin/sh", "sh", "-c", pager, NULL);
- } else {
- /* Debian's alternatives command for pagers is
- * called 'pager'. Note that we do not call
- * sensible-pagers here, since that is just a
- * shell script that implements a logic that
- * is similar to this one anyway, but is
- * Debian-specific. */
- execlp("pager", "pager", NULL);
-
- execlp("less", "less", NULL);
- execlp("more", "more", NULL);
- }
-
- log_error("Unable to execute pager: %m");
- _exit(EXIT_FAILURE);
- }
-
- /* Return in the parent */
- if (dup2(fd[1], STDOUT_FILENO) < 0)
- log_error("Failed to duplicate pager pipe: %m");
-
- close_pipe(fd);
-}
-
-static void pager_close(void) {
- siginfo_t dummy;
-
- if (pager_pid <= 0)
- return;
-
- /* Inform pager that we are done */
- fclose(stdout);
- kill(pager_pid, SIGCONT);
- wait_for_terminate(pager_pid, &dummy);
- pager_pid = 0;
-}
-
static void agent_close(void) {
siginfo_t dummy;
break;
case ACTION_CANCEL_SHUTDOWN:
- r = send_shutdownd(0, 0, false, NULL);
+ r = send_shutdownd(0, 0, false, false, NULL);
break;
case ACTION_INVALID: