xref: /haiku/src/bin/shutdown.cpp (revision 24159a0c7d6d6dcba9f2a0c1a7c08d2c8167f21b)
1 /*
2  * Copyright 2002-2005, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Francois Revol (mmu_man@users.sf.net)
7  */
8 
9 /*!	Shuts down the system, either halting or rebooting. */
10 
11 #include <syscalls.h>
12 
13 #include <OS.h>
14 #include <Roster.h>
15 #include <RosterPrivate.h>
16 
17 #include <signal.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <ctype.h>
23 
24 uint32 gTimeToSleep = 0;
25 bool gReboot = false;
26 
27 // we get here when shutdown is cancelled.
28 // then sleep() returns
29 
30 void
31 handle_usr1(int sig)
32 {
33 	while (0);
34 }
35 
36 
37 bool
38 parseTime(char *arg, char *argv, int32 *_i)
39 {
40 	char *unit;
41 
42 	if (isdigit(arg[0])) {
43 		gTimeToSleep = strtoul(arg, &unit, 10);
44 	} else if (argv && isdigit(argv[0])) {
45 		(*_i)++;
46 		gTimeToSleep = strtoul(argv, &unit, 10);
47 	} else
48 		return false;
49 
50 	if (unit[0] == '\0' || !strcmp(unit, "s"))
51 		return true;
52 	if (!strcmp(unit, "m")) {
53 		gTimeToSleep *= 60;
54 		return true;
55 	}
56 
57 	return false;
58 }
59 
60 
61 void
62 usage(const char *arg0)
63 {
64 	const char *program = strrchr(arg0, '/');
65 	if (program == NULL)
66 		program = arg0;
67 	else
68 		program++;
69 
70 	fprintf(stderr, "usage: %s [-rqca] [-d time]\n"
71 		"\t-r reboot,\n"
72 		"\t-q quick shutdown (don't broadcast apps),\n"
73 		"\t-a ask user to confirm the shutdown (ignored when -q is given),\n"
74 		"\t-c cancel a running shutdown,\n"
75 		"\t-s run shutdown synchronously (only returns if shutdown is cancelled)\n"
76 		"\t-d delay shutdown by <time> seconds.\n", program);
77 	exit(1);
78 }
79 
80 
81 int
82 main(int argc, char **argv)
83 {
84 	bool askUser = false;
85 	bool quick = false;
86 	bool async = true;
87 
88 	for (int32 i = 1; i < argc; i++) {
89 		char *arg = argv[i];
90 		if (arg[0] == '-') {
91 			if (!isalpha(arg[1]))
92 				usage(argv[0]);
93 
94 			while (arg && isalpha((++arg)[0])) {
95 				switch (arg[0]) {
96 					case 'a':
97 						askUser = true;
98 						break;
99 					case 'q':
100 						quick = true;
101 						break;
102 					case 'r':
103 						gReboot = true;
104 						break;
105 					case 's':
106 						async = false;
107 						break;
108 					case 'c':
109 					{
110 						// find all running shutdown command and signal its shutdown thread
111 
112 						thread_info threadInfo;
113 						get_thread_info(find_thread(NULL), &threadInfo);
114 
115 						team_id thisTeam = threadInfo.team;
116 
117 						int32 team_cookie = 0;
118 						team_info teamInfo;
119 						while (get_next_team_info(&team_cookie, &teamInfo) == B_OK) {
120 							if (strstr(teamInfo.args, "shutdown") != NULL && teamInfo.team != thisTeam) {
121 								int32 thread_cookie = 0;
122 								while (get_next_thread_info(teamInfo.team, &thread_cookie, &threadInfo) == B_OK) {
123 									if (!strcmp(threadInfo.name, "shutdown"))
124 										kill(threadInfo.thread, SIGUSR1);
125 								}
126 							}
127 						}
128 						exit(0);
129 						break;
130 					}
131 					case 'd':
132 						if (parseTime(arg + 1, argv[i + 1], &i)) {
133 							arg = NULL;
134 							break;
135 						}
136 						// supposed to fall through
137 
138 					default:
139 						usage(argv[0]);
140 				}
141 			}
142 		} else
143 			usage(argv[0]);
144 	}
145 
146 	if (gTimeToSleep > 0) {
147 		int32 left;
148 
149 		signal(SIGUSR1, handle_usr1);
150 
151 		printf("Delaying %s by %lu seconds...\n", gReboot ? "reboot" : "shutdown", gTimeToSleep);
152 
153 		left = sleep(gTimeToSleep);
154 
155 		if (left > 0) {
156 			fprintf(stderr, "Shutdown cancelled.\n");
157 			exit(0);
158 		}
159 	}
160 
161 	if (quick) {
162 		#ifdef __HAIKU__
163 		_kern_shutdown(gReboot);
164 		#endif // __HAIKU__
165 		fprintf(stderr, "Shutdown failed!\n");
166 		return 2;
167 	} else {
168 		BRoster roster;
169 		BRoster::Private rosterPrivate(roster);
170 		status_t error = rosterPrivate.ShutDown(gReboot, askUser, !async);
171 		if (error != B_OK)
172 			fprintf(stderr, "Shutdown failed: %s\n", strerror(error));
173 		return 2;
174 	}
175 
176 	return 0;
177 }
178 
179