+// Fill a circular buffer from a file descriptor, reading at least _rlength_ bytes.
+// Throws ReadException if the requested number of bytes cannot be read, with:
+// 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)
+{
+ do {
+ int r = buf->fill_to(fd, rlength);
+ if (r == -1) {
+ if (errno != EINTR) {
+ throw ReadCPException(errno);
+ }
+ }
+ else if (r == 0) {
+ throw ReadCPException(0);
+ }
+ else {
+ return;
+ }
+ }
+ while (true);
+}
+
+// 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)
+{
+ fillBufferTo(&rbuffer, fd, 1);
+
+ while (rbuffer[0] >= 100) {
+ // Information packet; discard.
+ fillBufferTo(&rbuffer, fd, 1);
+ int pktlen = (unsigned char) rbuffer[1];
+
+ rbuffer.consume(1); // Consume one byte so we'll read one byte of the next packet
+ fillBufferTo(&rbuffer, fd, pktlen);
+ rbuffer.consume(pktlen - 1);
+ }
+}
+
+// Actually shut down the system.