Fix protocol errors in dinitctl
authorDavin McCall <davmac@davmac.org>
Thu, 7 Jan 2016 23:06:54 +0000 (23:06 +0000)
committerDavin McCall <davmac@davmac.org>
Thu, 7 Jan 2016 23:06:54 +0000 (23:06 +0000)
src/Makefile
src/cpbuffer.h
src/dinitctl.cc

index 1d4326d11b407b960133f538e00ffb57806d91d3..13da888c1407421a502ee70b7793fcdf11f2e903 100644 (file)
@@ -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
index 251ef6aacdab76be7c0f2d004ad7ea6bb0e13d0a..94132ca2db001f224e36e5f0bea3e53743811df3 100644 (file)
@@ -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;
         }
index f30766036a610b7746765a6f842d20efb012691a..7399cb559fd7fb70624dba64b0791cf63c6987fe 100644 (file)
@@ -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?