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