source: trunk/src/sh_getopt.c@ 25

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

Minor code revisions.

File size: 16.8 KB
Line 
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
42extern int sh_calls_set_bind_addr (const char *);
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;
58 int (*func)(const char * opt);
59} opttable_t;
60
61/*@noreturn@*/
62static int sh_getopt_usage (const char * dummy);
63#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
64static int sh_getopt_forever (const char * dummy);
65#endif
66static int sh_getopt_copyright (const char * dummy);
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 },
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
288 /* last entry -- required !! -- */
289 { NULL,
290 '\0',
291 NULL,
292 HAS_ARG_NO,
293 NULL }
294};
295
296static int sh_getopt_copyright (const char * dummy)
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@*/
361static int sh_getopt_usage (const char * dummy)
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 sl_strlcpy(fmt,_("%c%c%c --%-s,\t\t\t %s\n"), sizeof(fmt));
394 else if (sl_strlen(op_table[i].longopt) < 17)
395 sl_strlcpy(fmt, _("%c%c%c --%-s,\t\t %s\n"), sizeof(fmt));
396 else
397 sl_strlcpy(fmt, _("%c%c%c --%-s,\t %s\n"), sizeof(fmt));
398 /* flawfinder: ignore */
399 fprintf (stdout, fmt,
400 (op_table[i].shortopt == '-') ? ' ' : '-',
401 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
402 (op_table[i].shortopt == '-') ? ' ' : ',',
403 _(op_table[i].longopt),
404 _(op_table[i].usage));
405 } else {
406 if (sl_strlen(op_table[i].longopt) < 12)
407 sl_strlcpy(fmt, _("%c%c %s --%-s=<arg>,\t\t %s\n"), sizeof(fmt));
408 else
409 sl_strlcpy(fmt, _("%c%c %s --%-s=<arg>,\t %s\n"), sizeof(fmt));
410 /* flawfinder: ignore */
411 fprintf (stdout, fmt,
412 (op_table[i].shortopt == '-') ? ' ' : '-',
413 (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
414 (op_table[i].shortopt == '-') ? _(" ") : _("<arg>,"),
415 _(op_table[i].longopt),
416 _(op_table[i].usage));
417 }
418 }
419
420 fprintf (stdout,
421 _("\nPlease report bugs to support@la-samhna.de.\n"));
422
423 (void) fflush(stdout);
424
425 if ( dummy != NULL)
426 {
427 if (sl_strcmp( dummy, _("fail")) == 0 )
428 _exit (EXIT_FAILURE);
429 }
430
431 _exit (EXIT_SUCCESS);
432 /*@notreached@*/
433 return 0; /* make compilers happy */
434}
435
436#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
437static int sh_getopt_forever (const char * dummy)
438{
439 dummy = (void *) dummy;
440 SL_ENTER(_("sh_getopt_forever"));
441 sh.flag.loop = S_TRUE;
442 SL_RETURN(0, _("sh_getopt_forever"));
443}
444#endif
445
446int sh_getopt_get (int argc, char * argv[])
447{
448 int count = 0;
449 size_t len = 0;
450 int foundit = 0;
451 int i;
452 size_t k;
453 char * theequal;
454
455 SL_ENTER(_("sh_getopt_get"));
456
457 /* -- Return if no args. --
458 */
459 if (argc < 2)
460 SL_RETURN(0, _("sh_getopt_get"));
461
462 while (argc > 1 && argv[1][0] == '-')
463 {
464
465 /* Initialize
466 */
467 foundit = 0;
468 len = sl_strlen (argv[1]);
469
470 /* a '-' with no argument: error
471 */
472 if (len == 1)
473 (void) sh_getopt_usage(_("fail"));
474
475 /* a '--' with no argument: stop argument processing
476 */
477 if (len == 2 && argv[1][1] == '-')
478 SL_RETURN( count, _("sh_getopt_get"));
479
480 /* a short option: process it
481 */
482 if (len >= 2 && argv[1][1] != '-')
483 {
484 for (k = 1; k < len; ++k)
485 {
486 for (i = 0; op_table[i].shortopt != '\0'; ++i)
487 {
488
489 if ( op_table[i].shortopt == argv[1][k] )
490 {
491 foundit = 1;
492 if ( op_table[i].hasArg == HAS_ARG_YES )
493 {
494 if (k != (len - 1))
495 {
496 /* not last option
497 */
498 fprintf (stderr,
499 _("Error: short option with argument is not last in option string\n"));
500 (void) sh_getopt_usage(_("fail"));
501 }
502 if (argc < 3)
503 {
504 /* argument required, but no avail
505 */
506 fprintf (stderr, _("Error: missing argument\n"));
507 (void) sh_getopt_usage(_("fail"));
508 }
509 else
510 {
511 /* call function with argument */
512 --argc; ++argv;
513 if (NULL != op_table[i].func &&
514 0 != (* op_table[i].func )(argv[1]))
515 fprintf (stderr,
516 _("Error processing option -%c"),
517 op_table[i].shortopt);
518 break;
519 }
520 }
521 else
522 {
523 if (NULL != op_table[i].func &&
524 0 != (* op_table[i].func )(NULL))
525 fprintf (stderr,
526 _("Error processing option -%c"),
527 op_table[i].shortopt);
528 break;
529 }
530 }
531 }
532 }
533
534 /* 'break' should get here
535 */
536 if (foundit == 1)
537 {
538 --argc; ++argv;
539 continue;
540 }
541 else
542 {
543 /* unrecognized short option */
544 fprintf (stderr, _("Error: unrecognized short option\n"));
545 (void) sh_getopt_usage(_("fail"));
546 }
547 }
548
549 /* a long option: process it
550 */
551 if (len > 2)
552 {
553
554 for (i = 0; op_table[i].longopt != NULL; ++i)
555 {
556
557 if (sl_strncmp(_(op_table[i].longopt),
558 &argv[1][2],
559 sl_strlen(op_table[i].longopt)) == 0 )
560 {
561 foundit = 1;
562 if ( op_table[i].hasArg == HAS_ARG_YES )
563 {
564 if ( (theequal = strchr(argv[1], '=')) == NULL)
565 {
566 if (argc < 3)
567 {
568 /* argument required, but no avail
569 */
570 fprintf (stderr, _("Error: missing argument\n"));
571 (void) sh_getopt_usage(_("fail"));
572 }
573 else
574 {
575 /* call function with argument */
576 --argc; ++argv;
577 if (NULL != op_table[i].func &&
578 0 != (* op_table[i].func )(argv[1]))
579 fprintf (stderr,
580 _("Error processing option -%s"),
581 op_table[i].longopt);
582 break;
583 }
584 }
585 else
586 {
587 if (sl_strlen (theequal) > 1)
588 {
589 ++theequal;
590 /* call function with argument */
591 if (NULL != op_table[i].func &&
592 0 != (* op_table[i].func )(theequal))
593 fprintf (stderr,
594 _("Error processing option -%s"),
595 op_table[i].longopt);
596 break;
597 }
598 else
599 {
600 fprintf (stderr, _("Error: invalid argument\n"));
601 /* argument required, but no avail */
602 (void) sh_getopt_usage(_("fail"));
603 }
604 }
605 }
606 else
607 {
608 if (NULL != op_table[i].func &&
609 0 != (* op_table[i].func )(NULL))
610 fprintf (stderr,
611 _("Error processing option -%s"),
612 op_table[i].longopt);
613 break;
614 }
615 }
616 }
617
618 /* 'break' should get here */
619 if (foundit == 1)
620 {
621 ++count;
622 --argc;
623 ++argv;
624 continue;
625 }
626 else
627 {
628 /* unrecognized long option */
629 fprintf (stderr, _("Error: unrecognized long option\n"));
630 (void) sh_getopt_usage(_("fail"));
631 }
632 }
633 }
634
635 SL_RETURN( count, _("sh_getopt_get"));
636}
Note: See TracBrowser for help on using the repository browser.