Add a level of indirection when naming the DBUS objects

The current design ignores the itemX_label sysfs attribute, if the
environment variable is populated with the MODE_itemX="label", then
fetch the label from itemX_label file.The actual label for the dbus
object is fetched from the environment variable LABEL_item<label>.

Resolves openbmc/openbmc#1633

Change-Id: I0d4baaa91073dd5db75ac62277d78ad9b3065e64
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/env.cpp b/env.cpp
index d77200e..5745e16 100644
--- a/env.cpp
+++ b/env.cpp
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-#include <string>
 #include <cstdlib>
+#include <fstream>
+#include <string>
+#include "hwmon.hpp"
 #include "sensorset.hpp"
 
 std::string getEnv(
@@ -37,4 +39,45 @@
     return value;
 }
 
+std::string getIndirectLabelEnv(
+    const char* prefix, std::string path, const SensorSet::key_type& sensor)
+{
+    std::string key;
+    std::string value;
+
+    path.append(sensor.first);
+    path.append(sensor.second);
+    path.append(1, '_');
+    path.append(hwmon::entry::label);
+
+    std::ifstream handle(path.c_str());
+    if (handle.fail())
+    {
+        return value;
+    }
+
+    std::string content(
+        (std::istreambuf_iterator<char>(handle)),
+        (std::istreambuf_iterator<char>()));
+
+    if (content.empty())
+    {
+        return value;
+    }
+
+    content.pop_back();
+
+    key.assign(prefix);
+    key.append(1, '_');
+    key.append(sensor.first);
+    key.append(content);
+    auto env = getenv(key.c_str());
+    if (env)
+    {
+        value.assign(env);
+    }
+
+    return value;
+}
+
 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
diff --git a/env.hpp b/env.hpp
index 20db257..6442468 100644
--- a/env.hpp
+++ b/env.hpp
@@ -4,3 +4,19 @@
 
 std::string getEnv(
     const char* prefix, const SensorSet::key_type& sensor);
+
+/** @brief Get the label for the sensor with a level of indirection.
+ *
+ *  Read the sensor number from the <path>/<item><X>_label file.<item> & <X> is
+ *  populated from the sensor key. The sensor label is read from the environment
+ *  variable <prefix>_<item><sensorNum>.
+ *
+ *  @param[in] prefix - Prefix of the environment variable.
+ *  @param[in] path - Directory path of the label file.
+ *  @param[in] sensor - Sensor details.
+ *
+ *  @return On success return the sensor label, in case of failure return empty
+ *          string.
+ */
+std::string getIndirectLabelEnv(
+    const char* prefix, std::string path, const SensorSet::key_type& sensor);
diff --git a/mainloop.cpp b/mainloop.cpp
index 1da6b69..5976307 100644
--- a/mainloop.cpp
+++ b/mainloop.cpp
@@ -212,13 +212,34 @@
 
     for (auto& i : *sensors)
     {
-        // Get sensor configuration from the environment.
+        std::string label;
 
-        // Ignore inputs without a label.
-        auto label = getEnv("LABEL", i.first);
-        if (label.empty())
+        /*
+         * Check if the value of the MODE_<item><X> env variable for the sensor
+         * is "label", then read the sensor number from the <item><X>_label
+         * file. The name of the DBUS object would be the value of the env
+         * variable LABEL_<item><sensorNum>. If the MODE_<item><X> env variable
+         * does'nt exist, then the name of DBUS object is the value of the env
+         * variable LABEL_<item><X>.
+         */
+        auto mode = getEnv("MODE", i.first);
+        if (!mode.compare(hwmon::entry::label))
         {
-            continue;
+            label = getIndirectLabelEnv(
+                "LABEL", _hwmonRoot + '/' + _instance + '/', i.first);
+            if (label.empty())
+            {
+                continue;
+            }
+        }
+        else
+        {
+            // Ignore inputs without a label.
+            label = getEnv("LABEL", i.first);
+            if (label.empty())
+            {
+                continue;
+            }
         }
 
         Attributes attrs;