Merging serial model from branch; converting to the hideous indentation style of...
[lwes-journaller.git] / src / opt.c
blobcef3f441a38f1abb10489091192ce45e3ce15ebb
1 /*======================================================================*
2 * Copyright (C) 2008 Light Weight Event System *
3 * All rights reserved. *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
18 * Boston, MA 02110-1301 USA. *
19 *======================================================================*/
20 #define _GNU_SOURCE
21 #include "config.h"
23 #include "log.h"
24 #include "opt.h"
26 #if HAVE_LIBGEN_H
27 #include <libgen.h>
28 #endif
30 #include <string.h>
31 #include <popt.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <pwd.h>
37 /* Base program name from argv[0]. */
38 char* arg_basename = 0;
40 /* Number of network reader processes/threads to run. */
41 int arg_nreaders = 1;
43 /* Set default queue type, types in preferred order. */
44 #if HAVE_MQUEUE_H
45 const char* arg_queue_type = ARG_MQ;
46 #elif HAVE_SYS_MSG_H
47 const char* arg_queue_type = ARG_MSG;
48 #else
49 #error No kernel message queue support on this platform.
50 #endif
52 /* Queue parameters. */
53 const char* arg_queue_name = "/lwes_journal";
54 int arg_queue_max_sz = 64*1024 - 1;
55 int arg_queue_max_cnt = 10000;
56 int arg_join_group;
58 #if HAVE_LIBZ
59 const char* arg_journ_type = ARG_GZ;
60 #else
61 const char* arg_journ_type = ARG_FILE;
62 #endif
63 char* arg_monitor_type = NULL ;
65 #if HAVE_PTHREAD_H
66 const char* arg_proc_type = ARG_THREAD;
67 #else
68 const char* arg_proc_type = ARG_PROCESS;
69 #endif
71 /* network transport parameters */
72 const char* arg_xport = "udp";
73 const char* arg_ip = "224.0.0.69";
74 int arg_port = 9191;
75 const char* arg_interface = "";
76 int arg_join_group = 1;
77 int arg_sockbuffer = 16*1024*1024;
78 int arg_ttl = 16 ;
80 /* Set the logging level, see log.h. */
81 int arg_log_level = LOG_MASK_ERROR
82 | LOG_MASK_WARNING
83 | LOG_MASK_INFO;
84 const char* arg_log_file = NULL;
86 int arg_rt = 0;
88 /* site ID used to set various config items from config file. */
89 int arg_site = 1;
91 /* intended owner of journal files */
92 int arg_journal_uid = 0;
93 const char* arg_journal_user = NULL;
95 /* Queue report interval. */
96 /*TODO: int arg_interval = 60;*/
98 const char* arg_pid_file = "/var/run/lwes-journaller.pid";
100 /* Journals specified and number of journals specified. */
101 char** arg_journalls;
102 int arg_njournalls;
103 char* arg_disk_journals[10];
105 int arg_nodaemonize = 0;
107 /* Print version, then exit. */
108 int arg_version;
110 /* Print args to sub-programs, then exit. */
111 int arg_args;
113 #ifdef HAVE_MONDEMAND
114 const char* arg_mondemand_host = NULL;
115 const char* arg_mondemand_ip = NULL;
116 int arg_mondemand_port = 20402;
117 #endif
119 void process_options(int argc, const char* argv[])
121 static const struct poptOption options[] = {
122 { "args", 0, POPT_ARG_NONE, &arg_args, 0, "Print command line arguments, then exit", 0 },
123 { "nodaemonize", 0, POPT_ARG_NONE, &arg_nodaemonize, 0, "Don't run in the background", 0 },
124 { "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" },
125 { "log-file", 0, POPT_ARG_STRING, &arg_log_file, 0, "Set the output log file", "file" },
126 { "interface", 'I', POPT_ARG_STRING, &arg_interface, 0, "Network interface to listen on", "ip" },
127 /*TODO: { "report-interval", 's', POPT_ARG_INT, &arg_interval, 0, "Queue report interval", "seconds" },*/
128 { "address", 'm', POPT_ARG_STRING, &arg_ip, 0, "IP address", "ip" },
129 { "join-group", 'g', POPT_ARG_INT, &arg_join_group, 0, "Join multicast group", "0/1" },
130 { "journal-type", 'j', POPT_ARG_STRING, &arg_journ_type, 0, "Journal type", "{" ARG_GZ "," ARG_FILE "}" },
131 { "monitor-type", 'j', POPT_ARG_STRING, &arg_monitor_type, 0, "Monitor type", 0 },
132 { "nreaders", 'r', POPT_ARG_INT, &arg_nreaders, 0, "Number of network reading threads, dflt=1, max=5", 0 },
133 { "pid-file", 'f', POPT_ARG_STRING, &arg_pid_file, 0, "PID file, dflt=NULL", "path" },
134 { "port", 'p', POPT_ARG_INT, &arg_port, 0, "Port number to listen on, dflt=9191", "short" },
135 { "thread-type", 't', POPT_ARG_STRING, &arg_proc_type, 0, "Threading model, '" ARG_THREAD "' or '" ARG_PROCESS "' or '" ARG_SERIAL "', dflt="
136 #if HAVE_PTHREAD_H
137 ARG_THREAD
138 #else
139 ARG_PROCESS
140 #endif
141 , 0 },
142 { "queue-max-cnt", 0, POPT_ARG_INT, &arg_queue_max_cnt, 0, "Max messages for queue, dflt=10000", "int" },
143 { "queue-max-sz", 0, POPT_ARG_INT, &arg_queue_max_sz, 0, "Max message size for queue, dflt=65535", "int" },
144 { "queue-name", 'Q', POPT_ARG_STRING, &arg_queue_name, 0, "Queue name, should start with '/', dflt='/lwes_journal'", "string" },
145 { "queue-type", 'q', POPT_ARG_STRING, &arg_queue_type, 0, "Queue type", "{" ARG_MSG "," ARG_MQ "}" },
146 { "real-time", 'R', POPT_ARG_NONE, &arg_rt, 0, "Run threads with real-time priority", 0 },
147 { "site", 'n', POPT_ARG_INT, &arg_site, 0, "Site id", "int" },
148 { "sockbuffer", 0, POPT_ARG_INT, &arg_sockbuffer, 0, "Receive socket buffer size", "bytes" },
149 { "ttl", 0, POPT_ARG_INT, &arg_ttl, 0, "Emitting TTL value", "hops" },
150 { "user", 0, POPT_ARG_STRING, &arg_journal_user, 0, "Owner of journal files", "user" },
151 { "version", 'v', POPT_ARG_NONE, &arg_version, 0, "Display version, then exit", 0 },
152 { "xport-type", 'x', POPT_ARG_STRING, &arg_xport, 0, "Transport, dflt=udp", "{" ARG_UDP ", ...}" },
153 #ifdef HAVE_MONDEMAND
154 { "mondemand-host", 0, POPT_ARG_STRING, &arg_mondemand_host, 0, "Mondemand monitoring host", "string" },
155 { "mondemand-ip", 0, POPT_ARG_STRING, &arg_mondemand_ip, 0, "Mondemand monitoring ip", "ip-address" },
156 { "mondemand-port", 0, POPT_ARG_INT, &arg_mondemand_port, 0, "Mondemand monitoring port dflt=20402", "port" },
157 #endif
159 POPT_AUTOHELP
160 { NULL, 0, 0, NULL, 0, NULL, NULL }};
162 int bad_options = 0;
163 int rc;
165 #if HAVE_LIBGEN_H
166 arg_basename = basename((char*)argv[0]);
167 #else
168 arg_basename = (char*)argv[0];
169 #endif
171 poptContext optCon = poptGetContext(NULL, argc, argv, options, 0);
172 poptSetOtherOptionHelp(optCon, "");
174 while ( (rc = poptGetNextOpt(optCon)) != -1 )
176 if ( rc < 0 )
178 switch ( rc )
180 case POPT_ERROR_BADOPT:
181 /* You might waht to check options of other types here... */
183 default:
184 LOG_ER("%s: %s\n",
185 poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
186 poptStrerror(rc));
187 ++bad_options;
192 arg_journalls = (char**) poptGetArgs(optCon);
194 /* Count the journals specified on the command line. */
195 if ( arg_journalls )
197 for ( arg_njournalls=0; arg_journalls[arg_njournalls]; ++arg_njournalls )
201 /* Use default journal spec if none provided on the command line. */
202 if ( 0 == arg_njournalls )
204 static const char* default_arg_journalls[] = { "/tmp/all_events.log.gz",
205 NULL };
206 arg_journalls = (char**) default_arg_journalls;
207 arg_njournalls = 1;
210 /* convert the journal file username to a uid */
211 if ( arg_journal_user != NULL)
213 struct passwd *pw_entry = getpwnam(arg_journal_user);
214 if (pw_entry==NULL)
216 LOG_ER("%s was told to use a file owner (%s) that could not be found\n",
217 arg_basename, arg_journal_user);
218 ++bad_options;
220 else
222 arg_journal_uid = pw_entry->pw_uid;
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_monitor_type == \"%s\"\n"
295 " arg_pid_file == \"%s\"\n"
296 " arg_proc_type == \"%s\"\n"
297 " arg_queue_name == \"%s\"\n"
298 " arg_queue_type == \"%s\"\n"
299 " arg_xport == \"%s\"\n"
300 /*" arg_interval == %d\n"*/
301 " arg_join_group == %d\n"
302 " arg_log_level == %s (%d)\n"
303 " arg_log_file == %s\n"
304 " arg_njournalls == %d\n"
305 " arg_nreaders == %d\n"
306 " arg_port == %d\n"
307 " arg_queue_max_cnt == %d\n"
308 " arg_queue_max_sz == %d\n"
309 " arg_rt == %d\n"
310 " arg_site == %d\n"
311 " arg_ttl == %d\n"
312 " arg_journal_user == %s\n"
313 " arg_journal_uid == %d\n",
314 arg_basename,
315 arg_interface,
316 arg_ip,
317 arg_journ_type,
318 arg_monitor_type,
319 arg_pid_file,
320 arg_proc_type,
321 arg_queue_name,
322 arg_queue_type,
323 arg_xport,
324 /*TODO: arg_interval,*/
325 arg_join_group,
326 log_level_string,
327 arg_log_level,
328 arg_log_file,
329 arg_njournalls,
330 arg_nreaders,
331 arg_port,
332 arg_queue_max_cnt,
333 arg_queue_max_sz,
334 arg_rt,
335 arg_site,
336 arg_ttl,
337 arg_journal_user,
338 arg_journal_uid);
340 for ( arg_njournalls=0; arg_journalls[arg_njournalls]; ++arg_njournalls )
342 log_msg(LOG_INFO, __FILE__, __LINE__,
343 "journall[%d] == %s\n",
344 arg_njournalls,
345 arg_journalls[arg_njournalls]);
347 exit(EXIT_SUCCESS);
350 #ifdef HAVE_MONDEMAND
351 if ( arg_mondemand_host == NULL
352 && arg_mondemand_ip != NULL )
354 /* mondemand was requested, but no hostname was specified. Choose one. */
355 char host[256];
356 if ( gethostname(host,sizeof(host)-1) == 0 )
358 /* this strndup is an intentional one-time memory leak. */
359 arg_mondemand_host = strndup(host,sizeof(host)-1);
361 else
363 LOG_WARN("Mondemand requires a hostname, but none was provided or"
364 " available. Disabling mondemand.");
365 arg_mondemand_ip = NULL;
368 #endif
370 if ( arg_journalls == NULL
371 || ! arg_journalls[0]
372 || ! strrchr(arg_journalls[0],'/') )
374 LOG_ER("%s requires output pathnames in form "
375 "'/path/to/archive/file.gz'\n", arg_basename);
376 ++bad_options;
379 if ( bad_options )
381 exit(EXIT_FAILURE);