%install_service basic.target.wants sdb-prestart.service
%endif
+for i in reboot halt poweroff exit; do
+ D=%{buildroot}%{_unitdir}/systemd-${i}.service.wants
+ mkdir -p $D
+ ln -s ../deviced-request-shutdown@.service $D/deviced-request-shutdown@${i}.service
+done
+
mkdir -p %{buildroot}%{TZ_SYS_DUMPGEN}
install -m 775 scripts/dump_pmstate_log.sh %{buildroot}%{TZ_SYS_DUMPGEN}/dump_pmstate_log.sh
-# Assume power module is on (-DPOWER_MODULE=on)
-touch %{buildroot}%{_sbindir}/reboot
-touch %{buildroot}%{_sbindir}/halt
-touch %{buildroot}%{_sbindir}/poweroff
-touch %{buildroot}%{_sbindir}/shutdown
-
%post
# Assume power module is on (-DPOWER_MODULE=on)
update-alternatives --install %{_prefix}/lib/systemd/systemd-shutdown systemd-shutdown %{_prefix}/lib/systemd/deviced-shutdown 500
-update-alternatives --install %{_sbindir}/reboot reboot %{_sbindir}/deviced-power-command 500
-update-alternatives --install %{_sbindir}/halt halt %{_sbindir}/deviced-power-command 500
-update-alternatives --install %{_sbindir}/poweroff poweroff %{_sbindir}/deviced-power-command 500
-update-alternatives --install %{_sbindir}/shutdown shutdown %{_sbindir}/deviced-power-command 500
#memory type vconf key init
users_gid=$(getent group %{TZ_SYS_USER_GROUP} | cut -f3 -d':')
# Assume power module is on (-DPOWER_MODULE=on)
if [ $1 -eq 0 ] ; then
update-alternatives --remove systemd-shutdown %{_prefix}/lib/systemd/deviced-shutdown
- update-alternatives --remove reboot %{_sbindir}/deviced-power-command
- update-alternatives --remove halt %{_sbindir}/deviced-power-command
- update-alternatives --remove poweroff %{_sbindir}/deviced-power-command
- update-alternatives --remove shutdown %{_sbindir}/deviced-power-command
systemctl daemon-reload
systemctl stop deviced.service
fi
+%posttrans
+update-alternatives --remove reboot %{_sbindir}/deviced-power-command || :
+update-alternatives --remove halt %{_sbindir}/deviced-power-command || :
+update-alternatives --remove poweroff %{_sbindir}/deviced-power-command || :
+update-alternatives --remove shutdown %{_sbindir}/deviced-power-command || :
+
%post -n libdeviced -p /sbin/ldconfig
%postun -n libdeviced -p /sbin/ldconfig
%{_unitdir}/mtp-responder-dummy.service
# Assume power module is on (-DPOWER_MODULE=on)
+%{_unitdir}/deviced-request-shutdown@.service
+%{_unitdir}/systemd-exit.service.wants/deviced-request-shutdown@exit.service
+%{_unitdir}/systemd-halt.service.wants/deviced-request-shutdown@halt.service
+%{_unitdir}/systemd-reboot.service.wants/deviced-request-shutdown@reboot.service
+%{_unitdir}/systemd-poweroff.service.wants/deviced-request-shutdown@poweroff.service
%{_prefix}/lib/systemd/deviced-shutdown
-%{_sbindir}/deviced-power-command
-%ghost %{_sbindir}/reboot
-%ghost %{_sbindir}/halt
-%ghost %{_sbindir}/poweroff
-%ghost %{_sbindir}/shutdown
+%{_sbindir}/deviced-request-shutdown
%files -n libdeviced
%manifest deviced.manifest
* limitations under the License.
*/
+#include <ctype.h>
+#include <errno.h>
#include <getopt.h>
-#include <libsyscommon/libgdbus.h>
#include <stdio.h>
#include <stdbool.h>
-#include <core/common.h>
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
-enum application {
- APP_UNKNOWN,
- APP_SHUTDOWN,
- APP_REBOOT,
- APP_HALT,
- APP_POWEROFF,
-};
-
-struct {
- const char *name;
- enum application application;
-} apps[] = {
- { .name = "reboot", .application = APP_REBOOT, },
- { .name = "halt", .application = APP_HALT, },
- { .name = "poweroff", .application = APP_POWEROFF, },
- { .name = "shutdown", .application = APP_SHUTDOWN, },
-};
-
-enum application parse_path(const char *name)
-{
- const char *base = strrchr(name, '/');
- base = base ? base + 1 : name;
- for (size_t i = 0; i < ARRAY_SIZE(apps); ++i) {
- const char *target = apps[i].name;
-
- /* NB: We only check if the prefix matches,
- * so that we can run "reboot" as, for example "reboot-custom". */
- if (strncmp(base, target, strlen(target)) == 0)
- return apps[i].application;
- }
- return APP_UNKNOWN;
-}
-
-/* NB: we are emulating different programs: the "shutdown" program, and the trio of "reboot", "halt"
- * and "poweroff". These two cases have different option sets, so they need separate parsing methods
- * and separate usage strings. */
-
-struct parse_result {
- enum {
- DO_NOTHING,
- SHOW_SHUTDOWN_PARSE_ERROR,
- SHOW_REBOOT_ET_AL_PARSE_ERROR,
- SHOW_SHUTDOWN_HELP,
- SHOW_REBOOT_ET_AL_HELP,
- DO_POWEROFF,
- DO_EXIT,
- DO_REBOOT,
- } operation;
-
- const char *extra_option;
-
- bool show_sync_warning;
- bool show_timings_warning;
- bool show_wall_warning;
- bool show_wtmp_warning;
-};
-
-struct parse_result parse_shutdown(int argc, char **argv) {
- enum {
- ACT_HALT,
- ACT_REBOOT,
- ACT_POWEROFF,
- } action = ACT_POWEROFF;
- bool will_do_nothing = false;
- bool show_timings_warning = false;
- bool show_wall_warning = false;
-
- for (;;) {
- switch (getopt_long(argc, argv, "HPrhkc", (struct option []) {
- { "help", no_argument, NULL, 0, },
- { "no-wall", no_argument, NULL, 1, },
- { "halt", no_argument, NULL, 'H', },
- { "poweroff", no_argument, NULL, 'P', },
- { "reboot", no_argument, NULL, 'r', },
- { NULL, 0, NULL, 0, },
- }, NULL)) {
- case -1:
- switch (argc - optind) {
- case 2:
- show_wall_warning = true;
- show_timings_warning = true;
- break;
-
- case 1:
- show_timings_warning = true;
- break;
-
- case 0:
- break;
-
- default:
- return (struct parse_result) { .operation = SHOW_SHUTDOWN_PARSE_ERROR, };
- }
-
- return (struct parse_result) {
- .operation = will_do_nothing ? DO_NOTHING
- : action == ACT_REBOOT ? DO_REBOOT
- : action == ACT_HALT ? DO_EXIT // don't ask difficult questions like "why not DO_HALT"
- : DO_POWEROFF,
- .extra_option = NULL,
- .show_sync_warning = false,
- .show_timings_warning = show_timings_warning,
- .show_wall_warning = show_wall_warning,
- .show_wtmp_warning = false,
- };
-
- case 0:
- return (struct parse_result) { .operation = SHOW_SHUTDOWN_HELP, };
-
- case 1:
- show_wall_warning = true;
- break;
-
- case 'H':
- action = ACT_HALT;
- break;
-
- case 'P':
- action = ACT_POWEROFF;
- break;
-
- case 'r':
- action = ACT_REBOOT;
- break;
-
- case 'h':
- if (action == ACT_REBOOT)
- action = ACT_POWEROFF;
- break;
-
- case 'k':
- will_do_nothing = true;
- show_wall_warning = true;
- break;
-
- case 'c':
- will_do_nothing = true;
- show_timings_warning = true;
- break;
-
- case '?':
- return (struct parse_result) { .operation = SHOW_SHUTDOWN_PARSE_ERROR, };
-
- default:
- assert(false);
- }
- }
-}
-
-struct parse_result parse_reboot_et_al(enum application application, int argc, char **argv) {
- enum {
- ACT_HALT,
- ACT_REBOOT,
- ACT_POWEROFF,
- } action;
- switch (application) {
- case APP_REBOOT:
- action = ACT_REBOOT;
- break;
-
- case APP_HALT:
- action = ACT_HALT;
- break;
-
- case APP_POWEROFF:
- action = ACT_POWEROFF;
- break;
-
- default:
- assert(false);
- }
-
- bool will_do_nothing = false;
- bool show_sync_warning = false;
- bool show_timings_warning = false;
- bool show_wall_warning = false;
- bool show_wtmp_warning = false;
- char *extra_option = NULL;
-
- for (;;) {
- switch (getopt_long(argc, argv, "-pfwdn", (struct option []) {
- { "help", no_argument, NULL, 0, },
- /* 1 reserved for options not in -foo format */
- { "halt", no_argument, NULL, 2, },
- { "reboot", no_argument, NULL, 3, },
- { "no-wall", no_argument, NULL, 4, },
- { "poweroff", no_argument, NULL, 'p', },
- { "force", no_argument, NULL, 'f', },
- { "wtmp-only", no_argument, NULL, 'w', },
- { "no-wtmp", no_argument, NULL, 'd', },
- { "no-sync", no_argument, NULL, 'n', },
- { NULL, 0, NULL, 0, },
- }, NULL)) {
- case -1:
- if (optind != argc)
- return (struct parse_result) { .operation = SHOW_REBOOT_ET_AL_PARSE_ERROR, };
-
- return (struct parse_result) {
- .operation = will_do_nothing ? DO_NOTHING
- : action == ACT_REBOOT ? DO_REBOOT
- : action == ACT_HALT ? DO_EXIT
- : DO_POWEROFF,
- .extra_option = extra_option,
- .show_sync_warning = show_sync_warning,
- .show_timings_warning = show_timings_warning,
- .show_wall_warning = show_wall_warning,
- .show_wtmp_warning = show_wtmp_warning,
- };
-
- case 0:
- return (struct parse_result) { .operation = SHOW_REBOOT_ET_AL_HELP, };
-
- case 1:
- if (extra_option)
- return (struct parse_result) { .operation = SHOW_REBOOT_ET_AL_PARSE_ERROR, };
- extra_option = optarg;
- break;
-
- case 2:
- action = ACT_HALT;
- break;
-
- case 3:
- action = ACT_REBOOT;
- break;
-
- case 4:
- show_wall_warning = true;
- break;
-
- case 'p':
- action = ACT_POWEROFF;
- break;
-
- case 'f':
- show_timings_warning = false;
- break;
-
- case 'w':
- will_do_nothing = true;
- show_wtmp_warning = true;
- break;
-
- case 'd':
- show_wtmp_warning = true;
- break;
-
- case 'n':
- show_sync_warning = true;
- break;
-
- case '?':
- return (struct parse_result) { .operation = SHOW_REBOOT_ET_AL_PARSE_ERROR, };
-
- default:
- assert(false);
- }
- }
-}
+#include <core/common.h>
+#include <libsyscommon/libgdbus.h>
-int call_deviced_poweroff(const char *type, const char *extra_option, const char *message)
+int call_deviced_poweroff(const char *type, const char *extra_option)
{
int ret_dbus = extra_option
? gdbus_call_sync_with_reply_int(DEVICED_BUS_NAME, DEVICED_PATH_POWEROFF, DEVICED_INTERFACE_POWEROFF, "PowerOffWithOption", g_variant_new("(ss)", type, extra_option), NULL)
fprintf(stderr, "Error: %d", ret_dbus);
return EXIT_FAILURE;
}
-
- fprintf(stderr, "%s", message);
- for (;;)
- pause();
return EXIT_SUCCESS;
}
int main(int argc, char **argv)
{
- enum application application = parse_path(argv[0]);
- struct parse_result parse_result;
- switch (application) {
- case APP_UNKNOWN:
- fprintf(stderr, "This program can only be used as a symlink to 'reboot', 'halt', 'poweroff' or 'shutdown'.\n");
- return EXIT_FAILURE;
+ const char *option = argc > 2 ? argv[2] : NULL;
+ const char *action = argc > 1 ? argv[1] : NULL;
+ char buf[REBOOT_PARAM_MAXLEN] = {0, };
- case APP_SHUTDOWN:
- parse_result = parse_shutdown(argc, argv);
- break;
-
- case APP_REBOOT:
- case APP_HALT:
- case APP_POWEROFF:
- parse_result = parse_reboot_et_al(application, argc, argv);
- break;
-
- default:
- // This shouldn't be needed, but GCC complains otherwise.
- assert(false);
+ if (!action) {
+ fprintf(stderr, "Usage: %s {action} [extra]\n", argv[0]);
return EXIT_FAILURE;
}
- if (parse_result.show_sync_warning)
- fprintf(stderr, "Warning: Tizen always syncs, sync options ignored.\n");
- if (parse_result.show_timings_warning)
- fprintf(stderr, "Warning: %s doesn't take care of delayed and pending operations on Tizen.\n", argv[0]);
- if (parse_result.show_wall_warning)
- fprintf(stderr, "Warning: %s doesn't take care of wall messages on Tizen.\n", argv[0]);
- if (parse_result.show_wtmp_warning)
- fprintf(stderr, "Warning: %s doesn't take care of wtmp entries on Tizen.\n", argv[0]);
-
- switch (parse_result.operation) {
- case DO_NOTHING:
- return EXIT_SUCCESS;
-
- case SHOW_SHUTDOWN_HELP:
- case SHOW_SHUTDOWN_PARSE_ERROR:
- fprintf(stderr, "Usage: %s [-HPrh]\n", argv[0]);
- return parse_result.operation == SHOW_SHUTDOWN_HELP ? EXIT_SUCCESS : EXIT_FAILURE;
-
- case SHOW_REBOOT_ET_AL_HELP:
- case SHOW_REBOOT_ET_AL_PARSE_ERROR:
- fprintf(stderr, "Usage: %s [-p] [--halt|--poweroff|--reboot] [extra]\n", argv[0]); // FIXME: do we say something about the extras? if yes, do we mention deviced, the configs etc?
- return parse_result.operation == SHOW_REBOOT_ET_AL_HELP ? EXIT_SUCCESS : EXIT_FAILURE;
-
- case DO_POWEROFF:
- return call_deviced_poweroff("poweroff", parse_result.extra_option, "Shutting down...\n"); // should be "Powering off" really, "shutting down" is the generic term also encompassing halt/reboot >_>
- case DO_EXIT:
- return call_deviced_poweroff("exit", parse_result.extra_option, "Shutting down...\n"); // ditto: exit ultimately boils down to poweroff, too
- case DO_REBOOT:
- return call_deviced_poweroff("reboot", parse_result.extra_option, "Rebooting...\n");
- }
+ if (!option && get_systemd_reboot_param(buf, sizeof buf) > 0)
+ option = buf;
- assert(false); // unreachable
- return EXIT_FAILURE;
+ return call_deviced_poweroff(action, option);
}