#include "control-cmds.h"
#include "service-constants.h"
#include "cpbuffer.h"
+#include "dinit-client.h"
// dinitctl: utility to control the Dinit daemon, including starting and stopping of services.
// This utility communicates with the dinit daemon via a unix stream socket (/dev/initctl, or $HOME/.dinitctl).
-using handle_t = uint32_t;
-
-
-class read_cp_exception
-{
- public:
- int errcode;
- read_cp_exception(int err) : errcode(err) { }
-};
enum class command_t;
static int shutdown_dinit(int soclknum);
-// Fill a circular buffer from a file descriptor, until it contains at least _rlength_ bytes.
-// Throws read_cp_exception 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 read_cp_exception(errno);
- }
- }
- else if (r == 0) {
- throw read_cp_exception(0);
- }
- else {
- return;
- }
- }
- while (true);
-}
-
static const char * describeState(bool stopped)
{
return stopped ? "stopped" : "started";
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<1024> &rbuffer, int fd)
-{
- fillBufferTo(&rbuffer, fd, 1);
-
- while (rbuffer[0] >= 100) {
- // Information packet; discard.
- 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
- fillBufferTo(&rbuffer, fd, pktlen);
- rbuffer.consume(pktlen - 1);
- }
-}
-
-// Wait for an info packet. If any other reply packet comes, throw a read_cp_exception.
-static void wait_for_info(cpbuffer<1024> &rbuffer, int fd)
-{
- fillBufferTo(&rbuffer, fd, 2);
-
- if (rbuffer[0] < 100) {
- throw read_cp_exception(0);
- }
-
- int pktlen = (unsigned char) rbuffer[1];
- fillBufferTo(&rbuffer, fd, 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)
-{
- const char *cbuf = static_cast<const char *>(buf);
- int w = 0;
- while (count > 0) {
- int r = write(fd, cbuf, count);
- if (r == -1) {
- if (errno == EINTR) continue;
- return r;
- }
- w += r;
- cbuf += r;
- count -= r;
- }
- return w;
-}
-
-
enum class command_t {
NONE,
START_SERVICE,
while (r > 0) {
if (rbuffer[0] >= 100) {
int pktlen = (unsigned char) rbuffer[1];
- fillBufferTo(&rbuffer, socknum, pktlen);
+ fill_buffer_to(&rbuffer, socknum, pktlen);
if (rbuffer[0] == DINIT_IP_SERVICEEVENT) {
handle_t ev_handle;
using namespace std;
if (rbuffer[0] == DINIT_RP_SERVICERECORD) {
- fillBufferTo(&rbuffer, socknum, 2 + sizeof(*handle_p));
+ fill_buffer_to(&rbuffer, socknum, 2 + sizeof(*handle_p));
rbuffer.extract((char *) handle_p, 2, sizeof(*handle_p));
if (state_p) *state_p = static_cast<service_state_t>(rbuffer[1]);
//target_state = static_cast<service_state_t>(rbuffer[2 + sizeof(handle)]);
cpbuffer<1024> rbuffer;
wait_for_reply(rbuffer, socknum);
while (rbuffer[0] == DINIT_RP_SVCINFO) {
- fillBufferTo(&rbuffer, socknum, 8);
+ fill_buffer_to(&rbuffer, socknum, 8);
int nameLen = rbuffer[1];
service_state_t current = static_cast<service_state_t>(rbuffer[2]);
service_state_t target = static_cast<service_state_t>(rbuffer[3]);
- fillBufferTo(&rbuffer, socknum, nameLen + 8);
+ fill_buffer_to(&rbuffer, socknum, nameLen + 8);
char *name_ptr = rbuffer.get_ptr(8);
int clength = std::min(rbuffer.get_contiguous_length(name_ptr), nameLen);
buf[0] = DINIT_CP_SHUTDOWN;
buf[1] = static_cast<char>(shutdown_type_t::HALT);
- // TODO make sure to write the whole buffer
- int r = write(socknum, buf, bufsize);
+ int r = write_all(socknum, buf, bufsize);
if (r == -1) {
perror("write");
return 1;
}
- // Wait for ACK/NACK
- // r = read(socknum, buf, 1);
- //if (r > 0) {
- // cout << "Received acknowledgement. System should now shut down." << endl;
- //}
-
cpbuffer<1024> rbuffer;
try {
wait_for_reply(rbuffer, socknum);
--- /dev/null
+#include <cstdint>
+
+// Client library for Dinit clients
+
+
+using handle_t = uint32_t;
+
+class read_cp_exception
+{
+ public:
+ int errcode;
+ read_cp_exception(int err) : errcode(err) { }
+};
+
+// Fill a circular buffer from a file descriptor, until it contains at least _rlength_ bytes.
+// Throws read_cp_exception 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).
+inline void fill_buffer_to(cpbuffer<1024> *buf, int fd, int rlength)
+{
+ do {
+ int r = buf->fill_to(fd, rlength);
+ if (r == -1) {
+ if (errno != EINTR) {
+ throw read_cp_exception(errno);
+ }
+ }
+ else if (r == 0) {
+ throw read_cp_exception(0);
+ }
+ else {
+ return;
+ }
+ }
+ while (true);
+}
+
+// Wait for a reply packet, skipping over any information packets that are received in the meantime.
+inline void wait_for_reply(cpbuffer<1024> &rbuffer, int fd)
+{
+ fill_buffer_to(&rbuffer, fd, 1);
+
+ while (rbuffer[0] >= 100) {
+ // Information packet; discard.
+ fill_buffer_to(&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
+ fill_buffer_to(&rbuffer, fd, pktlen);
+ rbuffer.consume(pktlen - 1);
+ }
+}
+
+// Wait for an info packet. If any other reply packet comes, throw a read_cp_exception.
+inline void wait_for_info(cpbuffer<1024> &rbuffer, int fd)
+{
+ fill_buffer_to(&rbuffer, fd, 2);
+
+ if (rbuffer[0] < 100) {
+ throw read_cp_exception(0);
+ }
+
+ int pktlen = (unsigned char) rbuffer[1];
+ fill_buffer_to(&rbuffer, fd, pktlen);
+}
+
+// Write *all* the requested buffer and re-try if necessary until
+// the buffer is written or an unrecoverable error occurs.
+inline int write_all(int fd, const void *buf, size_t count)
+{
+ const char *cbuf = static_cast<const char *>(buf);
+ int w = 0;
+ while (count > 0) {
+ int r = write(fd, cbuf, count);
+ if (r == -1) {
+ if (errno == EINTR) continue;
+ return r;
+ }
+ w += r;
+ cbuf += r;
+ count -= r;
+ }
+ return w;
+}
#include "cpbuffer.h"
#include "control-cmds.h"
#include "service-constants.h"
+#include "dinit-client.h"
// shutdown: shut down the system
// This utility communicates with the dinit daemon via a unix socket (/dev/initctl).
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);
-
-
-class ReadCPException
-{
- public:
- int errcode;
- ReadCPException(int err) : errcode(err) { }
-};
int main(int argc, char **argv)
cout << "Issuing shutdown command..." << endl;
- // TODO make sure to write the whole buffer
- int r = write(socknum, buf, bufsize);
+ int r = write_all(socknum, buf, bufsize);
if (r == -1) {
perror("write");
return 1;
return 1;
}
}
- catch (ReadCPException &exc)
+ catch (read_cp_exception &exc)
{
cerr << "shutdown: control socket read failure or protocol error" << endl;
return 1;
return 0;
}
-// 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, 2);
- 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.
void do_system_shutdown(shutdown_type_t shutdown_type)
{