1 // #include <netinet/in.h>
10 #include <sys/reboot.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
18 #include "control-cmds.h"
19 #include "service-constants.h"
21 // shutdown: shut down the system
22 // This utility communicates with the dinit daemon via a unix socket (/dev/initctl).
24 int main(int argc, char **argv)
28 //bool show_help = argc < 2;
29 bool show_help = false;
31 auto shutdown_type = ShutdownType::POWEROFF;
33 for (int i = 1; i < argc; i++) {
34 if (argv[i][0] == '-') {
35 if (strcmp(argv[i], "--help") == 0) {
39 else if (strcmp(argv[i], "-r") == 0) {
40 shutdown_type = ShutdownType::REBOOT;
42 else if (strcmp(argv[i], "-h") == 0) {
43 shutdown_type = ShutdownType::POWEROFF;
46 cerr << "Unrecognized command-line parameter: " << argv[i] << endl;
51 // time argument? TODO
56 cout << "dinit-shutdown : shutdown the system" << endl;
57 cout << " --help : show this help" << endl;
61 int socknum = socket(AF_UNIX, SOCK_STREAM, 0);
67 const char *naddr = "/dev/dinitctl";
69 struct sockaddr_un name;
70 name.sun_family = AF_UNIX;
71 strcpy(name.sun_path, naddr);
72 int sunlen = offsetof(struct sockaddr_un, sun_path) + strlen(naddr) + 1; // family, (string), nul
74 int connr = connect(socknum, (struct sockaddr *) &name, sunlen);
81 //uint16_t sname_len = strlen(service_name);
83 char * buf = new char[bufsize];
85 buf[0] = DINIT_CP_SHUTDOWN;
86 buf[1] = static_cast<char>(shutdown_type);
88 //memcpy(buf + 1, &sname_len, 2);
89 //memcpy(buf + 3, service_name, sname_len);
91 // Make sure we can't die due to a signal at this point:
93 //sigfillset(&sigmask);
94 //sigprocmask(SIG_BLOCK, &sigmask, nullptr);
96 // Write to console rather than any terminal, since we lose the terminal it seems:
97 //close(STDOUT_FILENO);
98 //int consfd = open("/dev/console", O_WRONLY);
99 //if (consfd != STDOUT_FILENO) {
100 // dup2(consfd, STDOUT_FILENO);
103 // At this point, util-linux 2.13 shutdown sends SIGTERM to all processes with uid >= 100 and
104 // calls it 'sendiong SIGTERM to mortals'.
105 // Equivalent would probably be to rollback 'loginready' service. However, that will happen as
106 // part of the regular rollback anyway.
108 cout << "Writing shutdown command..." << endl; // DAV
110 // TODO make sure to write the whole buffer
111 int r = write(socknum, buf, bufsize);
116 cout << "Waiting for ACK..." << endl; // DAV
119 r = read(socknum, buf, 1);
120 // TODO: check result