X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogin%2Feloginctl.c;h=451b5b76f7db17c34d5a214471a50295248f7bd5;hp=9e40e87ad22ffe12ac5a9069b6ed5a21fabf86d8;hb=f3f6ae7c983865ea37e8ddfbd676586e55280f1e;hpb=687aa1e7968dcd99a38e165b5386e466491ba7b0 diff --git a/src/login/eloginctl.c b/src/login/eloginctl.c index 9e40e87ad..451b5b76f 100644 --- a/src/login/eloginctl.c +++ b/src/login/eloginctl.c @@ -65,6 +65,9 @@ static enum elogind_action verb_to_action(const char *verb) { return _ACTION_INVALID; } +/* Original: + * systemctl/systemctl.c:3292:logind_check_inhibitors() + */ static int check_inhibitors(sd_bus* bus, enum elogind_action a) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_strv_free_ char **sessions = NULL; @@ -151,7 +154,7 @@ static int check_inhibitors(sd_bus* bus, enum elogind_action a) { if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user")) continue; - if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty"))) + if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "tty")) continue; sd_session_get_tty(*s, &tty); @@ -166,16 +169,21 @@ static int check_inhibitors(sd_bus* bus, enum elogind_action a) { if (c <= 0) return 0; - log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'loginctl -i %s'.", + log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'loginctl %s -i'.", action_table[a].verb); return -EPERM; } +/* Original: + * systemctl/systemctl.c:8410:logind_cancel_shutdown() + */ int elogind_cancel_shutdown(sd_bus *bus) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; + (void) elogind_set_wall_message(bus, NULL); + r = sd_bus_call_method( bus, "org.freedesktop.login1", @@ -185,72 +193,83 @@ int elogind_cancel_shutdown(sd_bus *bus) { &error, NULL, NULL); if (r < 0) - return log_warning_errno(r, "Failed to talk to elogind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r)); + return log_warning_errno(r, + "Failed to talk to elogind, shutdown hasn't been cancelled: %s", + bus_error_message(&error, r)); return 0; } +/* Only a little helper for cleaning up elogind specific extra stuff. */ void elogind_cleanup(void) { polkit_agent_close(); strv_free(arg_wall); } +/* Littel debug log helper, helps debugging systemctl comands we mimic. */ static void elogind_log_special(enum elogind_action a) { +#ifdef ENABLE_DEBUG_ELOGIND switch (a) { case ACTION_HALT: log_struct(LOG_INFO, LOG_MESSAGE("Halt action called."), - LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), + "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR, NULL); break; case ACTION_POWEROFF: log_struct(LOG_INFO, LOG_MESSAGE("Poweroff action called."), - LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), + "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR, NULL); break; case ACTION_REBOOT: log_struct(LOG_INFO, LOG_MESSAGE("Reboot action called."), - LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), + "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR, NULL); break; case ACTION_KEXEC: log_struct(LOG_INFO, LOG_MESSAGE("KExec action called."), - LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), + "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR, NULL); break; case ACTION_SUSPEND: log_struct(LOG_INFO, LOG_MESSAGE("Suspend action called."), - LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START), + "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR, NULL); break; case ACTION_HIBERNATE: log_struct(LOG_INFO, LOG_MESSAGE("Hibernate action called."), - LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START), + "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR, NULL); + break; case ACTION_HYBRID_SLEEP: log_struct(LOG_INFO, LOG_MESSAGE("Hybrid-Sleep action called."), - LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START), + "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR, NULL); + break; case ACTION_CANCEL_SHUTDOWN: log_struct(LOG_INFO, LOG_MESSAGE("Cancel Shutdown called."), - LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), + "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR, NULL); break; default: break; } +#endif // ENABLE_DEBUG_ELOGIND } +/* Original: + * systemctl/systemctl.c:3229:logind_reboot() + */ static int elogind_reboot(sd_bus *bus, enum elogind_action a) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - const char *method = NULL; + const char *method = NULL, *description = NULL; int r; static const char *table[_ACTION_MAX] = { [ACTION_REBOOT] = "The system is going down for reboot NOW!", @@ -260,41 +279,41 @@ static int elogind_reboot(sd_bus *bus, enum elogind_action a) { if (!bus) return -EIO; - polkit_agent_open_if_enabled(); - switch (a) { - case ACTION_POWEROFF: - method = "PowerOff"; - break; - case ACTION_REBOOT: method = "Reboot"; + description = "reboot system"; + break; + + case ACTION_POWEROFF: + method = "PowerOff"; + description = "power off system"; break; case ACTION_SUSPEND: method = "Suspend"; + description = "suspend system"; break; case ACTION_HIBERNATE: method = "Hibernate"; + description = "hibernate system"; break; case ACTION_HYBRID_SLEEP: method = "HybridSleep"; + description = "put system into hybrid sleep"; break; default: return -EINVAL; } - r = elogind_set_wall_message(bus, table[a]); + polkit_agent_open_if_enabled(); - if (r < 0) { - log_warning_errno(r, "Failed to set wall message, ignoring: %s", - bus_error_message(&error, r)); - sd_bus_error_free(&error); - } + if ( IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT) ) + (void) elogind_set_wall_message(bus, table[a]); /* Now call elogind itself to request the operation */ r = sd_bus_call_method( @@ -305,46 +324,45 @@ static int elogind_reboot(sd_bus *bus, enum elogind_action a) { method, &error, NULL, - "b", - arg_ask_password); + "b", arg_ask_password); if (r < 0) - log_error("Failed to execute operation: %s", bus_error_message(&error, r)); + return log_error_errno(r, "Failed to %s via elogind: %s", + description, + bus_error_message(&error, r)); - return r; + return 0; } +/* Original: + * systemctl/systemctl.c:8281:logind_schedule_shutdown() + */ static int elogind_schedule_shutdown(sd_bus *bus, enum elogind_action a) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - const char *method = NULL; + char date[FORMAT_TIMESTAMP_MAX]; + const char *action; int r; if (!bus) return -EIO; - polkit_agent_open_if_enabled(); - switch (a) { - + case ACTION_HALT: + action = "halt"; + break; case ACTION_POWEROFF: - method = "poweroff"; + action = "poweroff"; break; - - case ACTION_REBOOT: - method = "reboot"; + case ACTION_KEXEC: + action = "kexec"; break; - + case ACTION_REBOOT: default: - return -EINVAL; + action = "reboot"; + break; } - r = elogind_set_wall_message(bus, NULL); - - if (r < 0) { - log_warning_errno(r, "Failed to set wall message, ignoring: %s", - bus_error_message(&error, r)); - sd_bus_error_free(&error); - } + (void) elogind_set_wall_message(bus, NULL); r = sd_bus_call_method( bus, @@ -355,15 +373,24 @@ static int elogind_schedule_shutdown(sd_bus *bus, enum elogind_action a) { &error, NULL, "st", - method, + action, arg_when); if (r < 0) - log_error("Failed to execute operation: %s", bus_error_message(&error, r)); + return log_warning_errno(r, + "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", + bus_error_message(&error, r)); - return r; + log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", + format_timestamp(date, sizeof(date), arg_when)); + + return 0; } +/* Original: + * systemctl/systemctl.c:3193:logind_set_wall_message() + * (Tweaked to allow an extra message to be appended.) + */ static int elogind_set_wall_message(sd_bus* bus, const char* msg) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *m = NULL; @@ -394,6 +421,9 @@ static int elogind_set_wall_message(sd_bus* bus, const char* msg) { return 0; } +/* Original: + * systemctl/systemctl.c:7743:parse_shutdown_time_spec() + */ static int parse_shutdown_time_spec(const char *t, usec_t *_u) { assert(t); assert(_u); @@ -443,6 +473,9 @@ static int parse_shutdown_time_spec(const char *t, usec_t *_u) { return 0; } +/* Original: + * systemctl/systemctl.c:270:polkit_agent_open_if_enabled() + */ void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ @@ -456,6 +489,10 @@ void polkit_agent_open_if_enabled(void) { polkit_agent_open(); } +/* Original: + * systemctl/systemctl.c:3482:start_special() + * However, this elogind variant is very different from the original. + */ int start_special(int argc, char *argv[], void *userdata) { sd_bus *bus = userdata; enum elogind_action a; @@ -468,6 +505,42 @@ int start_special(int argc, char *argv[], void *userdata) { elogind_log_special(a); + /* For poweroff and reboot, some extra checks are performed: */ + if ( IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT) ) { + + /* No power off actions in chroot environments */ + if ( running_in_chroot() > 0 ) { + log_info("Running in chroot, ignoring request."); + return 0; + } + + /* Check time argument */ + if ( (argc > 1) && (ACTION_CANCEL_SHUTDOWN != arg_action)) { + r = parse_shutdown_time_spec(argv[1], &arg_when); + if (r < 0) { + log_error("Failed to parse time specification: %s", argv[optind]); + return r; + } + } + + /* The optional user wall message must be set */ + if ( (argc > 1) + && ( (arg_action == ACTION_CANCEL_SHUTDOWN) + || (0 == arg_when) ) ) + /* No time argument for shutdown cancel, or no + * time argument given. */ + wall = argv + 1; + else if (argc > 2) + /* We skip the time argument */ + wall = argv + 2; + + if (wall) { + arg_wall = strv_copy(wall); + if (!arg_wall) + return log_oom(); + } + } + /* Switch to cancel shutdown, if a shutdown action was requested, and the option to cancel it was set: */ if ( IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT) @@ -478,40 +551,6 @@ int start_special(int argc, char *argv[], void *userdata) { if (r < 0) return r; - /* No power off actions in chroot environments */ - if ((a == ACTION_POWEROFF || - a == ACTION_REBOOT) && - (running_in_chroot() > 0) ) { - log_info("Running in chroot, ignoring request."); - return 0; - } - - /* Check time arguments */ - if ( IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT) - && (argc > 1) - && (arg_action != ACTION_CANCEL_SHUTDOWN) ) { - r = parse_shutdown_time_spec(argv[1], &arg_when); - if (r < 0) { - log_error("Failed to parse time specification: %s", argv[optind]); - return r; - } - } else - arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE; - - /* The optional user wall message must be set */ - if ((argc > 1) && (arg_action == ACTION_CANCEL_SHUTDOWN) ) - /* No time argument for shutdown cancel */ - wall = argv + 1; - else if (argc > 2) - /* We skip the time argument */ - wall = argv + 2; - - if (wall) { - arg_wall = strv_copy(wall); - if (!arg_wall) - return log_oom(); - } - /* Perform requested action */ if (IN_SET(a, ACTION_POWEROFF,