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