xref: /haiku/src/bin/shutdown.cpp (revision a13df0dc01b4f961be77fbb11ed08d177a4bae43)
117049c45SAxel Dörfler // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
217049c45SAxel Dörfler //
3925d069dSIngo Weinhold //  Copyright (c) 2002-2005, Haiku
417049c45SAxel Dörfler //
517049c45SAxel Dörfler //  This software is part of the Haiku distribution and is covered
617049c45SAxel Dörfler //  by the MIT license.
717049c45SAxel Dörfler //
817049c45SAxel Dörfler //  File:        shutdown.cpp
917049c45SAxel Dörfler //  Author:      Francois Revol (mmu_man@users.sf.net)
1017049c45SAxel Dörfler //  Description: shuts down the system, either halting or rebooting.
1117049c45SAxel Dörfler //
1217049c45SAxel Dörfler //  Notes:
1317049c45SAxel Dörfler //  This program behaves identically as the BeOS R5 version, with these
1417049c45SAxel Dörfler //  added arguments:
1517049c45SAxel Dörfler //
16*a13df0dcSIngo Weinhold //  -a asks the user to confirm the shutdown
1717049c45SAxel Dörfler //  -c cancels any running shutdown
1817049c45SAxel Dörfler //
1917049c45SAxel Dörfler //  Some code from Shard's Archiver from BeBits (was BSD/MIT too :).
2017049c45SAxel Dörfler //
2117049c45SAxel Dörfler // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
2217049c45SAxel Dörfler 
2317049c45SAxel Dörfler #include <syscalls.h>
2417049c45SAxel Dörfler 
2517049c45SAxel Dörfler #include <OS.h>
26925d069dSIngo Weinhold #include <Roster.h>
27925d069dSIngo Weinhold #include <RosterPrivate.h>
2817049c45SAxel Dörfler 
2917049c45SAxel Dörfler #include <signal.h>
3017049c45SAxel Dörfler #include <stdio.h>
3117049c45SAxel Dörfler #include <stdlib.h>
3217049c45SAxel Dörfler #include <string.h>
3317049c45SAxel Dörfler #include <unistd.h>
3417049c45SAxel Dörfler #include <ctype.h>
3517049c45SAxel Dörfler 
3617049c45SAxel Dörfler uint32 gTimeToSleep = 0;
3717049c45SAxel Dörfler bool gReboot = false;
3817049c45SAxel Dörfler 
3917049c45SAxel Dörfler // we get here when shutdown is cancelled.
4017049c45SAxel Dörfler // then sleep() returns
4117049c45SAxel Dörfler 
4217049c45SAxel Dörfler void
4317049c45SAxel Dörfler handle_usr1(int sig)
4417049c45SAxel Dörfler {
4517049c45SAxel Dörfler 	while (0);
4617049c45SAxel Dörfler }
4717049c45SAxel Dörfler 
4817049c45SAxel Dörfler 
4917049c45SAxel Dörfler bool
5017049c45SAxel Dörfler parseTime(char *arg, char *argv, int32 *_i)
5117049c45SAxel Dörfler {
5217049c45SAxel Dörfler 	char *unit;
5317049c45SAxel Dörfler 
5417049c45SAxel Dörfler 	if (isdigit(arg[0])) {
5517049c45SAxel Dörfler 		gTimeToSleep = strtoul(arg, &unit, 10);
5617049c45SAxel Dörfler 	} else if (argv && isdigit(argv[0])) {
5717049c45SAxel Dörfler 		(*_i)++;
5817049c45SAxel Dörfler 		gTimeToSleep = strtoul(argv, &unit, 10);
5917049c45SAxel Dörfler 	} else
6017049c45SAxel Dörfler 		return false;
6117049c45SAxel Dörfler 
6217049c45SAxel Dörfler 	if (unit[0] == '\0' || !strcmp(unit, "s"))
6317049c45SAxel Dörfler 		return true;
6417049c45SAxel Dörfler 	if (!strcmp(unit, "m")) {
6517049c45SAxel Dörfler 		gTimeToSleep *= 60;
6617049c45SAxel Dörfler 		return true;
6717049c45SAxel Dörfler 	}
6817049c45SAxel Dörfler 
6917049c45SAxel Dörfler 	return false;
7017049c45SAxel Dörfler }
7117049c45SAxel Dörfler 
7217049c45SAxel Dörfler 
7317049c45SAxel Dörfler void
7417049c45SAxel Dörfler usage(const char *arg0)
7517049c45SAxel Dörfler {
7617049c45SAxel Dörfler 	const char *program = strrchr(arg0, '/');
7717049c45SAxel Dörfler 	if (program == NULL)
7817049c45SAxel Dörfler 		program = arg0;
7917049c45SAxel Dörfler 	else
8017049c45SAxel Dörfler 		program++;
8117049c45SAxel Dörfler 
8217049c45SAxel Dörfler 	fprintf(stderr, "usage: %s [-rqca] [-d time]\n"
8317049c45SAxel Dörfler 		"\t-r reboot,\n"
8417049c45SAxel Dörfler 		"\t-q quick shutdown (don't broadcast apps),\n"
85*a13df0dcSIngo Weinhold 		"\t-a ask user to confirm the shutdown (ignored when -q is given),\n"
8617049c45SAxel Dörfler 		"\t-c cancel a running shutdown,\n"
8717049c45SAxel Dörfler 		"\t-d delay shutdown by <time> seconds.\n", program);
8817049c45SAxel Dörfler 	exit(1);
8917049c45SAxel Dörfler }
9017049c45SAxel Dörfler 
9117049c45SAxel Dörfler 
9217049c45SAxel Dörfler int
9317049c45SAxel Dörfler main(int argc, char **argv)
9417049c45SAxel Dörfler {
95*a13df0dcSIngo Weinhold 	bool askUser = false;
9617049c45SAxel Dörfler 	bool quick = false;
9717049c45SAxel Dörfler 
9817049c45SAxel Dörfler 	for (int32 i = 1; i < argc; i++) {
9917049c45SAxel Dörfler 		char *arg = argv[i];
10017049c45SAxel Dörfler 		if (arg[0] == '-') {
10117049c45SAxel Dörfler 			if (!isalpha(arg[1]))
10217049c45SAxel Dörfler 				usage(argv[0]);
10317049c45SAxel Dörfler 
10417049c45SAxel Dörfler 			while (arg && isalpha((++arg)[0])) {
10517049c45SAxel Dörfler 				switch (arg[0]) {
106*a13df0dcSIngo Weinhold 					case 'a':
107*a13df0dcSIngo Weinhold 						askUser = true;
108*a13df0dcSIngo Weinhold 						break;
10917049c45SAxel Dörfler 					case 'q':
11017049c45SAxel Dörfler 						quick = true;
11117049c45SAxel Dörfler 						break;
11217049c45SAxel Dörfler 					case 'r':
11317049c45SAxel Dörfler 						gReboot = true;
11417049c45SAxel Dörfler 						break;
11517049c45SAxel Dörfler 					case 'c':
11617049c45SAxel Dörfler 					{
11717049c45SAxel Dörfler 						// find all running shutdown command and signal its shutdown thread
11817049c45SAxel Dörfler 
11917049c45SAxel Dörfler 						thread_info threadInfo;
12017049c45SAxel Dörfler 						get_thread_info(find_thread(NULL), &threadInfo);
12117049c45SAxel Dörfler 
12217049c45SAxel Dörfler 						team_id thisTeam = threadInfo.team;
12317049c45SAxel Dörfler 
12417049c45SAxel Dörfler 						int32 team_cookie = 0;
12517049c45SAxel Dörfler 						team_info teamInfo;
12617049c45SAxel Dörfler 						while (get_next_team_info(&team_cookie, &teamInfo) == B_OK) {
12717049c45SAxel Dörfler 							if (strstr(teamInfo.args, "shutdown") != NULL && teamInfo.team != thisTeam) {
12817049c45SAxel Dörfler 								int32 thread_cookie = 0;
12917049c45SAxel Dörfler 								while (get_next_thread_info(teamInfo.team, &thread_cookie, &threadInfo) == B_OK) {
13017049c45SAxel Dörfler 									if (!strcmp(threadInfo.name, "shutdown"))
13117049c45SAxel Dörfler 										kill(threadInfo.thread, SIGUSR1);
13217049c45SAxel Dörfler 								}
13317049c45SAxel Dörfler 							}
13417049c45SAxel Dörfler 						}
13517049c45SAxel Dörfler 						exit(0);
13617049c45SAxel Dörfler 						break;
13717049c45SAxel Dörfler 					}
13817049c45SAxel Dörfler 					case 'd':
13917049c45SAxel Dörfler 						if (parseTime(arg + 1, argv[i + 1], &i)) {
14017049c45SAxel Dörfler 							arg = NULL;
14117049c45SAxel Dörfler 							break;
14217049c45SAxel Dörfler 						}
14317049c45SAxel Dörfler 						// supposed to fall through
14417049c45SAxel Dörfler 
14517049c45SAxel Dörfler 					default:
14617049c45SAxel Dörfler 						usage(argv[0]);
14717049c45SAxel Dörfler 				}
14817049c45SAxel Dörfler 			}
14917049c45SAxel Dörfler 		} else
15017049c45SAxel Dörfler 			usage(argv[0]);
15117049c45SAxel Dörfler 	}
15217049c45SAxel Dörfler 
15317049c45SAxel Dörfler 	if (gTimeToSleep > 0) {
15417049c45SAxel Dörfler 		int32 left;
15517049c45SAxel Dörfler 
15617049c45SAxel Dörfler 		signal(SIGUSR1, handle_usr1);
15717049c45SAxel Dörfler 
15817049c45SAxel Dörfler 		printf("Delaying %s by %lu seconds...\n", gReboot ? "reboot" : "shutdown", gTimeToSleep);
15917049c45SAxel Dörfler 
16017049c45SAxel Dörfler 		left = sleep(gTimeToSleep);
16117049c45SAxel Dörfler 
16217049c45SAxel Dörfler 		if (left > 0) {
16317049c45SAxel Dörfler 			fprintf(stderr, "Shutdown cancelled.\n");
16417049c45SAxel Dörfler 			exit(0);
16517049c45SAxel Dörfler 		}
16617049c45SAxel Dörfler 	}
16717049c45SAxel Dörfler 
16817049c45SAxel Dörfler 	if (quick) {
169925d069dSIngo Weinhold 		#ifdef __HAIKU__
17017049c45SAxel Dörfler 		_kern_shutdown(gReboot);
171925d069dSIngo Weinhold 		#endif // __HAIKU__
17217049c45SAxel Dörfler 		fprintf(stderr, "Shutdown failed!\n");
17317049c45SAxel Dörfler 		return 2;
17417049c45SAxel Dörfler 	} else {
175925d069dSIngo Weinhold 		BRoster roster;
176925d069dSIngo Weinhold 		BRoster::Private rosterPrivate(roster);
177*a13df0dcSIngo Weinhold 		status_t error = rosterPrivate.ShutDown(gReboot, askUser);
178925d069dSIngo Weinhold 		fprintf(stderr, "Shutdown failed: %s\n", strerror(error));
179925d069dSIngo Weinhold 		return 2;
18017049c45SAxel Dörfler 	}
18117049c45SAxel Dörfler 
18217049c45SAxel Dörfler 	return 0;
18317049c45SAxel Dörfler }
18417049c45SAxel Dörfler 
185