X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fshutdown.cc;h=c751fd086fe422a3e9beb877a7cc3abb37aa84c4;hb=18acacfe2064ade28a4febbfeb85fd6e14020ac1;hp=a9c95a8a3e4bdae06d139e617131770528c6b399;hpb=a8a74ef057fb657e32110be4323e5bd8c21def19;p=oweals%2Fdinit.git diff --git a/src/shutdown.cc b/src/shutdown.cc index a9c95a8..c751fd0 100644 --- a/src/shutdown.cc +++ b/src/shutdown.cc @@ -21,10 +21,10 @@ // shutdown: shut down the system // This utility communicates with the dinit daemon via a unix socket (/dev/initctl). -void do_system_shutdown(ShutdownType shutdown_type); +void do_system_shutdown(shutdown_type_t shutdown_type); static void unmount_disks(); static void swap_off(); -static void wait_for_reply(CPBuffer<1024> &rbuffer, int fd); +static void wait_for_reply(cpbuffer<1024> &rbuffer, int fd); class ReadCPException @@ -41,8 +41,9 @@ int main(int argc, char **argv) bool show_help = false; bool sys_shutdown = false; + bool use_passed_cfd = false; - auto shutdown_type = ShutdownType::POWEROFF; + auto shutdown_type = shutdown_type_t::POWEROFF; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { @@ -55,13 +56,16 @@ int main(int argc, char **argv) sys_shutdown = true; } else if (strcmp(argv[i], "-r") == 0) { - shutdown_type = ShutdownType::REBOOT; + shutdown_type = shutdown_type_t::REBOOT; } else if (strcmp(argv[i], "-h") == 0) { - shutdown_type = ShutdownType::HALT; + shutdown_type = shutdown_type_t::HALT; } else if (strcmp(argv[i], "-p") == 0) { - shutdown_type = ShutdownType::POWEROFF; + shutdown_type = shutdown_type_t::POWEROFF; + } + else if (strcmp(argv[i], "--use-passed-cfd") == 0) { + use_passed_cfd = true; } else { cerr << "Unrecognized command-line parameter: " << argv[i] << endl; @@ -80,6 +84,8 @@ int main(int argc, char **argv) cout << " -r : reboot" << endl; cout << " -h : halt system" << endl; cout << " -p : power down (default)" << endl; + cout << " --use-passed-cfd : use the socket file descriptor identified by the DINIT_CS_FD" << endl; + cout << " environment variable to communicate with the init daemon." << endl; cout << " --system : perform shutdown immediately, instead of issuing shutdown" << endl; cout << " command to the init program. Not recommended for use" << endl; cout << " by users." << endl; @@ -90,32 +96,52 @@ int main(int argc, char **argv) do_system_shutdown(shutdown_type); return 0; } - - int socknum = socket(AF_UNIX, SOCK_STREAM, 0); - if (socknum == -1) { - perror("socket"); - return 1; - } signal(SIGPIPE, SIG_IGN); - const char *naddr = "/dev/dinitctl"; - - struct sockaddr_un name; - name.sun_family = AF_UNIX; - strcpy(name.sun_path, naddr); - int sunlen = offsetof(struct sockaddr_un, sun_path) + strlen(naddr) + 1; // family, (string), nul + int socknum = 0; - int connr = connect(socknum, (struct sockaddr *) &name, sunlen); - if (connr == -1) { - perror("connect"); - return 1; + if (use_passed_cfd) { + char * dinit_cs_fd_env = getenv("DINIT_CS_FD"); + if (dinit_cs_fd_env != nullptr) { + char * endptr; + long int cfdnum = strtol(dinit_cs_fd_env, &endptr, 10); + if (endptr != dinit_cs_fd_env) { + socknum = (int) cfdnum; + } + else { + use_passed_cfd = false; + } + } + else { + use_passed_cfd = false; + } } + if (! use_passed_cfd) { + socknum = socket(AF_UNIX, SOCK_STREAM, 0); + if (socknum == -1) { + perror("socket"); + return 1; + } + + const char *naddr = "/dev/dinitctl"; + + struct sockaddr_un name; + name.sun_family = AF_UNIX; + strcpy(name.sun_path, naddr); + int sunlen = offsetof(struct sockaddr_un, sun_path) + strlen(naddr) + 1; // family, (string), nul + + int connr = connect(socknum, (struct sockaddr *) &name, sunlen); + if (connr == -1) { + perror("connect"); + return 1; + } + } + // Build buffer; - //uint16_t sname_len = strlen(service_name); - int bufsize = 2; - char * buf = new char[bufsize]; + constexpr int bufsize = 2; + char buf[bufsize]; buf[0] = DINIT_CP_SHUTDOWN; buf[1] = static_cast(shutdown_type); @@ -135,7 +161,7 @@ int main(int argc, char **argv) // cout << "Received acknowledgement. System should now shut down." << endl; //} - CPBuffer<1024> rbuffer; + cpbuffer<1024> rbuffer; try { wait_for_reply(rbuffer, socknum); @@ -162,7 +188,7 @@ int main(int argc, char **argv) // errcode = 0 if end of stream (remote end closed) // errcode = errno if another error occurred // Note that EINTR is ignored (i.e. the read will be re-tried). -static void fillBufferTo(CPBuffer<1024> *buf, int fd, int rlength) +static void fillBufferTo(cpbuffer<1024> *buf, int fd, int rlength) { do { int r = buf->fill_to(fd, rlength); @@ -183,13 +209,13 @@ static void fillBufferTo(CPBuffer<1024> *buf, int fd, int rlength) // Wait for a reply packet, skipping over any information packets // that are received in the meantime. -static void wait_for_reply(CPBuffer<1024> &rbuffer, int fd) +static void wait_for_reply(cpbuffer<1024> &rbuffer, int fd) { fillBufferTo(&rbuffer, fd, 1); while (rbuffer[0] >= 100) { // Information packet; discard. - fillBufferTo(&rbuffer, fd, 1); + fillBufferTo(&rbuffer, fd, 2); int pktlen = (unsigned char) rbuffer[1]; rbuffer.consume(1); // Consume one byte so we'll read one byte of the next packet @@ -199,13 +225,18 @@ static void wait_for_reply(CPBuffer<1024> &rbuffer, int fd) } // Actually shut down the system. -void do_system_shutdown(ShutdownType shutdown_type) +void do_system_shutdown(shutdown_type_t shutdown_type) { using namespace std; + // Mask all signals to prevent death of our parent etc from terminating us + sigset_t allsigs; + sigfillset(&allsigs); + sigprocmask(SIG_SETMASK, &allsigs, nullptr); + int reboot_type = 0; - if (shutdown_type == ShutdownType::REBOOT) reboot_type = RB_AUTOBOOT; - else if (shutdown_type == ShutdownType::POWEROFF) reboot_type = RB_POWER_OFF; + if (shutdown_type == shutdown_type_t::REBOOT) reboot_type = RB_AUTOBOOT; + else if (shutdown_type == shutdown_type_t::POWEROFF) reboot_type = RB_POWER_OFF; else reboot_type = RB_HALT_SYSTEM; // Write to console rather than any terminal, since we lose the terminal it seems: @@ -215,7 +246,7 @@ void do_system_shutdown(ShutdownType shutdown_type) dup2(consfd, STDOUT_FILENO); } - cout << "Sending TERM/KILL to all processes..." << endl; // DAV + cout << "Sending TERM/KILL to all processes..." << endl; // Send TERM/KILL to all (remaining) processes kill(-1, SIGTERM);