1 /* Including <unistd.h> makes sure that on a glibc system
2 * <features.h> is included, which again defines __GLIBC__
3 */
4
5 #include <unistd.h>
6 #include <stdio.h> /* puts */
7 #include <time.h> /* nanosleep */
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12
13 /*
14 * Magic values required to use _reboot() system call.
15 */
16 #define LINUX_REBOOT_MAGIC1 0xfee1dead
17 #define LINUX_REBOOT_MAGIC2 672274793
18 #define LINUX_REBOOT_MAGIC2A 85072278
19 #define LINUX_REBOOT_MAGIC2B 369367448
20 /*
21 * Commands accepted by the _reboot() system call.
22 *
23 * RESTART Restart system using default command and mode.
24 * HALT Stop OS and give system control to ROM monitor, if any.
25 * CAD_ON Ctrl-Alt-Del sequence causes RESTART command.
26 * CAD_OFF Ctrl-Alt-Del sequence sends SIGINT to init task.
27 * POWER_OFF Stop OS and remove all power from system, if possible.
28 * RESTART2 Restart system using given command string.
29 */
30 #define LINUX_REBOOT_CMD_RESTART 0x01234567
31 #define LINUX_REBOOT_CMD_HALT 0xCDEF0123
32 #define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
33 #define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
34 #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
35 #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
36
37
38 #define USE_LIBC
39
40 #ifdef USE_LIBC
41
42 /* libc version */
43 #if defined __GLIBC__ && __GLIBC__ >= 2
44 # include <sys/reboot.h>
45 # define REBOOT(cmd) reboot(cmd)
46 #else
47 extern int reboot(int, int, int);
48 # define REBOOT(cmd) reboot(LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,(cmd))
49 #endif
50
my_reboot(int cmd)51 static int my_reboot(int cmd)
52 {
53 return REBOOT(cmd);
54 }
55
56 #else /* no USE_LIBC */
57
58 /* direct syscall version */
59 #include <linux/unistd.h>
60
61 #ifdef _syscall3
62 _syscall3(int, reboot, int, magic, int, magic_too, int, cmd);
63 #else
64 /* Let us hope we have a 3-argument reboot here */
65 extern int reboot(int, int, int);
66 #endif
67
my_reboot(int cmd)68 static int my_reboot(int cmd)
69 {
70 return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd);
71 }
72
73 #endif
74
75
do_reboot(void)76 static void do_reboot(void)
77 {
78 my_reboot(LINUX_REBOOT_CMD_RESTART);
79 }
do_poweroff(void)80 static void do_poweroff(void)
81 {
82 my_reboot(LINUX_REBOOT_CMD_POWER_OFF);
83 }
do_halt(void)84 static void do_halt(void)
85 {
86 my_reboot(LINUX_REBOOT_CMD_HALT);
87 }
88
usage(void)89 static void usage(void)
90 {
91 puts(
92 "Usage: hardshutdown -h|-r|-p [NN]\n"
93 " NN - seconds to sleep before requested action"
94 );
95 exit(1);
96 }
97
98 enum action_t {
99 SHUTDOWN, // do nothing
100 HALT,
101 POWEROFF,
102 REBOOT
103 };
104
main(int argc,char * argv[])105 int main(int argc, char *argv[])
106 {
107 struct timespec t = {0,0};
108 enum action_t action = SHUTDOWN;
109 int c, i;
110 char *prog, *ptr;
111
112 //if (*argv[0] == '-') argv[0]++; /* allow shutdown as login shell */
113 prog = argv[0];
114 ptr = strrchr(prog,'/');
115 if (ptr)
116 prog = ptr+1;
117
118 for (c=1; c < argc; c++) {
119 if (argv[c][0] >= '0' && argv[c][0] <= '9') {
120 t.tv_sec = strtol(argv[c], NULL, 10);
121 continue;
122 }
123 if (argv[c][0] != '-') {
124 usage();
125 return 1;
126 }
127 for (i=1; argv[c][i]; i++) {
128 switch (argv[c][i]) {
129 case 'h':
130 action = HALT;
131 break;
132 case 'p':
133 action = POWEROFF;
134 break;
135 case 'r':
136 action = REBOOT;
137 break;
138 default:
139 usage();
140 return 1;
141 }
142 }
143 }
144
145 if (action==SHUTDOWN) {
146 usage();
147 return 1;
148 }
149
150 chdir("/");
151 while (nanosleep(&t,&t)<0)
152 if (errno!=EINTR) break;
153
154 switch (action) {
155 case HALT:
156 do_halt();
157 break;
158 case POWEROFF:
159 do_poweroff();
160 break;
161 case REBOOT:
162 do_reboot();
163 break;
164 default: /* SHUTDOWN */
165 break;
166 }
167 return 1;
168 }
169