blob: c21ddad58552fa1610b1b105e227781eeb81abf5 [file] [log] [blame]
Denys Vlasenkoc21dfaf2018-04-20 15:12:52 +02001/* 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
47extern int reboot(int, int, int);
48# define REBOOT(cmd) reboot(LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,(cmd))
49#endif
50
51static 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 */
65extern int reboot(int, int, int);
66#endif
67
68static int my_reboot(int cmd)
69{
70 return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd);
71}
72
73#endif
74
75
76static void do_reboot(void)
77{
78 my_reboot(LINUX_REBOOT_CMD_RESTART);
79}
80static void do_poweroff(void)
81{
82 my_reboot(LINUX_REBOOT_CMD_POWER_OFF);
83}
84static void do_halt(void)
85{
86 my_reboot(LINUX_REBOOT_CMD_HALT);
87}
88
89static 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
98enum action_t {
99 SHUTDOWN, // do nothing
100 HALT,
101 POWEROFF,
102 REBOOT
103};
104
105int 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}