Initial commit

Signed-off-by: Artem Senichev <a.senichev@yadro.com>
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..7f58ef0
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,191 @@
+/**
+ * @brief Host logger service entry point.
+ *
+ * This file is part of HostLogger project.
+ *
+ * Copyright (c) 2018 YADRO
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.hpp"
+#include "dbus_server.hpp"
+#include "dbus_watch.hpp"
+#include "log_manager.hpp"
+#include <getopt.h>
+#include <cstdio>
+#include <cstdlib>
+#include <climits>
+
+
+// Global logger configuration instance
+Config loggerConfig = {
+    .path = LOG_OUTPUT_PATH,
+    .storageSizeLimit = LOG_STORAGE_SIZE_LIMIT,
+    .storageTimeLimit = LOG_STORAGE_TIME_LIMIT,
+    .flushPeriod = LOG_FLUSH_PERIOD,
+    .rotationLimit = LOG_ROTATION_LIMIT
+};
+
+
+/** @brief Print title with version info. */
+static void printTitle()
+{
+    printf("Host logger service " PACKAGE_VERSION ".\n");
+}
+
+
+/** @brief Print help usage info.
+ *
+ *  @param[in] app - application's file name
+ */
+static void printHelp(const char* app)
+{
+    printTitle();
+    printf("Copyright (c) 2018 YADRO.\n");
+    printf("Usage: %s [options]\n", app);
+    printf("Options (defaults are specified in brackets):\n"
+           "  -p, --path=PATH   Path used to store logs [%s]\n"
+           "Intermediate storage buffer capacity setup:\n"
+           "  -s, --szlimit=N   Store up to N last messages [%i], 0=unlimited\n"
+           "  -t, --tmlimit=N   Store messages for last N hours [%i], 0=unlimited\n"
+           "Flush storage buffer policy:\n"
+           "  -f, --flush=N     Flush logs every N hours [%i]\n"
+           "                    If this option is set to 0 flush will be called at\n"
+           "                    every host state change event from D-Bus.\n"
+           "Log files rotation policy:\n"
+           "  -r, --rotate=N    Store up to N files in the log directory [%i],\n"
+           "                    0=unlimited\n"
+           "Common options:\n"
+           "  -v, --version     Print version and exit\n"
+           "  -h, --help        Print this help and exit\n",
+           loggerConfig.path,
+           loggerConfig.storageSizeLimit,
+           loggerConfig.storageTimeLimit,
+           loggerConfig.flushPeriod,
+           loggerConfig.rotationLimit);
+}
+
+
+/** @brief Get numeric positive value from string argument.
+ *
+ *  @param[in] param - parameter name
+ *  @param[in] arg - parameter text value
+ *
+ *  @return positive numeric value from string argument or -1 on errors
+ */
+static int getNumericArg(const char* param, const char* arg)
+{
+    char* ep = nullptr;
+    const unsigned long val = strtoul(arg, &ep, 0);
+    if (val > INT_MAX || !ep || ep == arg || *ep != 0) {
+        fprintf(stderr, "Invalid %s param: %s, expected 0<=N<=%i\n",
+                param, arg, INT_MAX);
+        return -1;
+    }
+    return static_cast<int>(val);
+}
+
+
+/** @brief Application entry point. */
+int main(int argc, char *argv[])
+{
+    int opt_val;
+    const struct option opts[] = {
+        { "path",    required_argument, 0, 'p' },
+        { "szlimit", required_argument, 0, 's' },
+        { "tmlimit", required_argument, 0, 't' },
+        { "flush",   required_argument, 0, 'f' },
+        { "rotate",  required_argument, 0, 'r' },
+        { "version", no_argument,       0, 'v' },
+        { "help",    no_argument,       0, 'h' },
+        { 0,         0,                 0,  0  }
+    };
+
+    opterr = 0;
+    while ((opt_val = getopt_long(argc, argv, "p:s:t:f:r:vh", opts, NULL)) != -1) {
+        switch (opt_val) {
+            case 'p':
+                loggerConfig.path = optarg;
+                if (*loggerConfig.path != '/') {
+                    fprintf(stderr, "Invalid directory: %s, expected absolute path\n", loggerConfig.path);
+                    return EXIT_FAILURE;
+                }
+                break;
+            case 's':
+                loggerConfig.storageSizeLimit = getNumericArg(opts[optind - 1].name, optarg);
+                if (loggerConfig.storageSizeLimit < 0)
+                    return EXIT_FAILURE;
+                break;
+            case 't':
+                loggerConfig.storageTimeLimit = getNumericArg(opts[optind - 1].name, optarg);
+                if (loggerConfig.storageTimeLimit < 0)
+                    return EXIT_FAILURE;
+                break;
+            case 'f':
+                loggerConfig.flushPeriod = getNumericArg(opts[optind - 1].name, optarg);
+                if (loggerConfig.flushPeriod < 0)
+                    return EXIT_FAILURE;
+                break;
+            case 'r':
+                loggerConfig.rotationLimit = getNumericArg(opts[optind - 1].name, optarg);
+                if (loggerConfig.rotationLimit < 0)
+                    return EXIT_FAILURE;
+                break;
+            case 'v':
+                printTitle();
+                return EXIT_SUCCESS;
+            case 'h':
+                printHelp(argv[0]);
+                return EXIT_SUCCESS;
+            default:
+                fprintf(stderr, "Invalid option: %s\n", argv[optind - 1]);
+                return EXIT_FAILURE;
+        }
+    }
+
+    int rc;
+
+    // Initialize log manager
+    LogManager logManager;
+    rc = logManager.openHostLog();
+    if (rc != 0)
+        return rc;
+
+    // Initialize D-Bus server
+    sdbusplus::bus::bus bus = sdbusplus::bus::new_default();
+    sd_event* event = nullptr;
+    rc = sd_event_default(&event);
+    if (rc < 0) {
+        fprintf(stderr, "Error occurred during the sd_event_default: %i\n", rc);
+        return EXIT_FAILURE;
+    }
+    EventPtr eventPtr(event);
+    bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
+
+    DbusServer dbusMgr(logManager, bus);
+    bus.request_name(HOSTLOGGER_DBUS_IFACE);
+
+    // Initialize D-Bus watcher
+    DbusWatcher dbusWatch(logManager, bus);
+    rc = dbusWatch.initialize();
+    if (rc < 0)
+        return EXIT_FAILURE;
+
+    // D-Bus event processing
+    rc = sd_event_loop(eventPtr.get());
+    if (rc != 0)
+        fprintf(stderr, "Error occurred during the sd_event_loop: %i\n", rc);
+
+    return rc ? rc : -1; // Allways retrun an error code
+}