source: trunk/src/sh_getopt.c@ 20

Last change on this file since 20 was 20, checked in by rainer, 19 years ago

Enable command-line parsing for prelude, and make prelude regression test safer.

File size: 17.0 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <limits.h>
26#include <errno.h>
27
28
29#include "samhain.h"
30#include "sh_error.h"
31#include "sh_getopt.h"
32#include "sh_files.h"
33#include "sh_utils.h"
34#include "sh_mail.h"
35#include "sh_forward.h"
36#include "sh_hash.h"
37
38#if defined(WITH_EXTERNAL)
39#include "sh_extern.h"
40#endif
41
[20]42extern int sh_calls_set_bind_addr (const char *);
[1]43
44#undef FIL__
45#define FIL__ _("sh_getopt.c")
46
47#define HAS_ARG_NO 0
48#define HAS_ARG_YES 1
49#define DROP_PRIV_NO 0
50#define DROP_PRIV_YES 1
51
52
53typedef struct options {
54 char * longopt;
55 const char shortopt;
56 char * usage;
57 int hasArg;
[20]58 int (*func)(const char * opt);
[1]59} opttable_t;
60
61/*@noreturn@*/
[20]62static int sh_getopt_usage (const char * dummy);
[1]63#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
[20]64static int sh_getopt_forever (const char * dummy);
[1]65#endif
[20]66static int sh_getopt_copyright (const char * dummy);
[1]67
68static opttable_t op_table[] = {
69
70#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
71 { N_("set-checksum-test"),
72 't',
73 N_("Set checksum testing to 'init', 'update', or 'check'"),
74 HAS_ARG_YES,
75 sh_util_setchecksum },
76 { N_("interactive"),
77 'i',
78 N_("Run update in interactive mode"),
79 HAS_ARG_NO,
80 sh_util_set_interactive },
81#endif
82#ifdef SH_WITH_SERVER
83 { N_("server"),
84 'S',
85 N_("Run as log server (obsolete)"),
86 HAS_ARG_NO,
87 sh_util_setserver },
88 { N_("qualified"),
89 'q',
90 N_("Log fully qualified name of client host"),
91 HAS_ARG_NO,
92 sh_forward_set_strip },
93 { N_("chroot"),
94 '-',
95 N_("Chroot to specified directory"),
96 HAS_ARG_YES,
97 sh_unix_set_chroot },
98#endif
99 { N_("daemon"),
100 'D',
101 N_("Run as daemon"),
102 HAS_ARG_NO,
103 sh_unix_setdeamon },
104 { N_("foreground"),
105 '-',
106 N_("Stay in the foreground"),
107 HAS_ARG_NO,
108 sh_unix_setnodeamon },
109 { N_("bind-address"),
110 '-',
111 N_("Bind to this address (interface) for outgoing connections"),
112 HAS_ARG_YES,
113 sh_calls_set_bind_addr },
114#ifdef SH_WITH_CLIENT
115 { N_("set-export-severity"),
116 'e',
117 N_("Set severity threshold for export to remote log server"),
118 HAS_ARG_YES,
119 sh_error_setexport },
120#endif
121 { N_("set-syslog-severity"),
122 's',
123 N_("Set severity threshold for syslog"),
124 HAS_ARG_YES,
125 sh_error_set_syslog },
126#ifdef WITH_EXTERNAL
127 { N_("set-extern-severity"),
128 'x',
129 N_("Set severity threshold for logging by external program(s)"),
130 HAS_ARG_YES,
131 sh_error_set_external },
132#endif
133#ifdef HAVE_LIBPRELUDE
134 { N_("set-prelude-severity"),
135 '-',
136 N_("Set severity threshold for logging to prelude"),
137 HAS_ARG_YES,
138 sh_error_set_prelude },
139#endif
140#if defined(WITH_DATABASE)
141 { N_("set-database-severity"),
142 '-',
143 N_("Set severity threshold for logging to RDBMS"),
144 HAS_ARG_YES,
145 sh_error_set_database },
146#endif
147 { N_("set-log-severity"),
148 'l',
149 N_("Set severity threshold for logfile"),
150 HAS_ARG_YES,
151 sh_error_setlog },
152#if defined(SH_WITH_MAIL)
153 { N_("set-mail-severity"),
154 'm',
155 N_("Set severitythreshold for e-mail"),
156 HAS_ARG_YES,
157 sh_error_setseverity },
158#endif
159 { N_("set-print-severity"),
160 'p',
161 N_("Set the severity threshold for terminal/console log"),
162 HAS_ARG_YES,
163 sh_error_setprint },
164#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
165 { N_("recursion"),
166 'r',
167 N_("Set recursion level for directories"),
168 HAS_ARG_YES,
169 sh_files_setrecursion },
170#endif
171 { N_("verify-log"),
172 'L',
173 N_("Verify the audit trail"),
174 HAS_ARG_YES,
175 sh_error_logverify },
176 { N_("just-list"),
177 'j',
178 N_("Modify -L to just list the audit trail"),
179 HAS_ARG_NO,
180 sh_error_logverify_mod },
181#if defined(SH_WITH_MAIL)
182 { N_("verify-mail"),
183 'M',
184 N_("Verify the mailbox"),
185 HAS_ARG_YES,
186 sh_mail_sigverify
187 },
188#endif
189 { N_("add-key"),
190 'V',
191 N_("Add key for the mail/log signature"),
192 HAS_ARG_YES,
193 sh_util_set_newkey
194 },
195 { N_("hash-string"),
196 'H',
197 N_("Print the hash of a string"),
198 HAS_ARG_YES,
199 sh_error_verify },
200#if defined (SH_WITH_SERVER)
201 { N_("password"),
202 'P',
203 N_("Compute a client registry entry for password"),
204 HAS_ARG_YES,
205 sh_forward_make_client },
206 { N_("gen-password"),
207 'G',
208 N_("Generate a random password"),
209 HAS_ARG_NO,
210 sh_forward_create_password },
211#endif
212
213#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
214 { N_("forever"),
215 'f',
216 N_("Loop forever, even if not daemon"),
217 HAS_ARG_NO,
218 sh_getopt_forever},
219 { N_("full-detail"),
220 'a',
221 N_("Modify -d to list full details"),
222 HAS_ARG_NO,
223 set_full_detail},
224 { N_("delimited"),
225 '-',
226 N_("Modify -d to list full details, comma delimited"),
227 HAS_ARG_NO,
228 set_list_delimited},
229 { N_("list-database"),
230 'd',
231 N_("List database content (like ls -l)"),
232 HAS_ARG_YES,
233 sh_hash_list_db},
234 { N_("init2stdout"),
235 '-',
236 N_("Write database to stdout on init"),
237 HAS_ARG_NO,
238 sh_hash_pushdata_stdout},
239#endif
240 { N_("trace-logfile"),
241 '-',
242 N_("Logfile for trace"),
243 HAS_ARG_YES,
244 sl_trace_file },
245 { N_("trace-enable"),
246 '-',
247 N_("Enable tracing"),
248 HAS_ARG_NO,
249 sl_trace_use },
250 { N_("copyright"),
251 'c',
252 N_("Print copyright information"),
253 HAS_ARG_NO,
254 sh_getopt_copyright },
255 { N_("help"),
256 'h',
257 N_("Print usage information"),
258 HAS_ARG_NO,
259 sh_getopt_usage },
[20]260#if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
261 /* need to skip over these */
262 { N_("prelude"),
263 '-',
264 N_("Prelude generic options"),
265 HAS_ARG_NO,
266 NULL },
267 { N_("profile"),
268 '-',
269 N_("Profile to use for this analyzer"),
270 HAS_ARG_YES,
271 NULL },
272 { N_("heartbeat-interval"),
273 '-',
274 N_("Number of seconds between two heartbeats"),
275 HAS_ARG_YES,
276 NULL },
277 { N_("server-addr"),
278 '-',
279 N_("Address where this sensor should report to"),
280 HAS_ARG_YES,
281 NULL },
282 { N_("analyzer-name"),
283 '-',
284 N_("Name for this analyzer"),
285 HAS_ARG_YES,
286 NULL },
287#endif
[1]288 /* last entry -- required !! -- */
289 { NULL,
290 '\0',
291 NULL,
292 HAS_ARG_NO,
293 NULL }
294};
295
[20]296static int sh_getopt_copyright (const char * dummy)
[1]297{
298 fprintf (stdout,
299 _("Copyright (C) 1999-2005 Rainer Wichmann"\
300 " (http://la-samhna.de).\n\n"));
301
302 fprintf (stdout,
303 _("This program is free software; "\
304 "you can redistribute it and/or modify\n"));
305 fprintf (stdout, _("it under the terms of the GNU General "\
306 "Public License as published by\n"));
307 fprintf (stdout, _("the Free Software Foundation; either version 2 "\
308 "of the License, or\n"));
309 fprintf (stdout, _("(at your option) any later version.\n\n"));
310
311 fprintf (stdout, _("This program is distributed in the hope "\
312 "that it will be useful,\n"));
313 fprintf (stdout, _("but WITHOUT ANY WARRANTY; "\
314 "without even the implied warranty of\n"));
315 fprintf (stdout, _("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."\
316 " See the\n"));
317 fprintf (stdout, _("GNU General Public License for more details.\n\n"));
318
319 fprintf (stdout, _("You should have received a copy of the "\
320 "GNU General Public License\n"));
321 fprintf (stdout, _("along with this program; "\
322 "if not, write to the Free Software\n"));
323 fprintf (stdout, _("Foundation, Inc., 59 Temple Place - Suite 330, "\
324 "Boston, MA 02111-1307, USA.\n\n"));
325
326 fprintf (stdout, _("This product makes use of the reference implementation "\
327 "of the TIGER message\n"));
328 fprintf (stdout, _("digest algorithm. This code is copyright Eli Biham "\
329 "(biham@cs.technion.ac.il)\n"));
330 fprintf (stdout, _("and Ross Anderson (rja14@cl.cam.ac.uk). It can be used "\
331 "freely without any\n"));
332 fprintf (stdout, _("restrictions.\n"));
333#if defined(USE_SRP_PROTOCOL) && !defined(SH_STANDALONE)
334#if (!defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H))
335 fprintf (stdout, _("This product makes use of the 'bignum' library by "\
336 "Henrik Johansson\n"));
337 fprintf (stdout, _("(Henrik.Johansson@Nexus.Comm.SE). If you are including "\
338 "this library in a\n"));
339 fprintf (stdout, _("commercial product, be sure to distribute ALL of"\
340 " it with the product.\n"));
341#endif
342 fprintf (stdout, _("This product uses the 'Secure Remote Password' "\
343 "cryptographic\n"));
344 fprintf (stdout, _("authentication system developed by Tom Wu "\
345 "(tjw@CS.Stanford.EDU).\n"));
346#endif
347 fprintf (stdout, _("\nPlease refer to the file COPYING in the source "\
348 "distribution for a"));
349 fprintf (stdout, _("\nfull list of incorporated code and associated "\
350 "licenses.\n"));
351
352 if (dummy)
353 _exit (EXIT_SUCCESS);
354 else
355 _exit (EXIT_SUCCESS);
356 /*@notreached@*/
357 return 0; /* make compilers happy */
358}
359
360/*@noreturn@*/
[20]361static int sh_getopt_usage (const char * dummy)
[1]362{
363 int i;
364 char fmt[64];
365
366 char opts[64];
367
368 for (i = 0; i < 64; ++i) /* splint does not grok char opts[64] = { '\0' }; */
369 opts[i] = '\0';
370
371 fprintf (stdout,
372 _("This is samhain (%s), "\
373 "(c) 1999-2005 Rainer Wichmann (http://la-samhna.de).\n"),
374 VERSION);
375 fprintf (stdout, _("This software comes with ABSOLUTELY NO WARRANTY. "));
376 fprintf (stdout, _("Use at own risk.\n"));
377
378 fprintf (stdout, _("Usage:\n\n"));
379
380 for (i = 0; op_table[i].longopt != NULL; ++i) {
381
382 if (i == 63)
383 break;
384
385 if (op_table[i].shortopt != '-' &&
386 strchr(opts, op_table[i].shortopt) != NULL)
387 fprintf (stdout, _("Short option char collision !\n"));
388 opts[i] = op_table[i].shortopt;
389
390
391 if (op_table[i].hasArg == HAS_ARG_NO) {
392 if (sl_strlen(op_table[i].longopt) < 10)
393 strcpy(fmt,_("%c%c%c --%-s,\t\t\t %s\n"));/* known to fit */
394 else if (sl_strlen(op_table[i].longopt) < 17)
395 strcpy(fmt, _("%c%c%c --%-s,\t\t %s\n")); /* known to fit */
396 else
397 strcpy(fmt, _("%c%c%c --%-s,\t %s\n")); /* known to fit */
398 /*@-formatconst@*/
399 fprintf (stdout,
400 fmt,
401 (op_table[i].shortopt == '-') ? ' ' : '-',
402 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
403 (op_table[i].shortopt == '-') ? ' ' : ',',
404 _(op_table[i].longopt),
405 _(op_table[i].usage));
406 /*@+formatconst@*/
407 } else {
408 if (sl_strlen(op_table[i].longopt) < 12)
409 strcpy(fmt, /* known to fit */
410 _("%c%c %s --%-s=<arg>,\t\t %s\n"));
411 else
412 strcpy(fmt, /* known to fit */
413 _("%c%c %s --%-s=<arg>,\t %s\n"));
414 /*@-formatconst@*/
415 fprintf (stdout,
416 fmt,
417 (op_table[i].shortopt == '-') ? ' ' : '-',
418 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
419 (op_table[i].shortopt == '-') ? _(" ") : _("<arg>,"),
420 _(op_table[i].longopt),
421 _(op_table[i].usage));
422 /*@+formatconst@*/
423 }
424 }
425
426 fprintf (stdout,
427 _("\nPlease report bugs to support@la-samhna.de.\n"));
428
429 (void) fflush(stdout);
430
431 if ( dummy != NULL)
432 {
433 if (sl_strcmp( dummy, _("fail")) == 0 )
434 _exit (EXIT_FAILURE);
435 }
436
437 _exit (EXIT_SUCCESS);
438 /*@notreached@*/
439 return 0; /* make compilers happy */
440}
441
442#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
[20]443static int sh_getopt_forever (const char * dummy)
[1]444{
445 dummy = (void *) dummy;
446 SL_ENTER(_("sh_getopt_forever"));
447 sh.flag.loop = S_TRUE;
448 SL_RETURN(0, _("sh_getopt_forever"));
449}
450#endif
451
452int sh_getopt_get (int argc, char * argv[])
453{
454 int count = 0;
455 size_t len = 0;
456 int foundit = 0;
457 int i;
458 size_t k;
459 char * theequal;
460
461 SL_ENTER(_("sh_getopt_get"));
462
463 /* -- Return if no args. --
464 */
465 if (argc < 2)
466 SL_RETURN(0, _("sh_getopt_get"));
467
468 while (argc > 1 && argv[1][0] == '-')
469 {
470
471 /* Initialize
472 */
473 foundit = 0;
474 len = sl_strlen (argv[1]);
475
476 /* a '-' with no argument: error
477 */
478 if (len == 1)
479 (void) sh_getopt_usage(_("fail"));
480
481 /* a '--' with no argument: stop argument processing
482 */
483 if (len == 2 && argv[1][1] == '-')
484 SL_RETURN( count, _("sh_getopt_get"));
485
486 /* a short option: process it
487 */
488 if (len >= 2 && argv[1][1] != '-')
489 {
490 for (k = 1; k < len; ++k)
491 {
492 for (i = 0; op_table[i].shortopt != '\0'; ++i)
493 {
494
495 if ( op_table[i].shortopt == argv[1][k] )
496 {
497 foundit = 1;
498 if ( op_table[i].hasArg == HAS_ARG_YES )
499 {
500 if (k != (len - 1))
501 {
502 /* not last option
503 */
504 fprintf (stderr,
505 _("Error: short option with argument is not last in option string\n"));
506 (void) sh_getopt_usage(_("fail"));
507 }
508 if (argc < 3)
509 {
510 /* argument required, but no avail
511 */
512 fprintf (stderr, _("Error: missing argument\n"));
513 (void) sh_getopt_usage(_("fail"));
514 }
515 else
516 {
517 /* call function with argument */
518 --argc; ++argv;
[20]519 if (NULL != op_table[i].func &&
520 0 != (* op_table[i].func )(argv[1]))
[1]521 fprintf (stderr,
522 _("Error processing option -%c"),
523 op_table[i].shortopt);
524 break;
525 }
526 }
527 else
528 {
[20]529 if (NULL != op_table[i].func &&
530 0 != (* op_table[i].func )(NULL))
[1]531 fprintf (stderr,
532 _("Error processing option -%c"),
533 op_table[i].shortopt);
534 break;
535 }
536 }
537 }
538 }
539
540 /* 'break' should get here
541 */
542 if (foundit == 1)
543 {
544 --argc; ++argv;
545 continue;
546 }
547 else
548 {
549 /* unrecognized short option */
550 fprintf (stderr, _("Error: unrecognized short option\n"));
551 (void) sh_getopt_usage(_("fail"));
552 }
553 }
554
555 /* a long option: process it
556 */
557 if (len > 2)
558 {
559
560 for (i = 0; op_table[i].longopt != NULL; ++i)
561 {
562
563 if (sl_strncmp(_(op_table[i].longopt),
564 &argv[1][2],
565 sl_strlen(op_table[i].longopt)) == 0 )
566 {
567 foundit = 1;
568 if ( op_table[i].hasArg == HAS_ARG_YES )
569 {
570 if ( (theequal = strchr(argv[1], '=')) == NULL)
571 {
[20]572 if (argc < 3)
573 {
574 /* argument required, but no avail
575 */
576 fprintf (stderr, _("Error: missing argument\n"));
577 (void) sh_getopt_usage(_("fail"));
578 }
579 else
580 {
581 /* call function with argument */
582 --argc; ++argv;
583 if (NULL != op_table[i].func &&
584 0 != (* op_table[i].func )(argv[1]))
585 fprintf (stderr,
586 _("Error processing option -%s"),
587 op_table[i].longopt);
588 break;
589 }
[1]590 }
591 else
592 {
593 if (sl_strlen (theequal) > 1)
594 {
595 ++theequal;
596 /* call function with argument */
[20]597 if (NULL != op_table[i].func &&
598 0 != (* op_table[i].func )(theequal))
[1]599 fprintf (stderr,
600 _("Error processing option -%s"),
601 op_table[i].longopt);
602 break;
603 }
604 else
605 {
606 fprintf (stderr, _("Error: invalid argument\n"));
607 /* argument required, but no avail */
608 (void) sh_getopt_usage(_("fail"));
609 }
610 }
611 }
612 else
613 {
[20]614 if (NULL != op_table[i].func &&
615 0 != (* op_table[i].func )(NULL))
[1]616 fprintf (stderr,
617 _("Error processing option -%s"),
618 op_table[i].longopt);
619 break;
620 }
621 }
622 }
623
624 /* 'break' should get here */
625 if (foundit == 1)
626 {
627 ++count;
628 --argc;
629 ++argv;
630 continue;
631 }
632 else
633 {
634 /* unrecognized long option */
635 fprintf (stderr, _("Error: unrecognized long option\n"));
636 (void) sh_getopt_usage(_("fail"));
637 }
638 }
639 }
640
641 SL_RETURN( count, _("sh_getopt_get"));
642}
Note: See TracBrowser for help on using the repository browser.