+
+// Check that a "load service" reply was received, and that the requested service was found.
+static int checkLoadReply(int socknum, CPBuffer<1024> &rbuffer, handle_t *handle_p, ServiceState *state_p)
+{
+ using namespace std;
+
+ if (rbuffer[0] == DINIT_RP_SERVICERECORD) {
+ fillBufferTo(&rbuffer, socknum, 2 + sizeof(*handle_p));
+ rbuffer.extract((char *) handle_p, 2, sizeof(*handle_p));
+ if (state_p) *state_p = static_cast<ServiceState>(rbuffer[1]);
+ //target_state = static_cast<ServiceState>(rbuffer[2 + sizeof(handle)]);
+ rbuffer.consume(3 + sizeof(*handle_p));
+ return 0;
+ }
+ else if (rbuffer[0] == DINIT_RP_NOSERVICE) {
+ cerr << "dinitctl: Failed to find/load service." << endl;
+ return 1;
+ }
+ else {
+ cerr << "dinitctl: Protocol error." << endl;
+ return 1;
+ }
+}
+
+static int unpinService(int socknum, const char *service_name, bool verbose)
+{
+ using namespace std;
+
+ // Build buffer;
+ if (issueLoadService(socknum, service_name) == 1) {
+ return 1;
+ }
+
+ // Now we expect a reply:
+
+ try {
+ CPBuffer<1024> rbuffer;
+ wait_for_reply(rbuffer, socknum);
+
+ handle_t handle;
+
+ if (checkLoadReply(socknum, rbuffer, &handle, nullptr) != 0) {
+ return 1;
+ }
+
+ // Issue UNPIN command.
+ {
+ int r;
+
+ {
+ char *buf = new char[1 + sizeof(handle)];
+ unique_ptr<char[]> ubuf(buf);
+ buf[0] = DINIT_CP_UNPINSERVICE;
+ memcpy(buf + 1, &handle, sizeof(handle));
+ r = write_all(socknum, buf, 2 + sizeof(handle));
+ }
+
+ if (r == -1) {
+ perror("dinitctl: write");
+ return 1;
+ }
+
+ wait_for_reply(rbuffer, socknum);
+ if (rbuffer[0] != DINIT_RP_ACK) {
+ cerr << "dinitctl: Protocol error." << endl;
+ return 1;
+ }
+ rbuffer.consume(1);
+ }
+ }
+ catch (ReadCPException &exc) {
+ cerr << "dinitctl: Control socket read failure or protocol error" << endl;
+ return 1;
+ }
+ catch (std::bad_alloc &exc) {
+ cerr << "dinitctl: Out of memory" << endl;
+ return 1;
+ }
+
+ if (verbose) {
+ cout << "Service unpinned." << endl;
+ }
+ return 0;
+}