source: trunk/src/sh_getopt.c @ 440

Last change on this file since 440 was 422, checked in by katerina, 9 years ago

Fix for tickets #326, #327.

File size: 25.0 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_unix.h"
33#include "sh_files.h"
34#include "sh_utils.h"
35#include "sh_mail.h"
36#include "sh_forward.h"
37#include "sh_hash.h"
38
39#if defined(WITH_EXTERNAL)
40#include "sh_extern.h"
41#endif
42
43extern int      sh_calls_set_bind_addr (const char *);
44
45#undef  FIL__
46#define FIL__  _("sh_getopt.c")
47
48#define HAS_ARG_NO  0
49#define HAS_ARG_YES 1
50#define DROP_PRIV_NO  0
51#define DROP_PRIV_YES 1
52
53
54typedef struct options {
55  const char * longopt;
56  const char   shortopt;
57  const char * usage;
58  int          hasArg;
59  int (*func)(const char * opt);
60} opttable_t;
61
62/*@noreturn@*/
63static int sh_getopt_usage (const char * dummy);
64#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
65static int sh_getopt_forever (const char * dummy);
66#endif
67static int sh_getopt_copyright (const char * dummy);
68static int sh_getopt_version (const char * dummy);
69
70static opttable_t op_table[] = {
71
72#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
73  { N_("set-checksum-test"), 
74    't', 
75    N_("Set checksum testing to 'init', 'update', or 'check'"), 
76    HAS_ARG_YES, 
77    sh_util_setchecksum },
78  { N_("interactive"), 
79    'i', 
80    N_("Run update in interactive mode"), 
81    HAS_ARG_NO, 
82    sh_util_set_interactive },
83  { N_("listfile"), 
84    '-', 
85    N_("Run update with listfile"), 
86    HAS_ARG_YES, 
87    sh_util_update_file },
88#endif
89#if defined(SH_WITH_SERVER) || defined(SH_WITH_CLIENT)
90  { N_("server-port"), 
91    '-', 
92    N_("Set the server port to connect to"), 
93    HAS_ARG_YES, 
94    sh_forward_server_port },
95#endif
96#ifdef SH_WITH_SERVER
97  { N_("server"), 
98    'S', 
99    N_("Run as log server (obsolete)"), 
100    HAS_ARG_NO, 
101    sh_util_setserver },
102  { N_("qualified"), 
103    'q', 
104    N_("Log fully qualified name of client host"), 
105    HAS_ARG_NO, 
106    sh_forward_set_strip },
107  { N_("chroot"), 
108    '-', 
109    N_("Chroot to specified directory"), 
110    HAS_ARG_YES, 
111    sh_unix_set_chroot },
112#endif
113  { N_("daemon"), 
114    'D', 
115    N_("Run as daemon"), 
116    HAS_ARG_NO, 
117    sh_unix_setdeamon },
118  { N_("foreground"), 
119    '-', 
120    N_("Stay in the foreground"), 
121    HAS_ARG_NO, 
122    sh_unix_setnodeamon },
123  { N_("bind-address"), 
124    '-', 
125    N_("Bind to this address (interface) for outgoing connections"), 
126    HAS_ARG_YES, 
127    sh_calls_set_bind_addr },
128#if defined(SH_WITH_SERVER) || defined(SH_WITH_CLIENT)
129  { N_("set-export-severity"), 
130    'e', 
131    N_("Set severity threshold for export to remote log server"), 
132    HAS_ARG_YES, 
133    sh_error_setexport },
134#endif
135  { N_("set-syslog-severity"), 
136    's', 
137    N_("Set severity threshold for syslog"), 
138    HAS_ARG_YES, 
139    sh_error_set_syslog },
140#ifdef WITH_EXTERNAL
141  { N_("set-extern-severity"), 
142    'x', 
143    N_("Set severity threshold for logging by external program(s)"), 
144    HAS_ARG_YES, 
145    sh_error_set_external },
146#endif
147#ifdef HAVE_LIBPRELUDE
148  { N_("set-prelude-severity"), 
149    '-', 
150    N_("Set severity threshold for logging to prelude"), 
151    HAS_ARG_YES, 
152    sh_error_set_prelude },
153#endif
154#if defined(WITH_DATABASE)
155  { N_("set-database-severity"), 
156    '-', 
157    N_("Set severity threshold for logging to RDBMS"), 
158    HAS_ARG_YES, 
159    sh_error_set_database },
160#endif
161  { N_("set-log-severity"), 
162    'l', 
163    N_("Set severity threshold for logfile"), 
164    HAS_ARG_YES, 
165    sh_error_setlog },
166#if defined(SH_WITH_MAIL)
167  { N_("set-mail-severity"), 
168    'm', 
169    N_("Set severitythreshold  for e-mail"), 
170    HAS_ARG_YES, 
171    sh_error_setseverity },
172#endif
173  { N_("set-print-severity"), 
174    'p', 
175    N_("Set the severity threshold for terminal/console log"), 
176    HAS_ARG_YES, 
177    sh_error_setprint },
178#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
179  { N_("recursion"), 
180    'r', 
181    N_("Set recursion level for directories"), 
182    HAS_ARG_YES, 
183    sh_files_setrecursion },
184#endif
185  { N_("verify-log"), 
186    'L', 
187    N_("Verify the audit trail"), 
188    HAS_ARG_YES, 
189    sh_error_logverify },
190  { N_("just-list"), 
191    'j', 
192    N_("Modify -L to just list the audit trail"), 
193    HAS_ARG_NO, 
194    sh_error_logverify_mod },
195#if defined(SH_WITH_MAIL)
196  { N_("verify-mail"), 
197    'M', 
198    N_("Verify the mailbox"), 
199    HAS_ARG_YES, 
200    sh_mail_sigverify
201  },
202#endif
203  { N_("add-key"), 
204    'V', 
205    N_("Add key for the mail/log signature"), 
206    HAS_ARG_YES, 
207    sh_util_set_newkey
208  },
209  { N_("hash-string"), 
210    'H', 
211    N_("Print the hash of a string"), 
212    HAS_ARG_YES, 
213    sh_error_verify },
214#if defined (SH_WITH_SERVER)
215  { N_("password"), 
216    'P', 
217    N_("Compute a client registry entry for password"), 
218    HAS_ARG_YES, 
219    sh_forward_make_client },
220  { N_("gen-password"), 
221    'G', 
222    N_("Generate a random password"), 
223    HAS_ARG_NO, 
224    sh_forward_create_password },
225#endif
226
227#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
228  { N_("forever"), 
229    'f', 
230    N_("Loop forever, even if not daemon"), 
231    HAS_ARG_NO, 
232    sh_getopt_forever},
233  { N_("list-file"), 
234    '-', 
235    N_("Modify -d to list content of a single file"), 
236    HAS_ARG_YES, 
237    set_list_file},
238  { N_("full-detail"), 
239    'a', 
240    N_("Modify -d to list full details"), 
241    HAS_ARG_NO, 
242    set_full_detail},
243  { N_("delimited"), 
244    '-', 
245    N_("Modify -d to list full details, comma delimited"), 
246    HAS_ARG_NO, 
247    set_list_delimited},
248  { N_("list-database"), 
249    'd', 
250    N_("List database content (like ls -l)"), 
251    HAS_ARG_YES, 
252    sh_hash_list_db},
253  { N_("init2stdout"), 
254    '-', 
255    N_("Write database to stdout on init"), 
256    HAS_ARG_NO, 
257    sh_hash_pushdata_stdout},
258#endif
259  { N_("trace-logfile"), 
260    '-', 
261    N_("Logfile for trace"), 
262    HAS_ARG_YES, 
263    sl_trace_file },
264  { N_("trace-enable"), 
265    '-', 
266    N_("Enable tracing"), 
267    HAS_ARG_NO, 
268    sl_trace_use },
269  { N_("copyright"), 
270    'c', 
271    N_("Print copyright information"), 
272    HAS_ARG_NO, 
273    sh_getopt_copyright },
274  { N_("help"), 
275    'h', 
276    N_("Print usage information"), 
277    HAS_ARG_NO, 
278    sh_getopt_usage },
279  { N_("version"), 
280    'v', 
281    N_("Show version and compiled-in options"), 
282    HAS_ARG_NO, 
283    sh_getopt_version },
284#if defined(HAVE_LIBPRELUDE)
285  /* need to skip over these */
286  { N_("prelude"), 
287    '-', 
288    N_("Prelude generic options"), 
289    HAS_ARG_NO, 
290    NULL },
291  { N_("profile"), 
292    '-', 
293    N_("Profile to use for this analyzer"), 
294    HAS_ARG_YES, 
295    NULL },
296  { N_("heartbeat-interval"), 
297    '-', 
298    N_("Number of seconds between two heartbeats"), 
299    HAS_ARG_YES, 
300    NULL },
301  { N_("server-addr"), 
302    '-', 
303    N_("Address where this sensor should report to"), 
304    HAS_ARG_YES, 
305    NULL },
306  { N_("analyzer-name"), 
307    '-', 
308    N_("Name for this analyzer"), 
309    HAS_ARG_YES, 
310    NULL },
311#endif
312  /* last entry -- required !! -- */
313  { NULL, 
314    '\0',     
315    NULL, 
316    HAS_ARG_NO, 
317    NULL }
318};
319
320
321static void sh_getopt_print_log_facilities (void)
322{
323  int num = 0;
324
325  fputs (_("Compiled-in log facilities:\n"), stdout);
326
327#ifndef DEFAULT_CONSOLE
328  if (num > 0) fputc ('\n', stdout);
329  printf ("%s", _(" console (/dev/console)")); ++num;
330#else
331  if (num > 0) fputc ('\n', stdout);
332  if (0 == strcmp (DEFAULT_CONSOLE, _("NULL")))
333    { printf ("%s", _("console (/dev/console)"));  ++num; }
334  else
335    { printf (_("console (%s)"), DEFAULT_CONSOLE);  ++num; }
336#endif
337  if (num > 0) fputc ('\n', stdout);
338  fputs  (_(" syslog"), stdout); ++num;
339  if (num > 0) fputc ('\n', stdout);
340  printf (_(" logfile (%s)"), DEFAULT_ERRFILE); ++num;
341
342#if defined(WITH_EXTERNAL)
343  if (num > 0) fputc ('\n', stdout);
344  fputs (_(" external program"), stdout); ++num;
345#endif
346
347#if defined(WITH_MESSAGE_QUEUE)
348  if (num > 0) fputc ('\n', stdout);
349  fputs (_(" message queue"), stdout); ++num;
350#endif
351 
352#if defined(WITH_DATABASE)
353  if (num > 0) fputc ('\n', stdout);
354  fputs (_(" database"), stdout); ++num;
355#ifdef WITH_ODBC
356  fputs (_(" (odbc)"), stdout);
357#endif
358#ifdef WITH_ORACLE
359  fputs (_(" (Oracle)"), stdout);
360#endif
361#ifdef WITH_POSTGRES
362  fputs (_(" (PostgreSQL)"), stdout);
363#endif
364#ifdef WITH_MYSQL
365  fputs (_(" (MySQL)"), stdout);
366#endif
367#endif
368
369#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
370  if (num > 0) fputc ('\n', stdout);
371  fputs (_(" server"), stdout); ++num;
372#endif
373
374#if defined(SH_WITH_MAIL)
375  if (num > 0) fputc ('\n', stdout);
376  fputs (_(" email"), stdout); ++num;
377#endif
378
379#ifdef HAVE_LIBPRELUDE
380  if (num > 0) fputc ('\n', stdout); ++num;
381  fputs (_(" prelude (0.9.6+)"), stdout);
382#endif
383
384  if (num == 0)
385    fputs (_(" none"), stdout);
386  fputc ('\n', stdout);
387  return;
388}
389
390static void sh_getopt_print_options (void)
391{
392  int num = 0;
393
394
395#if defined(SH_STANDALONE)
396  if (num > 0) fputc ('\n', stdout);
397  fputs (_("Standalone executable"), stdout); ++num;
398#endif
399#if defined(SH_WITH_CLIENT)
400  if (num > 0) fputc ('\n', stdout);
401  printf (_("Client executable (port %d)"), SH_DEFAULT_PORT); ++num;
402#endif
403#if defined(SH_WITH_SERVER)
404  if (num > 0) fputc ('\n', stdout);
405  printf (_("Server executable (port %d, user %s)"), 
406          SH_DEFAULT_PORT, DEFAULT_IDENT); 
407  ++num;
408#endif
409#if defined(USE_IPVX)
410  fputs (_(", IPv6 supported"), stdout);
411#endif
412
413  fputs (_(", compiled-in options:"), stdout);
414
415#if defined(USE_SYSTEM_MALLOC)
416  if (num > 0) fputc ('\n', stdout);
417  fputs (_(" using system malloc"), stdout); ++num;
418#else
419  if (num > 0) fputc ('\n', stdout);
420  fputs (_(" using dnmalloc"), stdout); ++num;
421#endif
422
423#if defined(HAVE_EGD_RANDOM)
424  if (num > 0) fputc ('\n', stdout);
425  printf (_(" using entropy gathering daemon (%s)"), EGD_SOCKET_NAME); ++num;
426#endif
427#if defined(HAVE_UNIX_RANDOM)
428  if (num > 0) fputc ('\n', stdout);
429  fputs (_(" using unix entropy gatherer"), stdout); ++num;
430#endif
431#if defined(HAVE_URANDOM)
432  if (num > 0) fputc ('\n', stdout);
433  printf (_(" using entropy device (%s)"), NAME_OF_DEV_RANDOM); ++num;
434#endif
435
436#ifdef WITH_GPG
437  if (num > 0) fputc ('\n', stdout);
438  printf (_(" GnuPG signatures (%s)"), DEFAULT_GPG_PATH); ++num;
439#ifdef HAVE_GPG_CHECKSUM
440  if (num > 0) fputc ('\n', stdout);
441  printf (_("   -- GnuPG checksum:  %s"), GPG_HASH); ++num;
442#endif
443#ifdef USE_FINGERPRINT
444  if (num > 0) fputc ('\n', stdout);
445  printf (_("   -- Key fingerprint: %s"), SH_GPG_FP); ++num;
446#endif
447#endif
448
449#if defined(SH_SHELL_EVAL)
450  if (num > 0) fputc ('\n', stdout);
451  fputs (_(" shell expansion in configuration file supported"), stdout); ++num;
452#endif
453
454#if defined(SL_DEBUG)
455  if (num > 0) fputc ('\n', stdout);
456  fputs (_(" debug build (do not use for production)"), stdout); ++num;
457#endif
458#if defined(SCREW_IT_UP)
459  if (num > 0) fputc ('\n', stdout);
460  fputs (_(" anti-debugger"), stdout); ++num;
461#endif
462#if defined(SH_USE_XML)
463  if (num > 0) fputc ('\n', stdout);
464  fputs (_(" xml log format"), stdout); ++num;
465#endif
466#if defined(HAVE_NTIME)
467  if (num > 0) fputc ('\n', stdout);
468  fputs (_(" using time server"), stdout); ++num;
469#endif
470#if defined(HAVE_REGEX_H)
471  if (num > 0) fputc ('\n', stdout);
472  fputs (_(" posix regex support"), stdout); ++num;
473#endif
474
475
476#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
477#if defined(HAVE_LIBZ)
478  if (num > 0) fputc ('\n', stdout);
479  fputs (_(" optionally store full text for files"), stdout); ++num;
480#endif
481#if !defined(SH_COMPILE_STATIC) && defined(__linux__) && defined(HAVE_AUPARSE_H) && defined(HAVE_AUPARSE_LIB)
482  if (num > 0) fputc ('\n', stdout);
483  fputs (_(" optionally report auditd record of changed file"), stdout); ++num;
484#endif
485#if defined(USE_XATTR)
486  if (num > 0) fputc ('\n', stdout);
487  fputs (_(" check SELinux attributes"), stdout); ++num;
488#endif
489#if defined(USE_ACL)
490  if (num > 0) fputc ('\n', stdout);
491  fputs (_(" check Posix ACLs"), stdout); ++num;
492#endif
493#if defined(RELOAD_DATABASE)
494  if (num > 0) fputc ('\n', stdout);
495  fputs (_(" fetch database on reload"), stdout); ++num;
496#endif
497#endif
498
499#if defined(SH_WITH_SERVER)
500
501#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
502  if (num > 0) fputc ('\n', stdout);
503  fputs (_(" command socket authentication: use SetSocketPassword"), stdout); 
504  ++num;
505#else
506  if (num > 0) fputc ('\n', stdout);
507  fputs (_(" command socket authentication: use SetSocketAllowUID"), stdout); 
508  ++num;
509#endif
510
511#if defined(SH_USE_LIBWRAP)
512  if (num > 0) fputc ('\n', stdout);
513  fputs (_(" support tcp wrapper"), stdout); ++num;
514#endif
515#if defined(INET_SYSLOG)
516  if (num > 0) fputc ('\n', stdout);
517  fputs (_(" support listening on 514/udp (syslog)"), stdout); ++num;
518#endif
519#endif
520
521  if (num == 0)
522    fputs (_(" none"), stdout);
523  fputc ('\n', stdout);
524  return;
525}
526
527static void sh_getopt_print_modules (void)
528{
529#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
530  int num = 0;
531 
532  fputs (_("Compiled-in modules:\n"), stdout);
533#ifdef SH_USE_UTMP
534  if (num > 0) fputc (',', stdout);
535  fputs (_(" login/logout"), stdout); ++num;
536#endif
537#ifdef SH_USE_MOUNTS
538  if (num > 0) fputc (',', stdout);
539  fputs (_(" mount options"), stdout); ++num;
540#endif
541#ifdef SH_USE_USERFILES
542  if (num > 0) fputc (',', stdout);
543  fputs (_(" userfiles"), stdout); ++num;
544#endif
545#ifdef SH_USE_KERN
546  if (num > 0) fputc (',', stdout);
547  fputs (_(" kernel"), stdout); ++num;
548#endif
549#ifdef SH_USE_SUIDCHK
550  if (num > 0) fputc (',', stdout);
551  fputs (_(" suid"), stdout); ++num;
552#endif
553#ifdef SH_USE_PROCESSCHECK
554  if (num > 0) fputc (',', stdout);
555  fputs (_(" processes"), stdout); ++num;
556#endif
557#ifdef SH_USE_PORTCHECK
558  if (num > 0) fputc (',', stdout);
559  fputs (_(" ports"), stdout); ++num;
560#endif
561#ifdef USE_LOGFILE_MONITOR
562  if (num > 0) fputc (',', stdout);
563  fputs (_(" logfile monitor"), stdout); ++num;
564#endif
565#if defined(USE_REGISTRY_CHECK)
566  if (num > 0) fputc ('\n', stdout);
567  fputs (_(" Windows registry"), stdout); ++num;
568#endif
569  if (num == 0)
570    fputs (_(" none"), stdout);
571  fputc ('\n', stdout);
572#endif
573  return;
574}
575
576static int sh_getopt_version (const char * dummy)
577{
578  (void) dummy;
579  fprintf (stdout,
580           _("This is samhain (%s), "\
581             "(c) 1999-2008 Rainer Wichmann (http://la-samhna.de).\n"),
582           VERSION);
583  fprintf (stdout, "%s",_("This software comes with ABSOLUTELY NO WARRANTY. "));
584  fprintf (stdout, "%s",_("Use at own risk.\n\n"));
585
586  sh_getopt_print_log_facilities ();
587  sh_getopt_print_modules ();
588  sh_getopt_print_options ();
589
590  _exit (EXIT_SUCCESS);
591  /*@notreached@*/
592  return 0; /* make compilers happy */
593}
594static int sh_getopt_copyright (const char * dummy)
595{
596  fprintf (stdout, "%s",
597           _("Copyright (C) 1999-2008 Rainer Wichmann"\
598             " (http://la-samhna.de).\n\n"));
599
600  fprintf (stdout, "%s",
601           _("This program is free software; "\
602             "you can redistribute it and/or modify\n"));
603  fprintf (stdout, "%s",_("it under the terms of the GNU General "\
604                     "Public License as published by\n"));
605  fprintf (stdout, "%s",_("the Free Software Foundation; either version 2 "\
606                     "of the License, or\n"));
607  fprintf (stdout, "%s",_("(at your option) any later version.\n\n"));
608
609  fprintf (stdout, "%s",_("This program is distributed in the hope "\
610                     "that it will be useful,\n"));
611  fprintf (stdout, "%s",_("but WITHOUT ANY WARRANTY; "\
612                     "without even the implied warranty of\n"));
613  fprintf (stdout, "%s",_("MERCHANTABILITY or FITNESS FOR A PARTICULAR "\
614                     "PURPOSE. See the\n"));
615  fprintf (stdout, "%s",_("GNU General Public License for more details.\n\n"));
616
617  fprintf (stdout, "%s",_("You should have received a copy of the "\
618                     "GNU General Public License\n"));
619  fprintf (stdout, "%s",_("along with this program; "\
620                     "if not, write to the Free Software\n"));
621  fprintf (stdout, "%s",_("Foundation, Inc., 59 Temple Place - Suite 330, "\
622                     "Boston, MA  02111-1307, USA.\n\n"));
623
624  fprintf (stdout, "%s",_("This product makes use of the reference "\
625                     "implementation of the TIGER message\n"));
626  fprintf (stdout, "%s",_("digest algorithm. This code is copyright Eli Biham "\
627                     "(biham@cs.technion.ac.il)\n"));
628  fprintf (stdout, "%s",_("and Ross Anderson (rja14@cl.cam.ac.uk). It can be used "\
629                     "freely without any\n"));
630  fprintf (stdout, "%s",_("restrictions.\n"));
631#if defined(USE_SRP_PROTOCOL) && !defined(SH_STANDALONE)
632#if (!defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H))
633  fprintf (stdout, "%s",_("This product makes use of the 'bignum' library by "\
634                     "Henrik Johansson\n"));
635  fprintf (stdout, "%s",_("(Henrik.Johansson@Nexus.Comm.SE). If you are "\
636                     "including this library in a\n"));
637  fprintf (stdout, "%s",_("commercial product, be sure to distribute ALL of"\
638                     " it with the product.\n"));
639#endif
640  fprintf (stdout, "%s",_("This product uses the 'Secure Remote Password' "\
641                     "cryptographic\n"));
642  fprintf (stdout, "%s",_("authentication system developed by Tom Wu "\
643                     "(tjw@CS.Stanford.EDU).\n"));
644#endif
645  fprintf (stdout, "%s",_("\nPlease refer to the file COPYING in the source "\
646                     "distribution for a"));
647  fprintf (stdout, "%s",_("\nfull list of incorporated code and associated "\
648                     "licenses.\n"));
649
650  if (dummy)
651    _exit (EXIT_SUCCESS);
652  else
653    _exit (EXIT_SUCCESS);
654  /*@notreached@*/
655  return 0; /* make compilers happy */
656}
657
658/*@noreturn@*/
659static int sh_getopt_usage (const char * dummy)
660{
661  int  i;
662  char fmt[64];
663
664  char opts[64];
665
666  for (i = 0; i < 64; ++i) /* splint does not grok char opts[64] = { '\0' }; */
667    opts[i] = '\0';
668
669  fprintf (stdout,
670           _("This is samhain (%s), "\
671             "(c) 1999-2006 Rainer Wichmann (http://la-samhna.de).\n"),
672           VERSION);
673  fprintf (stdout, "%s",_("This software comes with ABSOLUTELY NO WARRANTY. "));
674  fprintf (stdout, "%s",_("Use at own risk.\n"));
675
676  fprintf (stdout, "%s",_("Usage:\n\n"));
677
678  for (i = 0; op_table[i].longopt != NULL; ++i) {
679
680    if (i == 63)
681      break;
682
683    if (op_table[i].shortopt != '-' && 
684        strchr(opts, op_table[i].shortopt) != NULL)
685      fprintf (stdout, "%s",_("Short option char collision !\n"));
686    opts[i] = op_table[i].shortopt;
687
688
689    if (op_table[i].hasArg == HAS_ARG_NO) {
690      if (sl_strlen(op_table[i].longopt) < 10) 
691        sl_strlcpy(fmt,_("%c%c%c        --%-s,\t\t\t %s\n"), sizeof(fmt));
692      else if (sl_strlen(op_table[i].longopt) < 17)
693        sl_strlcpy(fmt, _("%c%c%c        --%-s,\t\t %s\n"), sizeof(fmt));
694      else 
695        sl_strlcpy(fmt, _("%c%c%c        --%-s,\t %s\n"), sizeof(fmt));
696      /* flawfinder: ignore */
697      fprintf (stdout, fmt,
698               (op_table[i].shortopt == '-') ? ' ' : '-',
699               (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
700               (op_table[i].shortopt == '-') ? ' ' : ',',
701               _(op_table[i].longopt),
702               _(op_table[i].usage));
703    } else {
704      if (sl_strlen(op_table[i].longopt) < 12) 
705        sl_strlcpy(fmt, _("%c%c %s  --%-s=<arg>,\t\t %s\n"), sizeof(fmt)); 
706      else 
707        sl_strlcpy(fmt, _("%c%c %s  --%-s=<arg>,\t %s\n"), sizeof(fmt));   
708      /* flawfinder: ignore */
709      fprintf (stdout, fmt,
710               (op_table[i].shortopt == '-') ? ' ' : '-',
711               (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
712               (op_table[i].shortopt == '-') ? _("      ") : _("<arg>,"),
713               _(op_table[i].longopt),
714               _(op_table[i].usage));
715    }
716  }
717
718  fprintf (stdout, "%s",
719           _("\nPlease report bugs to support@la-samhna.de.\n"));
720
721  (void) fflush(stdout);
722
723  if ( dummy != NULL) 
724    {
725      if (sl_strcmp( dummy, _("fail")) == 0 ) 
726          _exit (EXIT_FAILURE);
727    }
728
729  _exit (EXIT_SUCCESS);
730  /*@notreached@*/
731  return 0; /* make compilers happy */
732}
733
734#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
735static int sh_getopt_forever (const char * dummy)
736{
737  (void) dummy;
738  SL_ENTER(_("sh_getopt_forever"));
739  sh.flag.loop = S_TRUE;
740  SL_RETURN(0, _("sh_getopt_forever"));
741}
742#endif 
743
744int sh_getopt_get (int argc, char * argv[])
745{
746  int           count   = 0;
747  size_t        len     = 0;
748  int           foundit = 0;
749  int           i;
750  size_t        k;
751  char        * theequal;
752
753  SL_ENTER(_("sh_getopt_get"));
754
755  /* -- Return if no args. --
756   */
757  if (argc < 2) 
758    SL_RETURN(0, _("sh_getopt_get"));
759 
760  while (argc > 1  && argv[1][0] == '-') 
761    {
762
763      /* Initialize
764       */
765      foundit = 0;
766      len     = sl_strlen (argv[1]);
767   
768      /* a '-' with no argument: error
769       */
770      if (len == 1)
771        (void) sh_getopt_usage(_("fail"));
772
773      /* a '--' with no argument: stop argument processing
774       */
775      if (len == 2 && argv[1][1] == '-') 
776        SL_RETURN( count, _("sh_getopt_get"));
777
778      /* a short option: process it
779       */
780      if (len >= 2 && argv[1][1] != '-') 
781        {
782          for (k = 1; k < len; ++k)
783            {
784              for (i = 0; op_table[i].shortopt != '\0'; ++i) 
785                {
786                 
787                  if ( op_table[i].shortopt == argv[1][k] ) 
788                    {
789                      foundit = 1;
790                      if ( op_table[i].hasArg == HAS_ARG_YES ) 
791                        {
792                          if (k != (len - 1))
793                            {
794                              /* not last option
795                               */
796                              fprintf (stderr, "%s",
797                                       _("Error: short option with argument is not last in option string\n"));
798                              (void) sh_getopt_usage(_("fail"));
799                            }
800                          if (argc < 3) 
801                            { 
802                              /* argument required, but no avail
803                               */
804                              fprintf (stderr, "%s",
805                                       _("Error: missing argument\n"));
806                              (void) sh_getopt_usage(_("fail"));
807                            } 
808                          else 
809                            {
810                              /* call function with argument */
811                              --argc; ++argv;
812                              if (NULL != op_table[i].func &&
813                                  0 != (* op_table[i].func )(argv[1]))
814                                fprintf (stderr, 
815                                         _("Error processing option -%c\n"),
816                                         op_table[i].shortopt);
817                              break;
818                            }
819                        } 
820                      else 
821                        {
822                          if (NULL != op_table[i].func &&
823                              0 != (* op_table[i].func )(NULL))
824                            fprintf (stderr, 
825                                     _("Error processing option -%c\n"),
826                                     op_table[i].shortopt);
827                          break;
828                        }
829                    }
830                }
831            }
832
833          /* 'break' should get here
834           */
835          if (foundit == 1) 
836            {
837              --argc; ++argv;
838              continue;
839            } 
840          else 
841            {
842              /* unrecognized short option */
843              fprintf (stderr, "%s",_("Error: unrecognized short option\n"));
844              (void) sh_getopt_usage(_("fail"));
845            }
846        }
847
848      /* a long option: process it
849       */
850      if (len > 2) 
851        {
852
853          for (i = 0; op_table[i].longopt != NULL; ++i) 
854            {
855
856              if (sl_strncmp(_(op_table[i].longopt), 
857                             &argv[1][2], 
858                             sl_strlen(op_table[i].longopt)) == 0 ) 
859                {
860                  foundit = 1; 
861                  if ( op_table[i].hasArg == HAS_ARG_YES ) 
862                    {
863                      theequal = strchr(argv[1], '=');
864                      if (theequal == NULL) 
865                        { 
866                          if (argc < 3) 
867                            { 
868                              /* argument required, but no avail
869                               */
870                              fprintf (stderr, "%s",
871                                       _("Error: missing argument\n"));
872                              (void) sh_getopt_usage(_("fail"));
873                            } 
874                          else 
875                            {
876                              /* call function with argument */
877                              --argc; ++argv;
878                              if (NULL != op_table[i].func &&
879                                  0 != (* op_table[i].func )(argv[1]))
880                                fprintf (stderr, 
881                                         _("Error processing option -%s\n"),
882                                         op_table[i].longopt);
883                              break;
884                            }
885                        } 
886                      else 
887                        {
888                          if (sl_strlen (theequal) > 1) 
889                            {
890                              ++theequal;
891                              /* call function with argument */
892                              if (NULL != op_table[i].func &&
893                                  0 != (* op_table[i].func )(theequal))
894                                fprintf (stderr, 
895                                         _("Error processing option -%s\n"),
896                                         op_table[i].longopt);
897                              break;
898                            } 
899                          else 
900                            {
901                              fprintf (stderr, "%s",
902                                       _("Error: invalid argument\n"));
903                              /* argument required, but no avail */
904                              (void) sh_getopt_usage(_("fail"));
905                            }
906                        }
907                    } 
908                  else 
909                    {
910                      if (NULL != op_table[i].func && 
911                          0 != (* op_table[i].func )(NULL))
912                        fprintf (stderr, 
913                                 _("Error processing option -%s\n"),
914                                 op_table[i].longopt);
915                      break;
916                    }
917                }
918            }
919
920          /* 'break' should get here */
921          if (foundit == 1) 
922            {
923              ++count;
924              --argc; 
925              ++argv;
926              continue;
927            } 
928          else 
929            {
930              /* unrecognized long option */
931              fprintf (stderr, "%s",_("Error: unrecognized long option\n"));
932              (void) sh_getopt_usage(_("fail"));
933            }
934        }
935    }
936
937  SL_RETURN( count, _("sh_getopt_get"));
938}
Note: See TracBrowser for help on using the repository browser.