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