source: mainline/uspace/app/shutdown/shutdown.c

Last change on this file was f35749e, checked in by Jiri Svoboda <jiri@…>, 4 months ago

System restart via shutdown -r

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup lprint
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Shut the system down
36 *
37 */
38
39#include <fibril_synch.h>
40#include <nchoice.h>
41#include <shutdown.h>
42#include <stdio.h>
43#include <stdbool.h>
44#include <str.h>
45#include <system.h>
46#include "shutdown.h"
47
48#define NAME "shutdown"
49
50static void syntax_print(void);
51
52static sd_action_t action;
53
54static void sd_shutdown_complete(void *);
55static void sd_shutdown_failed(void *);
56
57static system_cb_t sd_system_cb = {
58 .shutdown_complete = sd_shutdown_complete,
59 .shutdown_failed = sd_shutdown_failed
60};
61
62/** System shutdown complete.
63 *
64 * @param arg Argument (shutdown_t *)
65 */
66static void sd_shutdown_complete(void *arg)
67{
68 shutdown_t *shutdown = (shutdown_t *)arg;
69
70 fibril_mutex_lock(&shutdown->lock);
71 shutdown->stopped = true;
72 shutdown->failed = false;
73 fibril_condvar_broadcast(&shutdown->cv);
74 fibril_mutex_unlock(&shutdown->lock);
75}
76
77/** System shutdown failed.
78 *
79 * @param arg Argument (not used)
80 */
81static void sd_shutdown_failed(void *arg)
82{
83 shutdown_t *shutdown = (shutdown_t *)arg;
84
85 fibril_mutex_lock(&shutdown->lock);
86 shutdown->stopped = true;
87 shutdown->failed = true;
88 fibril_condvar_broadcast(&shutdown->cv);
89 fibril_mutex_unlock(&shutdown->lock);
90}
91
92/** Interactively choose the shutdown action to perform
93 *
94 * @return EOK on success or an error code
95 */
96static errno_t choose_action(void)
97{
98 errno_t rc;
99 nchoice_t *nchoice = NULL;
100 void *choice;
101
102 rc = nchoice_create(&nchoice);
103 if (rc != EOK) {
104 printf(NAME ": Out of memory.\n");
105 goto error;
106 }
107
108 rc = nchoice_set_prompt(nchoice, "Do you want to shut the system down? "
109 "Select action:");
110 if (rc != EOK) {
111 printf(NAME ": Out of memory.\n");
112 goto error;
113 }
114
115 rc = nchoice_add(nchoice, "Power off", (void *)(uintptr_t)sd_poweroff,
116 0);
117 if (rc != EOK) {
118 printf(NAME ": Out of memory.\n");
119 goto error;
120 }
121
122 rc = nchoice_add(nchoice, "Restart", (void *)(uintptr_t)sd_restart,
123 0);
124 if (rc != EOK) {
125 printf(NAME ": Out of memory.\n");
126 goto error;
127 }
128
129 rc = nchoice_add(nchoice, "Cancel", (void *)(uintptr_t)sd_cancel,
130 ncf_default);
131 if (rc != EOK) {
132 printf(NAME ": Out of memory.\n");
133 goto error;
134 }
135
136 rc = nchoice_get(nchoice, &choice);
137 if (rc != EOK) {
138 if (rc != ENOENT)
139 printf(NAME ": Error getting user choice.\n");
140 goto error;
141 }
142
143 action = (sd_action_t)choice;
144 nchoice_destroy(nchoice);
145 return EOK;
146error:
147 if (nchoice != NULL)
148 nchoice_destroy(nchoice);
149 return rc;
150}
151
152int main(int argc, char **argv)
153{
154 errno_t rc;
155 system_t *system = NULL;
156 shutdown_t shutdown;
157
158 --argc;
159 ++argv;
160
161 while (*argv != NULL && *argv[0] == '-') {
162 if (str_cmp(*argv, "-p") == 0) {
163 --argc;
164 ++argv;
165 action = sd_poweroff;
166 continue;
167 } else if (str_cmp(*argv, "-r") == 0) {
168 --argc;
169 ++argv;
170 action = sd_restart;
171 continue;
172 }
173
174 printf(NAME ": Error, invalid option.\n");
175 syntax_print();
176 return 1;
177 }
178
179 if (argc >= 1) {
180 printf(NAME ": Error, unexpected argument.\n");
181 syntax_print();
182 return 1;
183 }
184
185 if (action == 0)
186 choose_action();
187
188 if (action == sd_cancel)
189 return 0;
190
191 fibril_mutex_initialize(&shutdown.lock);
192 fibril_condvar_initialize(&shutdown.cv);
193 shutdown.stopped = false;
194 shutdown.failed = false;
195
196 rc = system_open(SYSTEM_DEFAULT, &sd_system_cb, &shutdown, &system);
197 if (rc != EOK) {
198 printf(NAME ": Failed opening system control service.\n");
199 return 1;
200 }
201
202 switch (action) {
203 case sd_poweroff:
204 rc = system_poweroff(system);
205 break;
206 case sd_restart:
207 rc = system_restart(system);
208 break;
209 case sd_cancel:
210 assert(false);
211 rc = EINVAL;
212 break;
213 }
214
215 if (rc != EOK) {
216 system_close(system);
217 printf(NAME ": Failed requesting system shutdown.\n");
218 return 1;
219 }
220
221 fibril_mutex_lock(&shutdown.lock);
222 printf("The system is shutting down...\n");
223 while (!shutdown.stopped)
224 fibril_condvar_wait(&shutdown.cv, &shutdown.lock);
225
226 if (shutdown.failed) {
227 printf("Shutdown failed.\n");
228 system_close(system);
229 return 1;
230 }
231
232 printf("Shutdown complete. It is now safe to remove power.\n");
233
234 /* Sleep forever */
235 while (true)
236 fibril_condvar_wait(&shutdown.cv, &shutdown.lock);
237
238 fibril_mutex_unlock(&shutdown.lock);
239
240 system_close(system);
241 return 0;
242}
243
244/** Print syntax help. */
245static void syntax_print(void)
246{
247 printf("syntax:\n"
248 "\tshutdown [<options>]\n"
249 "options:\n"
250 "\t-p Power off\n"
251 "\t-r Restart off\n");
252}
253
254/**
255 * @}
256 */
Note: See TracBrowser for help on using the repository browser.