tools: exit with non-zero on advertise/withdraw error

refs #5271

Change-Id: I287fc5746ac1fd2930bb85ac49e5ad732abd3581
diff --git a/tools/nlsrc.cpp b/tools/nlsrc.cpp
index 982808b..16807a7 100644
--- a/tools/nlsrc.cpp
+++ b/tools/nlsrc.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -52,6 +52,7 @@
 
 const uint32_t ERROR_CODE_TIMEOUT = 10060;
 const uint32_t RESPONSE_CODE_SUCCESS = 200;
+const uint32_t RESPONSE_CODE_NO_EFFECT = 204;
 const uint32_t RESPONSE_CODE_SAVE_OR_DELETE = 205;
 
 Nlsrc::Nlsrc(std::string programName, ndn::Face& face)
@@ -65,7 +66,7 @@
 void
 Nlsrc::printUsage() const
 {
-  std::string help(R"EOT(Usage:
+  const std::string help(R"EOT(Usage:
 @NLSRC@ [-h | -V]
 @NLSRC@ [-R <router prefix> [-c <nlsr.conf path> | -k]] COMMAND [<Command Options>]
        -h print usage and exit
@@ -90,8 +91,8 @@
        withdraw <name> delete
            withdraw and delete the name prefix from the conf file
 )EOT");
-  boost::algorithm::replace_all(help, "@NLSRC@", m_programName);
-  std::cout << help;
+  boost::algorithm::replace_all_copy(std::ostream_iterator<char>(std::cout),
+                                     help, "@NLSRC@", m_programName);
 }
 
 void
@@ -279,19 +280,21 @@
   }
   catch (const std::exception& e) {
     std::cerr << "ERROR: Control response decoding error" << std::endl;
+    m_exitCode = 1;
     return;
   }
 
   uint32_t code = response.getCode();
 
   if (code != RESPONSE_CODE_SUCCESS && code != RESPONSE_CODE_SAVE_OR_DELETE) {
-
     std::cerr << response.getText() << std::endl;
     std::cerr << "Name prefix update error (code: " << code << ")" << std::endl;
+    m_exitCode = code == RESPONSE_CODE_NO_EFFECT ? 0 : 1;
     return;
   }
 
   std::cout << "Applied Name prefix update successfully: " << info << std::endl;
+  m_exitCode = 0;
 }
 
 void
@@ -393,6 +396,7 @@
 {
   std::cerr << "Request timed out (code: " << errorCode
             << ", error: " << error << ")"  << std::endl;
+  m_exitCode = 1;
 }
 
 void
@@ -460,7 +464,7 @@
 
   if (argc < 2) {
     nlsrc.printUsage();
-    return 0;
+    return 2;
   }
 
   int opt;
@@ -485,13 +489,13 @@
       break;
     default:
       nlsrc.printUsage();
-      return 1;
+      return 2;
     }
   }
 
   if (argc == ::optind) {
     nlsrc.printUsage();
-    return 1;
+    return 2;
   }
 
   if (nlsrc.getRouterPrefix() != nlsrc::LOCALHOST_PREFIX && !disableValidator) {
@@ -500,21 +504,19 @@
     }
   }
 
-  std::vector<std::string> subcommand;
-  std::copy(&argv[::optind], &argv[argc], std::back_inserter(subcommand));
-
+  std::vector<std::string> subcommand(&argv[::optind], &argv[argc]);
   try {
-    bool isOk = nlsrc.dispatch(subcommand);
-    if (!isOk) {
+    bool isValidSyntax = nlsrc.dispatch(subcommand);
+    if (!isValidSyntax) {
       nlsrc.printUsage();
-      return 1;
+      return 2;
     }
 
     face.processEvents();
   }
   catch (const std::exception& e) {
     std::cerr << "ERROR: " << e.what() << std::endl;
-    return 2;
+    return 1;
   }
-  return 0;
+  return nlsrc.getExitCode();
 }
diff --git a/tools/nlsrc.hpp b/tools/nlsrc.hpp
index 99a441c..a64c940 100644
--- a/tools/nlsrc.hpp
+++ b/tools/nlsrc.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -68,6 +68,12 @@
   bool
   dispatch(ndn::span<std::string> subcommand);
 
+  int
+  getExitCode() const
+  {
+    return m_exitCode;
+  }
+
 private:
   void
   runNextStep();
@@ -162,6 +168,8 @@
   std::map<ndn::Name, Router> m_routers;
   std::string m_rtString;
   std::deque<std::function<void()>> m_fetchSteps;
+
+  int m_exitCode = 0;
 };
 
 } // namespace nlsrc