lots of things changed, see ChangeLog
[lwes-journaller/github-mirror.git] / src / opt.c
blobaac777664562787e452e377fbae12cf2091e8d6a
1 /*======================================================================*
2 * Copyright (c) 2008, Yahoo! Inc. All rights reserved. *
3 * Copyright (c) 2010-2016, OpenX Inc. All rights reserved. *
4 * *
5 * Licensed under the New BSD License (the "License"); you may not use *
6 * this file except in compliance with the License. Unless required *
7 * by applicable law or agreed to in writing, software distributed *
8 * under the License is distributed on an "AS IS" BASIS, WITHOUT *
9 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
10 * See the License for the specific language governing permissions and *
11 * limitations under the License. See accompanying LICENSE file. *
12 *======================================================================*/
14 #define _GNU_SOURCE
15 #include "config.h"
17 #include "log.h"
18 #include "opt.h"
20 #if HAVE_LIBGEN_H
21 #include <libgen.h>
22 #endif
24 #include <string.h>
25 #include <popt.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <pwd.h>
31 /* Base program name from argv[0]. */
32 char* arg_basename = 0;
34 /* Set default queue type, types in preferred order. */
35 #if HAVE_MQUEUE_H
36 const char* arg_queue_type = ARG_MQ;
37 #elif HAVE_SYS_MSG_H
38 const char* arg_queue_type = ARG_MSG;
39 #else
40 #error No kernel message queue support on this platform.
41 #endif
43 /* Queue parameters. */
44 const char* arg_queue_name = "/lwes_journal";
45 int arg_queue_max_sz = 64*1024 - 1;
46 int arg_queue_max_cnt = 10000;
48 #if HAVE_LIBZ
49 const char* arg_journ_type = ARG_GZ;
50 #else
51 const char* arg_journ_type = ARG_FILE;
52 #endif
54 #if HAVE_PTHREAD_H
55 const char* arg_proc_type = ARG_THREAD;
56 #else
57 const char* arg_proc_type = ARG_PROCESS;
58 #endif
60 /* network transport parameters */
61 const char* arg_xport = "udp";
62 const char* arg_ip = "224.0.0.69";
63 int arg_port = 9191;
64 const char* arg_interface = NULL;
65 int arg_sockbuffer = 16*1024*1024;
66 int arg_ttl = 16 ;
68 /* Set the logging level, see log.h. */
69 int arg_log_level = LOG_MASK_ERROR
70 | LOG_MASK_WARNING
71 | LOG_MASK_INFO;
72 const char* arg_log_file = NULL;
74 int arg_rt = 0;
76 /* site ID used to set various config items from config file. */
77 int arg_site = 1;
79 /* intended owner of journal files */
80 int arg_journal_uid = 0;
81 const char* arg_journal_user = NULL;
83 /* Queue report interval. */
84 int arg_queue_test_interval = 10000;
86 const char* arg_pid_file = "/var/run/lwes-journaller.pid";
88 /* Journals specified and number of journals specified. */
89 char** arg_journalls;
90 int arg_njournalls;
91 char* arg_disk_journals[10];
93 /* Journal rotate interval in seconds (will attempt to rotate on
94 * round intervals starting at beginning of day)
96 int arg_journal_rotate_interval = 0;
97 int arg_wakup_interval_ms = WAKEUP_MS;
99 int arg_nodaemonize = 0;
101 /* Print version, then exit. */
102 int arg_version;
104 /* Print args to sub-programs, then exit. */
105 int arg_args;
107 #ifdef HAVE_MONDEMAND
108 const char* arg_mondemand_host = NULL;
109 const char* arg_mondemand_ip = NULL;
110 int arg_mondemand_port = 20402;
111 const char* arg_mondemand_program_id = "lwes-journaller";
112 #endif
114 void process_options(int argc, const char* argv[])
116 static const struct poptOption options[] = {
117 { "args", 0, POPT_ARG_NONE, &arg_args, 0, "Print command line arguments, then exit", 0 },
118 { "nodaemonize", 0, POPT_ARG_NONE, &arg_nodaemonize, 0, "Don't run in the background", 0 },
119 { "log-level", 0, POPT_ARG_INT, &arg_log_level, 0, "Set the output logging level - OFF=(1), ERROR=(2), WARNING=(4), INFO=(8), PROGRESS=(16)", "mask" },
120 { "log-file", 0, POPT_ARG_STRING, &arg_log_file, 0, "Set the output log file", "file" },
121 { "interface", 'I', POPT_ARG_STRING, &arg_interface, 0, "Network interface to listen on", "ip" },
122 { "queue-test-interval", 'q', POPT_ARG_INT, &arg_queue_test_interval, 0, "Queue depth test interval for serial mode (dflt=10000)", "milliseconds" },
123 { "address", 'm', POPT_ARG_STRING, &arg_ip, 0, "IP address", "ip" },
124 { "journal-type", 'j', POPT_ARG_STRING, &arg_journ_type, 0, "Journal type", "{" ARG_GZ "," ARG_FILE "}" },
125 { "journal-rotate-interval", 'i', POPT_ARG_INT, &arg_journal_rotate_interval, 0, "Journal rotation interval in seconds (default off)", 0 },
126 { "pid-file", 'f', POPT_ARG_STRING, &arg_pid_file, 0, "PID file, dflt=NULL", "path" },
127 { "port", 'p', POPT_ARG_INT, &arg_port, 0, "Port number to listen on, dflt=9191", "short" },
128 { "thread-type", 't', POPT_ARG_STRING, &arg_proc_type, 0, "Threading model, '" ARG_THREAD "' or '" ARG_PROCESS "' or '" ARG_SERIAL "', dflt="
129 #if HAVE_PTHREAD_H
130 ARG_THREAD
131 #else
132 ARG_PROCESS
133 #endif
134 , 0 },
135 { "queue-max-cnt", 0, POPT_ARG_INT, &arg_queue_max_cnt, 0, "Max messages for queue, dflt=10000", "int" },
136 { "queue-max-sz", 0, POPT_ARG_INT, &arg_queue_max_sz, 0, "Max message size for queue, dflt=65535", "int" },
137 { "queue-name", 'Q', POPT_ARG_STRING, &arg_queue_name, 0, "Queue name, should start with '/', dflt='/lwes_journal'", "string" },
138 { "queue-type", 'q', POPT_ARG_STRING, &arg_queue_type, 0, "Queue type", "{" ARG_MSG "," ARG_MQ "}" },
139 { "real-time", 'R', POPT_ARG_NONE, &arg_rt, 0, "Run threads with real-time priority", 0 },
140 { "site", 'n', POPT_ARG_INT, &arg_site, 0, "Site id", "int" },
141 { "sockbuffer", 0, POPT_ARG_INT, &arg_sockbuffer, 0, "Receive socket buffer size", "bytes" },
142 { "ttl", 0, POPT_ARG_INT, &arg_ttl, 0, "Emitting TTL value", "hops" },
143 { "wakeup", 'w', POPT_ARG_INT, &arg_wakup_interval_ms, 0, "How often to break checking for signals", "milliseconds" },
144 { "user", 0, POPT_ARG_STRING, &arg_journal_user, 0, "Owner of journal files", "user" },
145 { "version", 'v', POPT_ARG_NONE, &arg_version, 0, "Display version, then exit", 0 },
146 { "xport-type", 'x', POPT_ARG_STRING, &arg_xport, 0, "Transport, dflt=udp", "{" ARG_UDP ", ...}" },
147 #ifdef HAVE_MONDEMAND
148 { "mondemand-host", 0, POPT_ARG_STRING, &arg_mondemand_host, 0, "Mondemand monitoring host", "string" },
149 { "mondemand-ip", 0, POPT_ARG_STRING, &arg_mondemand_ip, 0, "Mondemand monitoring ip", "ip-address" },
150 { "mondemand-port", 0, POPT_ARG_INT, &arg_mondemand_port, 0, "Mondemand monitoring port dflt=20402", "port" },
151 { "mondemand-program-id", 0, POPT_ARG_STRING, &arg_mondemand_program_id, 0, "Mondemand program id (default is 'lwes-journaller')", "program-id" },
152 #endif
154 POPT_AUTOHELP
155 { NULL, 0, 0, NULL, 0, NULL, NULL }};
157 int bad_options = 0;
158 int rc;
160 #if HAVE_LIBGEN_H
161 arg_basename = basename((char*)argv[0]);
162 #else
163 arg_basename = (char*)argv[0];
164 #endif
166 poptContext optCon = poptGetContext(NULL, argc, argv, options, 0);
167 poptSetOtherOptionHelp(optCon, "");
169 while ( (rc = poptGetNextOpt(optCon)) != -1 )
171 if ( rc < 0 )
173 switch ( rc )
175 case POPT_ERROR_BADOPT:
176 /* You might waht to check options of other types here... */
178 default:
179 LOG_ER("%s: %s\n",
180 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
181 poptStrerror(rc));
182 ++bad_options;
187 arg_journalls = (char**) poptGetArgs(optCon);
189 /* Count the journals specified on the command line. */
190 if ( arg_journalls )
192 for ( arg_njournalls=0; arg_journalls[arg_njournalls]; ++arg_njournalls )
196 /* Use default journal spec if none provided on the command line. */
197 if ( 0 == arg_njournalls )
199 static const char* default_arg_journalls[] = { "/tmp/all_events.log.gz",
200 NULL };
201 arg_journalls = (char**) default_arg_journalls;
202 arg_njournalls = 1;
205 /* convert the journal file username to a uid */
206 if ( arg_journal_user != NULL)
208 struct passwd *pw_entry = getpwnam(arg_journal_user);
209 if (pw_entry==NULL)
211 LOG_ER("%s was told to use a file owner (%s) that could not be found\n",
212 arg_basename, arg_journal_user);
213 ++bad_options;
215 else
217 arg_journal_uid = pw_entry->pw_uid;
220 else
222 /* default to the effective id of the user */
223 arg_journal_uid = geteuid();
226 if ( arg_version )
228 printf("The packet journaller is a program for recording LWES\n"
229 "messages for later processing.\n"
230 "\n"
231 "It listens for UDP packets on an interface/IP address/port\n"
232 "combination and writes them to an optionally compressed\n"
233 "packet journal file.\n"
234 "\n"
235 "It adds a 22 bytes header with the packet size and sender\n"
236 "information. See the README file for additional details.\n"
237 "\n"
238 "The journaller looks at the \"message type\" in each received\n"
239 "packet and will rotate the logs if it matches\n"
240 "\"Command::Rotate\".\n"
241 "\n"
244 printf("Compile time features: \n"
246 " process model(s): "
247 #if HAVE_PTHREAD_H
248 "threads "
249 #endif
250 "exec "
251 ";\n"
253 " queue type(s): "
254 #if HAVE_MQUEUE_H
255 "mqueue "
256 #endif
257 #if HAVE_SYS_MSG_H
258 "msg "
259 #endif
260 ";\n"
262 " journal type(s): "
263 #if HAVE_LIBZ
264 "gz "
265 #endif
266 "file "
267 ";\n"
269 #if HAVE_SCHED_H
270 " scheduling type(s): FIFO "
271 ";\n"
272 #endif
274 "\n"
277 printf("Bug reports to %s\n\n", PACKAGE_BUGREPORT);
279 exit(EXIT_SUCCESS);
282 if ( arg_args )
284 char log_level_string[100];
286 log_get_mask_string(log_level_string, sizeof(log_level_string));
288 log_msg(LOG_INFO, __FILE__, __LINE__,
289 "arguments:\n"
290 " arg_basename == \"%s\"\n"
291 " arg_interface == \"%s\"\n"
292 " arg_ip == \"%s\"\n"
293 " arg_journ_type == \"%s\"\n"
294 " arg_pid_file == \"%s\"\n"
295 " arg_proc_type == \"%s\"\n"
296 " arg_queue_name == \"%s\"\n"
297 " arg_queue_type == \"%s\"\n"
298 " arg_xport == \"%s\"\n"
299 /*" arg_interval == %d\n"*/
300 " arg_log_level == %s (%d)\n"
301 " arg_log_file == %s\n"
302 " arg_njournalls == %d\n"
303 " arg_port == %d\n"
304 " arg_queue_max_cnt == %d\n"
305 " arg_queue_max_sz == %d\n"
306 " arg_rt == %d\n"
307 " arg_site == %d\n"
308 " arg_ttl == %d\n"
309 " arg_journal_user == %s\n"
310 " arg_journal_uid == %d\n",
311 arg_basename,
312 arg_interface,
313 arg_ip,
314 arg_journ_type,
315 arg_pid_file,
316 arg_proc_type,
317 arg_queue_name,
318 arg_queue_type,
319 arg_xport,
320 /*TODO: arg_interval,*/
321 log_level_string,
322 arg_log_level,
323 arg_log_file,
324 arg_njournalls,
325 arg_port,
326 arg_queue_max_cnt,
327 arg_queue_max_sz,
328 arg_rt,
329 arg_site,
330 arg_ttl,
331 arg_journal_user,
332 arg_journal_uid);
334 for ( arg_njournalls=0; arg_journalls[arg_njournalls]; ++arg_njournalls )
336 log_msg(LOG_INFO, __FILE__, __LINE__,
337 "journall[%d] == %s\n",
338 arg_njournalls,
339 arg_journalls[arg_njournalls]);
341 exit(EXIT_SUCCESS);
344 #ifdef HAVE_MONDEMAND
345 if ( arg_mondemand_host == NULL
346 && arg_mondemand_ip != NULL )
348 /* mondemand was requested, but no hostname was specified. Choose one. */
349 char host[256];
350 if ( gethostname(host,sizeof(host)-1) == 0 )
352 /* this strndup is an intentional one-time memory leak. */
353 arg_mondemand_host = strndup(host,sizeof(host)-1);
355 else
357 LOG_WARN("Mondemand requires a hostname, but none was provided or"
358 " available. Disabling mondemand.");
359 arg_mondemand_ip = NULL;
362 #endif
364 if ( arg_journalls == NULL
365 || ! arg_journalls[0]
366 || ! strrchr(arg_journalls[0],'/') )
368 LOG_ER("%s requires output pathnames in form "
369 "'/path/to/archive/file.gz'\n", arg_basename);
370 ++bad_options;
373 if (arg_journal_rotate_interval < 0)
375 LOG_ER("--journal-rotate-interval should be positive\n");
376 ++bad_options;
379 if ( bad_options )
381 exit(EXIT_FAILURE);