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