|
@@ -16,20 +16,12 @@
|
|
#include "control-cmds.h"
|
|
#include "control-cmds.h"
|
|
#include "service-constants.h"
|
|
#include "service-constants.h"
|
|
#include "cpbuffer.h"
|
|
#include "cpbuffer.h"
|
|
|
|
+#include "dinit-client.h"
|
|
|
|
|
|
// dinitctl: utility to control the Dinit daemon, including starting and stopping of services.
|
|
// 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).
|
|
// 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;
|
|
enum class command_t;
|
|
|
|
|
|
@@ -42,30 +34,6 @@ static int list_services(int socknum);
|
|
static int shutdown_dinit(int soclknum);
|
|
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)
|
|
static const char * describeState(bool stopped)
|
|
{
|
|
{
|
|
return stopped ? "stopped" : "started";
|
|
return stopped ? "stopped" : "started";
|
|
@@ -76,55 +44,6 @@ static const char * describeVerb(bool stop)
|
|
return stop ? "stop" : "start";
|
|
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 {
|
|
enum class command_t {
|
|
NONE,
|
|
NONE,
|
|
START_SERVICE,
|
|
START_SERVICE,
|
|
@@ -424,7 +343,7 @@ static int start_stop_service(int socknum, const char *service_name, command_t c
|
|
while (r > 0) {
|
|
while (r > 0) {
|
|
if (rbuffer[0] >= 100) {
|
|
if (rbuffer[0] >= 100) {
|
|
int pktlen = (unsigned char) rbuffer[1];
|
|
int pktlen = (unsigned char) rbuffer[1];
|
|
- fillBufferTo(&rbuffer, socknum, pktlen);
|
|
|
|
|
|
+ fill_buffer_to(&rbuffer, socknum, pktlen);
|
|
|
|
|
|
if (rbuffer[0] == DINIT_IP_SERVICEEVENT) {
|
|
if (rbuffer[0] == DINIT_IP_SERVICEEVENT) {
|
|
handle_t ev_handle;
|
|
handle_t ev_handle;
|
|
@@ -520,7 +439,7 @@ static int check_load_reply(int socknum, cpbuffer<1024> &rbuffer, handle_t *hand
|
|
using namespace std;
|
|
using namespace std;
|
|
|
|
|
|
if (rbuffer[0] == DINIT_RP_SERVICERECORD) {
|
|
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));
|
|
rbuffer.extract((char *) handle_p, 2, sizeof(*handle_p));
|
|
if (state_p) *state_p = static_cast<service_state_t>(rbuffer[1]);
|
|
if (state_p) *state_p = static_cast<service_state_t>(rbuffer[1]);
|
|
//target_state = static_cast<service_state_t>(rbuffer[2 + sizeof(handle)]);
|
|
//target_state = static_cast<service_state_t>(rbuffer[2 + sizeof(handle)]);
|
|
@@ -678,12 +597,12 @@ static int list_services(int socknum)
|
|
cpbuffer<1024> rbuffer;
|
|
cpbuffer<1024> rbuffer;
|
|
wait_for_reply(rbuffer, socknum);
|
|
wait_for_reply(rbuffer, socknum);
|
|
while (rbuffer[0] == DINIT_RP_SVCINFO) {
|
|
while (rbuffer[0] == DINIT_RP_SVCINFO) {
|
|
- fillBufferTo(&rbuffer, socknum, 8);
|
|
|
|
|
|
+ fill_buffer_to(&rbuffer, socknum, 8);
|
|
int nameLen = rbuffer[1];
|
|
int nameLen = rbuffer[1];
|
|
service_state_t current = static_cast<service_state_t>(rbuffer[2]);
|
|
service_state_t current = static_cast<service_state_t>(rbuffer[2]);
|
|
service_state_t target = static_cast<service_state_t>(rbuffer[3]);
|
|
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);
|
|
char *name_ptr = rbuffer.get_ptr(8);
|
|
int clength = std::min(rbuffer.get_contiguous_length(name_ptr), nameLen);
|
|
int clength = std::min(rbuffer.get_contiguous_length(name_ptr), nameLen);
|
|
@@ -746,19 +665,12 @@ static int shutdown_dinit(int socknum)
|
|
buf[0] = DINIT_CP_SHUTDOWN;
|
|
buf[0] = DINIT_CP_SHUTDOWN;
|
|
buf[1] = static_cast<char>(shutdown_type_t::HALT);
|
|
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) {
|
|
if (r == -1) {
|
|
perror("write");
|
|
perror("write");
|
|
return 1;
|
|
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;
|
|
cpbuffer<1024> rbuffer;
|
|
try {
|
|
try {
|
|
wait_for_reply(rbuffer, socknum);
|
|
wait_for_reply(rbuffer, socknum);
|