blob: 89b4f58dc9a844db10fbf83f7281994a5467e3c2 [file] [log] [blame]
Artem Senichevefd5d742018-10-24 16:14:04 +03001/**
2 * @brief Host logger service entry point.
3 *
4 * This file is part of HostLogger project.
5 *
6 * Copyright (c) 2018 YADRO
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include "config.hpp"
22#include "dbus_server.hpp"
23#include "dbus_watch.hpp"
24#include "log_manager.hpp"
Patrick Venture4d5a5dc2018-11-14 08:51:13 -080025
Artem Senichevefd5d742018-10-24 16:14:04 +030026#include <getopt.h>
Patrick Venture4d5a5dc2018-11-14 08:51:13 -080027
28#include <climits>
Artem Senichevefd5d742018-10-24 16:14:04 +030029#include <cstdio>
30#include <cstdlib>
Artem Senichevefd5d742018-10-24 16:14:04 +030031
32// Global logger configuration instance
Patrick Venture4d5a5dc2018-11-14 08:51:13 -080033Config loggerConfig = {.path = LOG_OUTPUT_PATH,
34 .storageSizeLimit = LOG_STORAGE_SIZE_LIMIT,
35 .storageTimeLimit = LOG_STORAGE_TIME_LIMIT,
36 .flushPeriod = LOG_FLUSH_PERIOD,
37 .rotationLimit = LOG_ROTATION_LIMIT};
Artem Senichevefd5d742018-10-24 16:14:04 +030038
39/** @brief Print title with version info. */
40static void printTitle()
41{
42 printf("Host logger service " PACKAGE_VERSION ".\n");
43}
44
Artem Senichevefd5d742018-10-24 16:14:04 +030045/** @brief Print help usage info.
46 *
47 * @param[in] app - application's file name
48 */
49static void printHelp(const char* app)
50{
51 printTitle();
52 printf("Copyright (c) 2018 YADRO.\n");
53 printf("Usage: %s [options]\n", app);
Patrick Venture4d5a5dc2018-11-14 08:51:13 -080054 printf(
55 "Options (defaults are specified in brackets):\n"
56 " -p, --path=PATH Path used to store logs [%s]\n"
57 "Intermediate storage buffer capacity setup:\n"
58 " -s, --szlimit=N Store up to N last messages [%i], 0=unlimited\n"
59 " -t, --tmlimit=N Store messages for last N hours [%i], "
60 "0=unlimited\n"
61 "Flush storage buffer policy:\n"
62 " -f, --flush=N Flush logs every N hours [%i]\n"
63 " If this option is set to 0 flush will be called "
64 "at\n"
65 " every host state change event from D-Bus.\n"
66 "Log files rotation policy:\n"
67 " -r, --rotate=N Store up to N files in the log directory [%i],\n"
68 " 0=unlimited\n"
69 "Common options:\n"
70 " -v, --version Print version and exit\n"
71 " -h, --help Print this help and exit\n",
72 loggerConfig.path, loggerConfig.storageSizeLimit,
73 loggerConfig.storageTimeLimit, loggerConfig.flushPeriod,
74 loggerConfig.rotationLimit);
Artem Senichevefd5d742018-10-24 16:14:04 +030075}
76
Artem Senichevefd5d742018-10-24 16:14:04 +030077/** @brief Get numeric positive value from string argument.
78 *
79 * @param[in] param - parameter name
80 * @param[in] arg - parameter text value
81 *
82 * @return positive numeric value from string argument or -1 on errors
83 */
84static int getNumericArg(const char* param, const char* arg)
85{
86 char* ep = nullptr;
87 const unsigned long val = strtoul(arg, &ep, 0);
Patrick Venture4d5a5dc2018-11-14 08:51:13 -080088 if (val > INT_MAX || !ep || ep == arg || *ep != 0)
89 {
90 fprintf(stderr, "Invalid %s param: %s, expected 0<=N<=%i\n", param, arg,
91 INT_MAX);
Artem Senichevefd5d742018-10-24 16:14:04 +030092 return -1;
93 }
94 return static_cast<int>(val);
95}
96
Artem Senichevefd5d742018-10-24 16:14:04 +030097/** @brief Application entry point. */
Patrick Venture4d5a5dc2018-11-14 08:51:13 -080098int main(int argc, char* argv[])
Artem Senichevefd5d742018-10-24 16:14:04 +030099{
100 int opt_val;
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800101 // clang-format off
Artem Senichevefd5d742018-10-24 16:14:04 +0300102 const struct option opts[] = {
103 { "path", required_argument, 0, 'p' },
104 { "szlimit", required_argument, 0, 's' },
105 { "tmlimit", required_argument, 0, 't' },
106 { "flush", required_argument, 0, 'f' },
107 { "rotate", required_argument, 0, 'r' },
108 { "version", no_argument, 0, 'v' },
109 { "help", no_argument, 0, 'h' },
110 { 0, 0, 0, 0 }
111 };
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800112 // clang-format on
Artem Senichevefd5d742018-10-24 16:14:04 +0300113
114 opterr = 0;
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800115 while ((opt_val = getopt_long(argc, argv, "p:s:t:f:r:vh", opts, NULL)) !=
116 -1)
117 {
118 switch (opt_val)
119 {
Artem Senichevefd5d742018-10-24 16:14:04 +0300120 case 'p':
121 loggerConfig.path = optarg;
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800122 if (*loggerConfig.path != '/')
123 {
124 fprintf(stderr,
125 "Invalid directory: %s, expected absolute path\n",
126 loggerConfig.path);
Artem Senichevefd5d742018-10-24 16:14:04 +0300127 return EXIT_FAILURE;
128 }
129 break;
130 case 's':
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800131 loggerConfig.storageSizeLimit =
132 getNumericArg(opts[optind - 1].name, optarg);
Artem Senichevefd5d742018-10-24 16:14:04 +0300133 if (loggerConfig.storageSizeLimit < 0)
134 return EXIT_FAILURE;
135 break;
136 case 't':
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800137 loggerConfig.storageTimeLimit =
138 getNumericArg(opts[optind - 1].name, optarg);
Artem Senichevefd5d742018-10-24 16:14:04 +0300139 if (loggerConfig.storageTimeLimit < 0)
140 return EXIT_FAILURE;
141 break;
142 case 'f':
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800143 loggerConfig.flushPeriod =
144 getNumericArg(opts[optind - 1].name, optarg);
Artem Senichevefd5d742018-10-24 16:14:04 +0300145 if (loggerConfig.flushPeriod < 0)
146 return EXIT_FAILURE;
147 break;
148 case 'r':
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800149 loggerConfig.rotationLimit =
150 getNumericArg(opts[optind - 1].name, optarg);
Artem Senichevefd5d742018-10-24 16:14:04 +0300151 if (loggerConfig.rotationLimit < 0)
152 return EXIT_FAILURE;
153 break;
154 case 'v':
155 printTitle();
156 return EXIT_SUCCESS;
157 case 'h':
158 printHelp(argv[0]);
159 return EXIT_SUCCESS;
160 default:
161 fprintf(stderr, "Invalid option: %s\n", argv[optind - 1]);
162 return EXIT_FAILURE;
163 }
164 }
165
166 int rc;
167
168 // Initialize log manager
169 LogManager logManager;
170 rc = logManager.openHostLog();
171 if (rc != 0)
172 return rc;
173
174 // Initialize D-Bus server
175 sdbusplus::bus::bus bus = sdbusplus::bus::new_default();
176 sd_event* event = nullptr;
177 rc = sd_event_default(&event);
Patrick Venture4d5a5dc2018-11-14 08:51:13 -0800178 if (rc < 0)
179 {
Artem Senichevefd5d742018-10-24 16:14:04 +0300180 fprintf(stderr, "Error occurred during the sd_event_default: %i\n", rc);
181 return EXIT_FAILURE;
182 }
183 EventPtr eventPtr(event);
184 bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
185
186 DbusServer dbusMgr(logManager, bus);
187 bus.request_name(HOSTLOGGER_DBUS_IFACE);
188
189 // Initialize D-Bus watcher
190 DbusWatcher dbusWatch(logManager, bus);
191 rc = dbusWatch.initialize();
192 if (rc < 0)
193 return EXIT_FAILURE;
194
195 // D-Bus event processing
196 rc = sd_event_loop(eventPtr.get());
197 if (rc != 0)
198 fprintf(stderr, "Error occurred during the sd_event_loop: %i\n", rc);
199
200 return rc ? rc : -1; // Allways retrun an error code
201}