| /** |
| * @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 |
| } |