Add --continue argument

The monitor will exit when key is pressed.
Add --continue argument and if it is set to "true", the monitor will
continue after key is pressed.

This is useful in cases to monitor a button presses.
E.g. It can be used to monitor ID button and start a system unit
everytime when the button is pressed.

This argument is optional so it does not break the current code.

Tested: With "--continue=true", the monitor does not exit when the key
        is pressed.
        Without the argument of if it is set to other strings, the
        monitor exits after the key is pressed.

Change-Id: I4f2ca16d7b26e10397181c83c2c5947ed5ce091f
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/argument.cpp b/argument.cpp
index 41cf6f7..d388001 100644
--- a/argument.cpp
+++ b/argument.cpp
@@ -37,6 +37,7 @@
     { "key",      required_argument,  nullptr,   'k' },
     { "polarity", required_argument,  nullptr,   'r' },
     { "target",   required_argument,  nullptr,   't' },
+    { "continue", optional_argument,  nullptr,   'c' },
     { "help",     no_argument,        nullptr,   'h' },
     { 0, 0, 0, 0},
 };
@@ -60,7 +61,10 @@
 
         if (i->val)
         {
-            arguments[i->name] = (i->has_arg ? optarg : trueString);
+            // optinal argument may get nullptr for optarg
+            // make it empty string in such case
+            auto arg = (optarg == nullptr ? "" : optarg);
+            arguments[i->name] = (i->has_arg ? arg : trueString);
         }
     }
 }
@@ -90,6 +94,8 @@
                                             " This is 0 / 1 \n";
     std::cerr << "  --target=<systemd unit> Systemd unit to be called on GPIO"
                                             " state change\n";
+    std::cerr << "  --continue=[true]       Whether or not to continue"
+                                            " after key pressed\n";
 }
 } // namespace gpio
 } // namespace phosphor
diff --git a/mainapp.cpp b/mainapp.cpp
index 1dd7e80..9ecaad2 100644
--- a/mainapp.cpp
+++ b/mainapp.cpp
@@ -62,6 +62,9 @@
     // on meeting a condition.
     auto target = (options)["target"];
 
+    bool continueRun =
+      (options["continue"] == phosphor::gpio::ArgumentParser::trueString);
+
     sd_event* event = nullptr;
     auto r = sd_event_default(&event);
     if (r < 0)
@@ -73,8 +76,12 @@
     event = nullptr;
 
     // Create a monitor object and let it do all the rest
-    phosphor::gpio::Monitor monitor(path, std::stoi(key),
-                                    std::stoi(polarity), target, eventP);
+    phosphor::gpio::Monitor monitor(path,
+                                    std::stoi(key),
+                                    std::stoi(polarity),
+                                    target,
+                                    eventP,
+                                    continueRun);
 
     // Wait for client requests until this application has processed
     // at least one expected GPIO state change
diff --git a/monitor.cpp b/monitor.cpp
index 5bc4742..159127d 100644
--- a/monitor.cpp
+++ b/monitor.cpp
@@ -86,9 +86,12 @@
                     bus.call_noreply(method);
                 }
 
-                // This marks the completion of handling the gpio assertion
-                // and the app can exit
-                complete = true;
+                if (!continueAfterKeyPress)
+                {
+                    // This marks the completion of handling the gpio assertion
+                    // and the app can exit
+                    complete = true;
+                }
                 return;
             }
         }
diff --git a/monitor.hpp b/monitor.hpp
index 1dcef79..f4b07de 100644
--- a/monitor.hpp
+++ b/monitor.hpp
@@ -34,6 +34,7 @@
          *  @param[in] target   - systemd unit to be started on GPIO
          *                        value change
          *  @param[in] event    - sd_event handler
+         *  @param[in] continueRun - Whether to continue after key pressed
          *  @param[in] handler  - IO callback handler. Defaults to one in this
          *                        class
          *  @param[in] useEvDev - Whether to use EvDev to retrieve events
@@ -43,11 +44,13 @@
                 decltype(input_event::value) polarity,
                 const std::string& target,
                 EventPtr& event,
+                bool continueRun,
                 sd_event_io_handler_t handler = Monitor::processEvents,
                 bool useEvDev = true)
             : Evdev(path, key, event, handler, useEvDev),
               polarity(polarity),
-              target(target) {};
+              target(target),
+              continueAfterKeyPress(continueRun) {};
 
         /** @brief Callback handler when the FD has some activity on it
          *
@@ -75,6 +78,9 @@
         /** @brief Systemd unit to be started when the condition is met */
         const std::string& target;
 
+        /** @brief If the monitor should continue after key press */
+        bool continueAfterKeyPress;
+
         /** @brief Completion indicator */
         bool complete = false;
 
diff --git a/test/utest.cpp b/test/utest.cpp
index c6b6f18..a023cde 100644
--- a/test/utest.cpp
+++ b/test/utest.cpp
@@ -71,7 +71,7 @@
 
     const std::string emptyTarget = "";
     Monitor gpio(DEVICE, code, value, emptyTarget,
-                 eventP, callbackHandler, false);
+                 eventP, false, callbackHandler, false);
 
     // Waiting 3 seconds and check if the completion status is set
     int count = 0;
@@ -100,7 +100,7 @@
 
     const std::string emptyTarget = "";
     Monitor gpio(DEVICE, code, value, emptyTarget,
-                 eventP, callbackHandler, false);
+                 eventP, false, callbackHandler, false);
 
     // Pump the data in the middle
     int count = 0;