#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/socket.h>
#include <dbus/dbus.h>
return 0;
}
+static int bus_check_peercred(DBusConnection *c) {
+ int fd;
+ struct ucred ucred;
+ socklen_t l;
+
+ assert(c);
+
+ assert_se(dbus_connection_get_unix_fd(c, &fd));
+
+ l = sizeof(struct ucred);
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
+ log_error("SO_PEERCRED failed: %m");
+ return -errno;
+ }
+
+ if (l != sizeof(struct ucred)) {
+ log_error("SO_PEERCRED returned wrong size.");
+ return -E2BIG;
+ }
+
+ if (ucred.uid != 0)
+ return -EPERM;
+
+ return 1;
+}
+
static int columns(void) {
static int parsed_columns = 0;
const char *e;
static int systemctl_help(void) {
- printf("%s [options]\n\n"
- "Send control commands to the init daemon.\n\n"
+ printf("%s [OPTIONS...] {COMMAND} ...\n\n"
+ "Send control commands to the systemd manager.\n\n"
" -h --help Show this help\n"
" -t --type=TYPE List only units of a particular type\n"
" -a --all Show all units, including dead ones\n"
" --system Connect to system bus\n"
" --session Connect to session bus\n"
" --block Wait until operation finished\n"
- " --no-wall Don't send wall message before reboot/halt/power-off\n\n"
+ " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
"Commands:\n"
" list-units List units\n"
" list-jobs List jobs\n"
" monitor Monitor unit/job changes\n"
" dump Dump server status\n"
" snapshot [NAME] Create a snapshot\n"
- " daemon-reload Reload init daemon configuration\n"
- " daemon-reexecute Reexecute init daemon\n"
- " daemon-exit Ask the init daemon to quit\n"
+ " daemon-reload Reload systemd manager configuration\n"
+ " daemon-reexec Reexecute systemd manager\n"
+ " daemon-exit Ask the systemd manager to quit\n"
" show-environment Dump environment\n"
" set-environment [NAME=VALUE...] Set one or more environment variables\n"
" unset-environment [NAME...] Unset one or more environment variables\n"
" halt Shut down and halt the system\n"
+ " poweroff Shut down and power-off the system\n"
" reboot Shut down and reboot the system\n"
- " poweroff Shut down and power off the system\n"
" default Enter default mode\n"
" rescue Enter rescue mode\n"
" emergency Enter emergency mode\n",
static int halt_help(void) {
- printf("%s [options]\n\n"
+ printf("%s [OPTIONS...]\n\n"
"%s the system.\n\n"
" --help Show this help\n"
" --halt Halt the machine\n"
" -p --poweroff Switch off the machine\n"
" --reboot Reboot the machine\n"
- " -f --force Force immediate reboot/halt/power-off\n"
- " -w --wtmp-only Don't reboot/halt/power-off, just write wtmp record\n"
+ " -f --force Force immediate halt/power-off/reboot\n"
+ " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
" -d --no-wtmp Don't write wtmp record\n"
- " -n --no-sync Don't sync before reboot/halt/power-off\n"
- " --no-wall Don't send wall message before reboot/halt/power-off\n",
+ " -n --no-sync Don't sync before halt/power-off/reboot\n"
+ " --no-wall Don't send wall message before halt/power-off/reboot\n",
program_invocation_short_name,
arg_action == ACTION_REBOOT ? "Reboot" :
arg_action == ACTION_POWEROFF ? "Power off" :
static int shutdown_help(void) {
- printf("%s [options] [now] [WALL...]\n\n"
+ printf("%s [OPTIONS...] [now] [WALL...]\n\n"
"Shut down the system.\n\n"
" --help Show this help\n"
" -H --halt Halt the machine\n"
" -P --poweroff Power-off the machine\n"
" -r --reboot Reboot the machine\n"
" -h Equivalent to --poweroff, overriden by --halt\n"
- " -k Don't reboot/halt/power-off, just send warnings\n"
- " --no-wall Don't send wall message before reboot/halt/power-off\n",
+ " -k Don't halt/power-off/reboot, just send warnings\n"
+ " --no-wall Don't send wall message before halt/power-off/reboot\n",
program_invocation_short_name);
return 0;
static int telinit_help(void) {
- printf("%s [options]\n\n"
+ printf("%s [OPTIONS...] {COMMAND}\n\n"
"Send control commands to the init daemon.\n\n"
" --help Show this help\n"
- " --no-wall Don't send wall message before reboot/halt/power-off\n\n"
+ " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
"Commands:\n"
" 0 Power-off the machine\n"
" 6 Reboot the machine\n"
static int runlevel_help(void) {
- printf("%s [options]\n\n"
+ printf("%s [OPTIONS...]\n\n"
"Prints the previous and current runlevel of the init system.\n\n"
" --help Show this help\n",
program_invocation_short_name);
optind = argc;
return 1;
-
}
static int telinit_parse_argv(int argc, char *argv[]) {
}
if (optind >= argc) {
- log_error("Argument missing.");
+ telinit_help();
return -EINVAL;
}
return table[arg_action];
}
-static int talk_upstart(DBusConnection *bus) {
+static int talk_upstart(void) {
DBusMessage *m = NULL, *reply = NULL;
DBusError error;
int previous, rl, r;
const char *emit = "runlevel";
dbus_bool_t b_false = FALSE;
DBusMessageIter iter, sub;
+ DBusConnection *bus;
dbus_error_init(&error);
if (utmp_get_runlevel(&previous, NULL) < 0)
previous = 'N';
+ if (!(bus = dbus_connection_open("unix:abstract=/com/ubuntu/upstart", &error))) {
+ if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
+ r = 0;
+ goto finish;
+ }
+
+ log_error("Failed to connect to Upstart bus: %s", error.message);
+ r = -EIO;
+ goto finish;
+ }
+
+ if ((r = bus_check_peercred(bus)) < 0) {
+ log_error("Failed to verify owner of bus.");
+ goto finish;
+ }
+
if (!(m = dbus_message_new_method_call(
"com.ubuntu.Upstart",
"/com/ubuntu/Upstart",
"EmitEvent"))) {
log_error("Could not allocate message.");
- return -ENOMEM;
+ r = -ENOMEM;
+ goto finish;
}
dbus_message_iter_init_append(m, &iter);
if (reply)
dbus_message_unref(reply);
+ if (bus)
+ dbus_connection_unref(bus);
+
dbus_error_free(&error);
return r;
/* Hmm, talking to systemd via D-Bus didn't work. Then
* let's try to talk to Upstart via D-Bus. */
- if ((r = talk_upstart(bus)) > 0)
+ if ((r = talk_upstart()) > 0)
return 0;
}
goto finish;
}
- if ((bus = dbus_bus_get(arg_session ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, &error)))
+ /* If we are root, then let's not go via the bus */
+ if (geteuid() == 0 && !arg_session) {
+ bus = dbus_connection_open("unix:abstract=/org/freedesktop/systemd1/private", &error);
+
+ if (bus && bus_check_peercred(bus) < 0) {
+ log_error("Failed to verify owner of bus.");
+ goto finish;
+ }
+ } else
+ bus = dbus_bus_get(arg_session ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, &error);
+
+ if (bus)
dbus_connection_set_exit_on_disconnect(bus, FALSE);
switch (arg_action) {