From 0d26b330e39e9197dd82942474abc7aaf237be6c Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Tue, 13 Feb 2018 18:14:29 +0000 Subject: [PATCH] Refactoring in utilities. --- src/dinitctl.cc | 124 +++++++++++------------------------- src/includes/dinit-client.h | 15 +++-- src/shutdown.cc | 54 +++++++++------- 3 files changed, 76 insertions(+), 117 deletions(-) diff --git a/src/dinitctl.cc b/src/dinitctl.cc index 359ea55..6be9da9 100644 --- a/src/dinitctl.cc +++ b/src/dinitctl.cc @@ -290,41 +290,30 @@ static int start_stop_service(int socknum, cpbuffer_t &rbuffer, const char *serv service_state_t wanted_state = do_stop ? service_state_t::STOPPED : service_state_t::STARTED; int pcommand = 0; switch (command) { - case command_t::STOP_SERVICE: - pcommand = DINIT_CP_STOPSERVICE; - break; - case command_t::RELEASE_SERVICE: - pcommand = DINIT_CP_RELEASESERVICE; - break; - case command_t::START_SERVICE: - pcommand = DINIT_CP_STARTSERVICE; - break; - case command_t::WAKE_SERVICE: - pcommand = DINIT_CP_WAKESERVICE; - break; - default: ; + case command_t::STOP_SERVICE: + pcommand = DINIT_CP_STOPSERVICE; + break; + case command_t::RELEASE_SERVICE: + pcommand = DINIT_CP_RELEASESERVICE; + break; + case command_t::START_SERVICE: + pcommand = DINIT_CP_STARTSERVICE; + break; + case command_t::WAKE_SERVICE: + pcommand = DINIT_CP_WAKESERVICE; + break; + default: ; } // Need to issue STOPSERVICE/STARTSERVICE // We'll do this regardless of the current service state / target state, since issuing // start/stop also sets or clears the "explicitly started" flag on the service. { - int r; - - { - auto buf = new char[2 + sizeof(handle)]; - unique_ptr ubuf(buf); - - buf[0] = pcommand; - buf[1] = do_pin ? 1 : 0; - memcpy(buf + 2, &handle, sizeof(handle)); - r = write_all(socknum, buf, 2 + sizeof(handle)); - } - - if (r == -1) { - perror("dinitctl: write"); - return 1; - } + char buf[2 + sizeof(handle)]; + buf[0] = pcommand; + buf[1] = do_pin ? 1 : 0; + memcpy(buf + 2, &handle, sizeof(handle)); + write_all_x(socknum, buf, 2 + sizeof(handle)); wait_for_reply(rbuffer, socknum); if (rbuffer[0] == DINIT_RP_ALREADYSS) { @@ -419,27 +408,15 @@ static int issue_load_service(int socknum, const char *service_name, bool find_o // Build buffer; uint16_t sname_len = strlen(service_name); int bufsize = 3 + sname_len; - int r; - try { - std::unique_ptr ubuf(new char[bufsize]); - auto buf = ubuf.get(); - - buf[0] = find_only ? DINIT_CP_FINDSERVICE : DINIT_CP_LOADSERVICE; - memcpy(buf + 1, &sname_len, 2); - memcpy(buf + 3, service_name, sname_len); - - r = write_all(socknum, buf, bufsize); - } - catch (std::bad_alloc &badalloc) { - std::cerr << "dinitctl: " << badalloc.what() << std::endl; - return 1; - } - - if (r == -1) { - perror("dinitctl: write"); - return 1; - } + std::unique_ptr ubuf(new char[bufsize]); + auto buf = ubuf.get(); + + buf[0] = find_only ? DINIT_CP_FINDSERVICE : DINIT_CP_LOADSERVICE; + memcpy(buf + 1, &sname_len, 2); + memcpy(buf + 3, service_name, sname_len); + + write_all_x(socknum, buf, bufsize); return 0; } @@ -488,20 +465,10 @@ static int unpin_service(int socknum, cpbuffer_t &rbuffer, const char *service_n // Issue UNPIN command. { - int r; - - { - char *buf = new char[1 + sizeof(handle)]; - unique_ptr ubuf(buf); - buf[0] = DINIT_CP_UNPINSERVICE; - memcpy(buf + 1, &handle, sizeof(handle)); - r = write_all(socknum, buf, 2 + sizeof(handle)); - } - - if (r == -1) { - perror("dinitctl: write"); - return 1; - } + char buf[1 + sizeof(handle)]; + buf[0] = DINIT_CP_UNPINSERVICE; + memcpy(buf + 1, &handle, sizeof(handle)); + write_all_x(socknum, buf, 2 + sizeof(handle)); wait_for_reply(rbuffer, socknum); if (rbuffer[0] != DINIT_RP_ACK) { @@ -538,20 +505,10 @@ static int unload_service(int socknum, cpbuffer_t &rbuffer, const char *service_ // Issue UNLOAD command. { - int r; - - { - char *buf = new char[1 + sizeof(handle)]; - unique_ptr ubuf(buf); - buf[0] = DINIT_CP_UNLOADSERVICE; - memcpy(buf + 1, &handle, sizeof(handle)); - r = write_all(socknum, buf, 2 + sizeof(handle)); - } - - if (r == -1) { - perror("dinitctl: write"); - return 1; - } + char buf[1 + sizeof(handle)]; + buf[0] = DINIT_CP_UNLOADSERVICE; + memcpy(buf + 1, &handle, sizeof(handle)); + write_all_x(socknum, buf, 2 + sizeof(handle)); wait_for_reply(rbuffer, socknum); if (rbuffer[0] == DINIT_RP_NAK) { @@ -575,12 +532,7 @@ static int list_services(int socknum, cpbuffer_t &rbuffer) using namespace std; char cmdbuf[] = { (char)DINIT_CP_LISTSERVICES }; - int r = write_all(socknum, cmdbuf, 1); - - if (r == -1) { - perror("dinitctl: write"); - return 1; - } + write_all_x(socknum, cmdbuf, 1); wait_for_reply(rbuffer, socknum); while (rbuffer[0] == DINIT_RP_SVCINFO) { @@ -643,11 +595,7 @@ static int shutdown_dinit(int socknum, cpbuffer_t &rbuffer) buf[0] = DINIT_CP_SHUTDOWN; buf[1] = static_cast(shutdown_type_t::HALT); - int r = write_all(socknum, buf, bufsize); - if (r == -1) { - perror("write"); - return 1; - } + write_all_x(socknum, buf, bufsize); wait_for_reply(rbuffer, socknum); diff --git a/src/includes/dinit-client.h b/src/includes/dinit-client.h index e40ad6d..0fff4a4 100644 --- a/src/includes/dinit-client.h +++ b/src/includes/dinit-client.h @@ -104,20 +104,25 @@ inline int write_all(int fd, const void *buf, size_t count) return w; } +// Write all the requested buffer, and throw an exception on failure. +inline void write_all_x(int fd, const void *buf, size_t count) +{ + if (write_all(fd, buf, count) == -1) { + throw cp_write_exception(errno); + } +} + // Check the protocol version is compatible with the client. // minverison - minimum protocol version that client can speak // version - maximum protocol version that client can speak // rbuffer, fd - communication buffer and socket // returns: the actual protocol version // throws an exception on protocol mismatch or error. -uint16_t check_protocol_version(int minversion, int version, cpbuffer_t &rbuffer, int fd) +inline uint16_t check_protocol_version(int minversion, int version, cpbuffer_t &rbuffer, int fd) { constexpr int bufsize = 1; char buf[bufsize] = { DINIT_CP_QUERYVERSION }; - int r = write_all(fd, buf, bufsize); - if (r == -1) { - throw cp_write_exception(errno); - } + write_all_x(fd, buf, bufsize); wait_for_reply(rbuffer, fd); if (rbuffer[0] != DINIT_RP_CPVERSION) { diff --git a/src/shutdown.cc b/src/shutdown.cc index 886826b..6ba4416 100644 --- a/src/shutdown.cc +++ b/src/shutdown.cc @@ -131,29 +131,24 @@ int main(int argc, char **argv) } } - // Build buffer; - constexpr int bufsize = 2; - char buf[bufsize]; - - buf[0] = DINIT_CP_SHUTDOWN; - buf[1] = static_cast(shutdown_type); - - cout << "Issuing shutdown command..." << endl; - - int r = write_all(socknum, buf, bufsize); - if (r == -1) { - perror("write"); - return 1; - } + try { + cpbuffer_t rbuffer; - // Wait for ACK/NACK - // r = read(socknum, buf, 1); - //if (r > 0) { - // cout << "Received acknowledgement. System should now shut down." << endl; - //} + check_protocol_version(0, 0, rbuffer, socknum); + + // Build buffer; + constexpr int bufsize = 2; + char buf[bufsize]; + + buf[0] = DINIT_CP_SHUTDOWN; + buf[1] = static_cast(shutdown_type); + + cout << "Issuing shutdown command..." << endl; + + write_all_x(socknum, buf, bufsize); + + // Wait for ACK/NACK - cpbuffer<1024> rbuffer; - try { wait_for_reply(rbuffer, socknum); if (rbuffer[0] != DINIT_RP_ACK) { @@ -161,9 +156,20 @@ int main(int argc, char **argv) return 1; } } - catch (cp_read_exception &exc) - { - cerr << "shutdown: control socket read failure or protocol error" << endl; + catch (cp_old_client_exception &e) { + std::cerr << "shutdown: too old (server reports newer protocol version)" << std::endl; + return 1; + } + catch (cp_old_server_exception &e) { + std::cerr << "shutdown: server too old or protocol error" << std::endl; + return 1; + } + catch (cp_read_exception &e) { + cerr << "shutdown: control socket read failure or protocol error" << endl; + return 1; + } + catch (cp_write_exception &e) { + cerr << "shutdown: control socket write error: " << std::strerror(e.errcode) << endl; return 1; } -- 2.25.1