42b9edc08f849d364b8b68a12f109d7eb204dd07
[platform/upstream/busybox.git] / init / halt.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Poweroff reboot and halt, oh my.
4  *
5  * Copyright 2006 by Rob Landley <rob@landley.net>
6  *
7  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
8  */
9
10 #include "libbb.h"
11 #include <sys/reboot.h>
12
13 #if ENABLE_FEATURE_WTMP
14 #include <sys/utsname.h>
15 #include <utmp.h>
16 #endif
17
18 int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
19 int halt_main(int argc UNUSED_PARAM, char **argv)
20 {
21         static const int magic[] = {
22 #ifdef RB_HALT_SYSTEM
23                 RB_HALT_SYSTEM,
24 #elif defined RB_HALT
25                 RB_HALT,
26 #endif
27 #ifdef RB_POWER_OFF
28                 RB_POWER_OFF,
29 #elif defined RB_POWERDOWN
30                 RB_POWERDOWN,
31 #endif
32                 RB_AUTOBOOT
33         };
34         static const smallint signals[] = { SIGUSR1, SIGUSR2, SIGTERM };
35
36         int delay = 0;
37         int which, flags, rc;
38 #if ENABLE_FEATURE_WTMP
39         struct utmp utmp;
40         struct utsname uts;
41 #endif
42
43         /* Figure out which applet we're running */
44         for (which = 0; "hpr"[which] != *applet_name; which++)
45                 continue;
46
47         /* Parse and handle arguments */
48         opt_complementary = "d+"; /* -d N */
49         flags = getopt32(argv, "d:nf" USE_FEATURE_WTMP("w"), &delay);
50
51         sleep(delay);
52
53 #if ENABLE_FEATURE_WTMP
54         if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) {
55                 close(creat(bb_path_wtmp_file, 0664));
56         }
57         memset(&utmp, 0, sizeof(utmp));
58         utmp.ut_tv.tv_sec = time(NULL);
59         safe_strncpy(utmp.ut_user, "shutdown", UT_NAMESIZE);
60         utmp.ut_type = RUN_LVL;
61         safe_strncpy(utmp.ut_id, "~~", sizeof(utmp.ut_id));
62         safe_strncpy(utmp.ut_line, "~~", UT_LINESIZE);
63         if (uname(&uts) == 0)
64                 safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host));
65         updwtmp(bb_path_wtmp_file, &utmp);
66
67         if (flags & 8) /* -w */
68                 return EXIT_SUCCESS;
69 #endif /* !ENABLE_FEATURE_WTMP */
70
71         if (!(flags & 2)) /* no -n */
72                 sync();
73
74         /* Perform action. */
75         rc = 1;
76         if (!(flags & 4)) { /* no -f */
77 //TODO: I tend to think that signalling linuxrc is wrong
78 // pity original author didn't comment on it...
79                 if (ENABLE_FEATURE_INITRD) {
80                         pid_t *pidlist = find_pid_by_name("linuxrc");
81                         if (pidlist[0] > 0)
82                                 rc = kill(pidlist[0], signals[which]);
83                         if (ENABLE_FEATURE_CLEAN_UP)
84                                 free(pidlist);
85                 }
86                 if (rc)
87                         rc = kill(1, signals[which]);
88         } else
89                 rc = reboot(magic[which]);
90
91         if (rc)
92                 bb_error_msg("no");
93         return rc;
94 }