1 // #include <netinet/in.h>
10 #include <sys/reboot.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
19 #include "control-cmds.h"
21 // shutdown: shut down the system
22 // This utility communicates with the dinit daemon via a unix socket (/dev/initctl).
24 static void unmount_disks();
25 static void swap_off();
27 int main(int argc, char **argv)
33 //bool show_help = argc < 2;
34 bool show_help = false;
36 for (int i = 1; i < argc; i++) {
37 if (argv[i][0] == '-') {
38 if (strcmp(argv[i], "--help") == 0) {
42 else if (strcmp(argv[i], "-r") == 0) {
46 else if (strcmp(argv[i], "-p") == 0) {
50 else if (strcmp(argv[i], "-h") == 0) {
54 else if (strcmp(argv[i], "-l") == 0) {
59 cerr << "Unrecognized command-line parameter: " << argv[i] << endl;
64 // time argument? TODO
70 cout << "dinit-shutdown : shutdown the system" << endl;
71 cout << " --help : show this help" << endl;
82 if (sd_type == 1) reboot_type = RB_AUTOBOOT;
83 else if (sd_type == 2) reboot_type = RB_POWER_OFF;
84 else reboot_type = RB_HALT_SYSTEM;
86 // Write to console rather than any terminal, since we lose the terminal it seems:
88 int consfd = open("/dev/console", O_WRONLY);
89 if (consfd != STDOUT_FILENO) {
90 dup2(consfd, STDOUT_FILENO);
93 // At this point, util-linux 2.13 shutdown sends SIGTERM to all processes with uid >= 100 and
94 // calls it 'sendiong SIGTERM to mortals'.
95 // Equivalent would probably be to rollback 'loginready' service. However, that will happen as
96 // part of the regular rollback anyway.
98 //cout << "Writing rollback command..." << endl; // DAV
100 //int r = write(socknum, buf, bufsize);
105 cout << "Sending TERM/KILL..." << endl; // DAV
107 // Send TERM/KILL to all (remaining) processes
112 cout << "Sending QUIT to init..." << endl; // DAV
114 // Tell init to exec reboot:
115 // TODO what if it's not PID=1? probably should have dinit pass us its PID
118 // TODO can we wait somehow for above to work?
119 // maybe have a pipe/socket and we read from our end...
121 // TODO: close all ancillary file descriptors.
124 cout << "Turning off swap..." << endl;
126 cout << "Unmounting disks..." << endl;
130 cout << "Issuing shutdown via kernel..." << endl;
136 static void unmount_disks()
138 pid_t chpid = fork();
141 // -a : all filesystems (except proc)
142 // -r : mount readonly if can't unmount
143 execl("/bin/umount", "/bin/umount", "-a", "-r", nullptr);
145 else if (chpid > 0) {
147 waitpid(chpid, &status, 0);
151 static void swap_off()
153 pid_t chpid = fork();
156 execl("/sbin/swapoff", "/sbin/swapoff", "-a", nullptr);
158 else if (chpid > 0) {
160 waitpid(chpid, &status, 0);