From: Davin McCall Date: Thu, 7 Jan 2016 23:06:54 +0000 (+0000) Subject: Fix protocol errors in dinitctl X-Git-Tag: v0.01~44 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=aa71ea68bce0819b73cce0a060b685ccf8012d6c;p=oweals%2Fdinit.git Fix protocol errors in dinitctl --- diff --git a/src/Makefile b/src/Makefile index 1d4326d..13da888 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ shutdown: shutdown.o dinit-reboot: dinit-reboot.o $(CXX) -o dinit-reboot dinit-reboot.o -$(objects): %.o: %.cc service.h dinit-log.h control.h control-cmds.h +$(objects): %.o: %.cc service.h dinit-log.h control.h control-cmds.h cpbuffer.h $(CXX) $(CXXOPTS) -c $< -o $@ #install: all diff --git a/src/cpbuffer.h b/src/cpbuffer.h index 251ef6a..94132ca 100644 --- a/src/cpbuffer.h +++ b/src/cpbuffer.h @@ -22,7 +22,7 @@ class CPBuffer int pos = cur_idx + length; if (pos >= 1024) pos -= 1024; int max_count = std::min(1024 - pos, 1024 - length); - ssize_t r = read(fd, buf + cur_idx, max_count); + ssize_t r = read(fd, buf + pos, max_count); if (r >= 0) { length += r; } diff --git a/src/dinitctl.cc b/src/dinitctl.cc index f307660..7399cb5 100644 --- a/src/dinitctl.cc +++ b/src/dinitctl.cc @@ -50,6 +50,22 @@ static const char * describeVerb(bool stop) return stop ? "stop" : "start"; } +// Wait for a reply packet, skipping over any information packets +// that are received in the meantime. +static void wait_for_reply(CPBuffer &rbuffer, int fd) +{ + fillBufferTo(&rbuffer, fd, 1); + + while (rbuffer[0] >= 100) { + // Information packet; discard. + fillBufferTo(&rbuffer, fd, 1); + int pktlen = (unsigned char) rbuffer[1]; + fillBufferTo(&rbuffer, fd, pktlen); + rbuffer.consume(pktlen); + } +} + + // Write *all* the requested buffer and re-try if necessary until // the buffer is written or an unrecoverable error occurs. static int write_all(int fd, const void *buf, size_t count) @@ -213,7 +229,7 @@ int main(int argc, char **argv) try { CPBuffer rbuffer; - fillBufferTo(&rbuffer, socknum, 1); + wait_for_reply(rbuffer, socknum); ServiceState state; ServiceState target_state; @@ -244,8 +260,20 @@ int main(int argc, char **argv) buf[0] = command; buf[1] = 0; // don't pin memcpy(buf + 2, &handle, sizeof(handle)); - r = write(socknum, buf, 2 + sizeof(handle)); + r = write_all(socknum, buf, 2 + sizeof(handle)); delete buf; + + if (r == -1) { + perror("write"); + return 1; + } + + wait_for_reply(rbuffer, socknum); + if (rbuffer[0] != DINIT_RP_ACK) { + cerr << "Protocol error." << endl; + return 1; + } + rbuffer.consume(1); } if (state == wanted_state) { @@ -303,6 +331,9 @@ int main(int argc, char **argv) } } } + + rbuffer.consume(pktlen); + r = rbuffer.fillTo(socknum, 2); } else { // Not an information packet?