blob: 078555e9b47a304489f6f268552ed403cbc5cafb [file] [log] [blame]
Neels Hofmeyr3a9ff112018-09-10 17:18:28 +02001/* test program with a vty interface to test logging behavior */
2/*
3 * (C) 2018 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * Author: Neels Hofmeyr <neels@hofmeyr.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#define _GNU_SOURCE
25#include <getopt.h>
26
27#include <signal.h>
28
29#include <osmocom/core/logging.h>
30#include <osmocom/core/utils.h>
31#include <osmocom/core/application.h>
32
33#include <osmocom/vty/command.h>
34#include <osmocom/vty/logging.h>
35#include <osmocom/vty/misc.h>
36#include <osmocom/vty/telnet_interface.h>
37
38#include <stdlib.h>
39
40#include "config.h"
41
42void *root_ctx = NULL;
43
44enum {
45 DAA,
46 DBB,
47 DCCC,
48 DDDDD,
49 DEEE,
50};
51
52DEFUN(log_sweep, log_sweep_cmd,
53 "log-sweep [CATEGORY]",
54 "Log once for all categories on all levels\n")
55{
56 int only_category = argc ? log_parse_category(argv[0]) : -1;
57
58 if (argc && only_category < 0) {
59 vty_out(vty, "%% Error: unknown category: %s%s", argv[0], VTY_NEWLINE);
60 return CMD_WARNING;
61 }
62
63#define LOG_LEVEL(CAT, LEVEL) \
64 if (only_category < 0 || only_category == CAT) \
65 LOGP(CAT, LEVEL, "Log message for " #CAT " on level " #LEVEL "\n")
66
67#define LOG_ALL_LEVELS(CAT) \
68 LOG_LEVEL(CAT, LOGL_DEBUG); \
69 LOG_LEVEL(CAT, LOGL_INFO); \
70 LOG_LEVEL(CAT, LOGL_NOTICE); \
71 LOG_LEVEL(CAT, LOGL_ERROR); \
72 LOG_LEVEL(CAT, LOGL_FATAL)
73
74 LOG_ALL_LEVELS(DAA);
75 LOG_ALL_LEVELS(DBB);
76 LOG_ALL_LEVELS(DCCC);
77 LOG_ALL_LEVELS(DDDDD);
78 LOG_ALL_LEVELS(DEEE);
79
80 vty_out(vty, "%s", VTY_NEWLINE);
81
82 return CMD_SUCCESS;
83}
84
85static void vty_commands_init()
86{
87 install_element_ve(&log_sweep_cmd);
88}
89
90static const struct log_info_cat default_categories[] = {
91 [DAA] = {
92 .name = "DAA",
93 .description = "Antropomorphic Armadillos (AA)",
94 .color = "\033[1;31m",
95 .enabled = 1, .loglevel = LOGL_DEBUG,
96 },
97 [DBB] = {
98 .name = "DBB",
99 .description = "Bidirectional Breadspread (BB)",
100 .color = "\033[1;32m",
101 .enabled = 1, .loglevel = LOGL_INFO,
102 },
103 [DCCC] = {
104 .name = "DCCC",
105 .description = "Chaos Communication Congress (CCC)",
106 .color = "\033[1;33m",
107 .enabled = 1, .loglevel = LOGL_NOTICE,
108 },
109 [DDDDD] = {
110 .name = "DDDDD",
111 .description = "Dehydrated Dribbling Duck Dunkers (DDDD)",
112 .color = "\033[1;34m",
113 .enabled = 1, .loglevel = LOGL_ERROR,
114 },
115 [DEEE] = {
116 .name = "DEEE",
117 .description = "Exhaustive Entropy Extraction (EEE)",
118 .color = "\033[1;35m",
119 .enabled = 1, .loglevel = LOGL_FATAL,
120 },
121};
122
123const struct log_info log_info = {
124 .cat = default_categories,
125 .num_cat = ARRAY_SIZE(default_categories),
126};
127
128static void print_help()
129{
130 printf( "options:\n"
131 " -h --help this text\n"
132 " -d --debug MASK Enable debugging (e.g. -d DRSL:DOML:DLAPDM)\n"
133 " -D --daemonize For the process into a background daemon\n"
134 " -c --config-file Specify the filename of the config file\n"
135 " -s --disable-color Don't use colors in stderr log output\n"
136 " -T --timestamp Prefix every log line with a timestamp\n"
137 " -V --version Print version information and exit\n"
138 " -e --log-level Set a global log-level\n"
139 );
140}
141
142static struct {
143 const char *config_file;
144 int daemonize;
145} cmdline_config = {};
146
147static void handle_options(int argc, char **argv)
148{
149 while (1) {
150 int option_idx = 0, c;
151 static const struct option long_options[] = {
152 { "help", 0, 0, 'h' },
153 { "debug", 1, 0, 'd' },
154 { "daemonize", 0, 0, 'D' },
155 { "config-file", 1, 0, 'c' },
156 { "disable-color", 0, 0, 's' },
157 { "timestamp", 0, 0, 'T' },
158 { "version", 0, 0, 'V' },
159 { "log-level", 1, 0, 'e' },
160 {}
161 };
162
163 c = getopt_long(argc, argv, "hc:d:Dc:sTVe:",
164 long_options, &option_idx);
165 if (c == -1)
166 break;
167
168 switch (c) {
169 case 'h':
170 print_help();
171 exit(0);
172 case 's':
173 log_set_use_color(osmo_stderr_target, 0);
174 break;
175 case 'd':
176 log_parse_category_mask(osmo_stderr_target, optarg);
177 break;
178 case 'D':
179 cmdline_config.daemonize = 1;
180 break;
181 case 'c':
182 cmdline_config.config_file = optarg;
183 break;
184 case 'T':
185 log_set_print_timestamp(osmo_stderr_target, 1);
186 break;
187 case 'e':
188 log_set_log_level(osmo_stderr_target, atoi(optarg));
189 break;
190 case 'V':
191 print_version(1);
192 exit(0);
193 break;
194 default:
195 /* catch unknown options *as well as* missing arguments. */
196 fprintf(stderr, "Error in command line options. Exiting.\n");
197 exit(-1);
198 }
199 }
200}
201
202static int quit = 0;
203
204static void signal_handler(int signal)
205{
206 fprintf(stdout, "signal %u received\n", signal);
207
208 switch (signal) {
209 case SIGINT:
210 case SIGTERM:
211 quit++;
212 break;
213 case SIGABRT:
214 osmo_generate_backtrace();
215 /* in case of abort, we want to obtain a talloc report
216 * and then return to the caller, who will abort the process */
217 case SIGUSR1:
218 talloc_report(tall_vty_ctx, stderr);
219 talloc_report_full(root_ctx, stderr);
220 break;
221 case SIGUSR2:
222 talloc_report_full(tall_vty_ctx, stderr);
223 break;
224 default:
225 break;
226 }
227}
228
229static struct vty_app_info vty_info = {
230 .name = "logging_vty_test",
231 .version = PACKAGE_VERSION,
232};
233
234int main(int argc, char **argv)
235{
236 int rc;
237
238 root_ctx = talloc_named_const(NULL, 0, "logging_vty_test");
239
240 vty_info.tall_ctx = root_ctx;
241 vty_init(&vty_info);
242
243 osmo_init_logging2(root_ctx, &log_info);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200244 log_enable_multithread();
Neels Hofmeyr3a9ff112018-09-10 17:18:28 +0200245
246 vty_commands_init();
247
248 handle_options(argc, argv);
249
Pau Espin Pedrolf65278f2019-08-05 14:10:43 +0200250 logging_vty_add_cmds();
Neels Hofmeyr3a9ff112018-09-10 17:18:28 +0200251 osmo_talloc_vty_add_cmds();
252
253 log_set_print_category(osmo_stderr_target, 1);
254 log_set_print_category_hex(osmo_stderr_target, 0);
255 log_set_print_level(osmo_stderr_target, 1);
256 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
Harald Welteb72867f2020-09-26 21:45:16 +0200257 log_target_file_switch_to_wqueue(osmo_stderr_target);
Neels Hofmeyr3a9ff112018-09-10 17:18:28 +0200258
259 if (cmdline_config.config_file) {
260 rc = vty_read_config_file(cmdline_config.config_file, NULL);
261 if (rc < 0) {
262 LOGP(DLGLOBAL, LOGL_FATAL, "Failed to parse the config file: '%s'\n",
263 cmdline_config.config_file);
264 return 1;
265 }
266 }
267
268 rc = telnet_init_dynif(root_ctx, NULL, vty_get_bind_addr(), 42042);
269 if (rc < 0)
270 return 2;
271
272 signal(SIGINT, &signal_handler);
273 signal(SIGTERM, &signal_handler);
274 signal(SIGABRT, &signal_handler);
275 signal(SIGUSR1, &signal_handler);
276 signal(SIGUSR2, &signal_handler);
277 osmo_init_ignore_signals();
278
279 if (cmdline_config.daemonize) {
280 rc = osmo_daemonize();
281 if (rc < 0) {
282 perror("Error during daemonize");
283 return 6;
284 }
285 }
286
287 while (!quit) {
288 log_reset_context();
289 osmo_select_main(0);
290 }
291
292 log_fini();
293
294 talloc_free(root_ctx);
295 talloc_free(tall_vty_ctx);
296
297 return 0;
298}