Logo Search packages:      
Sourcecode: samhain version File versions  Download package

sh_getopt.c

/* SAMHAIN file system integrity testing                                   */
/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
/*                                                                         */
/*  This program is free software; you can redistribute it                 */
/*  and/or modify                                                          */
/*  it under the terms of the GNU General Public License as                */
/*  published by                                                           */
/*  the Free Software Foundation; either version 2 of the License, or      */
/*  (at your option) any later version.                                    */
/*                                                                         */
/*  This program is distributed in the hope that it will be useful,        */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
/*  GNU General Public License for more details.                           */
/*                                                                         */
/*  You should have received a copy of the GNU General Public License      */
/*  along with this program; if not, write to the Free Software            */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */

#include "config_xor.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <errno.h>


#include "samhain.h"
#include "sh_error.h"
#include "sh_getopt.h"
#include "sh_files.h"
#include "sh_utils.h"
#include "sh_mail.h"
#include "sh_forward.h"
#include "sh_hash.h"

#if defined(WITH_EXTERNAL)
#include "sh_extern.h"
#endif

extern int      sh_calls_set_bind_addr (char *);

#undef  FIL__
#define FIL__  _("sh_getopt.c")

#define HAS_ARG_NO  0
#define HAS_ARG_YES 1
#define DROP_PRIV_NO  0
#define DROP_PRIV_YES 1


typedef struct options {
  char * longopt;
  const char   shortopt;
  char * usage;
  int          hasArg;
  int (*func)(char * opt);
} opttable_t;

/*@noreturn@*/
static int sh_getopt_usage (char * dummy);
#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
static int sh_getopt_forever (char * dummy);
#endif
static int sh_getopt_copyright (char * dummy);

static opttable_t op_table[] = {

#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
  { N_("set-checksum-test"),  
    't', 
    N_("Set checksum testing to 'init', 'update', or 'check'"),  
    HAS_ARG_YES, 
    sh_util_setchecksum },
  { N_("interactive"),  
    'i', 
    N_("Run update in interactive mode"),  
    HAS_ARG_NO, 
    sh_util_set_interactive },
#endif
#ifdef SH_WITH_SERVER
  { N_("server"),  
    'S', 
    N_("Run as log server (obsolete)"),  
    HAS_ARG_NO, 
    sh_util_setserver },
  { N_("qualified"),  
    'q', 
    N_("Log fully qualified name of client host"),  
    HAS_ARG_NO, 
    sh_forward_set_strip },
  { N_("chroot"),  
    '-', 
    N_("Chroot to specified directory"),  
    HAS_ARG_YES, 
    sh_unix_set_chroot },
#endif
  { N_("daemon"),  
    'D', 
    N_("Run as daemon"),  
    HAS_ARG_NO, 
    sh_unix_setdeamon },
  { N_("foreground"),  
    '-', 
    N_("Stay in the foreground"),  
    HAS_ARG_NO, 
    sh_unix_setnodeamon },
  { N_("bind-address"),  
    '-', 
    N_("Bind to this address (interface) for outgoing connections"),  
    HAS_ARG_YES, 
    sh_calls_set_bind_addr },
#ifdef SH_WITH_CLIENT
  { N_("set-export-severity"),  
    'e', 
    N_("Set severity threshold for export to remote log server"),  
    HAS_ARG_YES, 
    sh_error_setexport },
#endif
  { N_("set-syslog-severity"),  
    's', 
    N_("Set severity threshold for syslog"),  
    HAS_ARG_YES, 
    sh_error_set_syslog },
#ifdef WITH_EXTERNAL
  { N_("set-extern-severity"),  
    'x', 
    N_("Set severity threshold for logging by external program(s)"),  
    HAS_ARG_YES, 
    sh_error_set_external },
#endif
#ifdef HAVE_LIBPRELUDE
  { N_("set-prelude-severity"),  
    '-', 
    N_("Set severity threshold for logging to prelude"),  
    HAS_ARG_YES, 
    sh_error_set_prelude },
#endif
#if defined(WITH_DATABASE)
  { N_("set-database-severity"),  
    '-', 
    N_("Set severity threshold for logging to RDBMS"),  
    HAS_ARG_YES, 
    sh_error_set_database },
#endif
  { N_("set-log-severity"),  
    'l', 
    N_("Set severity threshold for logfile"),  
    HAS_ARG_YES, 
    sh_error_setlog },
#if defined(SH_WITH_MAIL)
  { N_("set-mail-severity"),  
    'm', 
    N_("Set severitythreshold  for e-mail"),  
    HAS_ARG_YES, 
    sh_error_setseverity },
#endif
  { N_("set-print-severity"),  
    'p', 
    N_("Set the severity threshold for terminal/console log"),  
    HAS_ARG_YES, 
    sh_error_setprint },
#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
  { N_("recursion"),  
    'r', 
    N_("Set recursion level for directories"),  
    HAS_ARG_YES, 
    sh_files_setrecursion },
#endif
  { N_("verify-log"),  
    'L', 
    N_("Verify the audit trail"),  
    HAS_ARG_YES, 
    sh_error_logverify },
  { N_("just-list"),  
    'j', 
    N_("Modify -L to just list the audit trail"),  
    HAS_ARG_NO, 
    sh_error_logverify_mod },
#if defined(SH_WITH_MAIL)
  { N_("verify-mail"),  
    'M', 
    N_("Verify the mailbox"),  
    HAS_ARG_YES, 
    sh_mail_sigverify 
  },
#endif
  { N_("add-key"),  
    'V', 
    N_("Add key for the mail/log signature"),  
    HAS_ARG_YES, 
    sh_util_set_newkey
  },
  { N_("hash-string"),  
    'H', 
    N_("Print the hash of a string"),  
    HAS_ARG_YES, 
    sh_error_verify },
#if defined (SH_WITH_SERVER) 
  { N_("password"),  
    'P', 
    N_("Compute a client registry entry for password"),  
    HAS_ARG_YES, 
    sh_forward_make_client },
  { N_("gen-password"),  
    'G', 
    N_("Generate a random password"),  
    HAS_ARG_NO, 
    sh_forward_create_password },
#endif

#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
  { N_("forever"),  
    'f', 
    N_("Loop forever, even if not daemon"),  
    HAS_ARG_NO, 
    sh_getopt_forever},
  { N_("full-detail"),  
    'a', 
    N_("Modify -d to list full details"),  
    HAS_ARG_NO, 
    set_full_detail},
  { N_("delimited"),  
    '-', 
    N_("Modify -d to list full details, comma delimited"),  
    HAS_ARG_NO, 
    set_list_delimited},
  { N_("list-database"),  
    'd', 
    N_("List database content (like ls -l)"),  
    HAS_ARG_YES, 
    sh_hash_list_db},
  { N_("init2stdout"),  
    '-', 
    N_("Write database to stdout on init"),  
    HAS_ARG_NO, 
    sh_hash_pushdata_stdout},
#endif
  { N_("trace-logfile"),  
    '-', 
    N_("Logfile for trace"),  
    HAS_ARG_YES, 
    sl_trace_file },
  { N_("trace-enable"),  
    '-', 
    N_("Enable tracing"),  
    HAS_ARG_NO, 
    sl_trace_use },
  { N_("copyright"),  
    'c', 
    N_("Print copyright information"),  
    HAS_ARG_NO, 
    sh_getopt_copyright },
  { N_("help"),  
    'h', 
    N_("Print usage information"),  
    HAS_ARG_NO, 
    sh_getopt_usage },
  /* last entry -- required !! -- */
  { NULL, 
    '\0',     
    NULL,  
    HAS_ARG_NO, 
    NULL }
};

static int sh_getopt_copyright (char * dummy)
{
  fprintf (stdout, 
         _("Copyright (C) 1999-2005 Rainer Wichmann"\
           " (http://la-samhna.de).\n\n"));

  fprintf (stdout, 
         _("This program is free software; "\
           "you can redistribute it and/or modify\n"));
  fprintf (stdout, _("it under the terms of the GNU General "\
                 "Public License as published by\n"));
  fprintf (stdout, _("the Free Software Foundation; either version 2 "\
                 "of the License, or\n"));
  fprintf (stdout, _("(at your option) any later version.\n\n"));

  fprintf (stdout, _("This program is distributed in the hope "\
                 "that it will be useful,\n"));
  fprintf (stdout, _("but WITHOUT ANY WARRANTY; "\
                 "without even the implied warranty of\n"));
  fprintf (stdout, _("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."\
                 " See the\n"));
  fprintf (stdout, _("GNU General Public License for more details.\n\n"));

  fprintf (stdout, _("You should have received a copy of the "\
                 "GNU General Public License\n"));
  fprintf (stdout, _("along with this program; "\
                 "if not, write to the Free Software\n"));
  fprintf (stdout, _("Foundation, Inc., 59 Temple Place - Suite 330, "\
                 "Boston, MA  02111-1307, USA.\n\n"));

  fprintf (stdout, _("This product makes use of the reference implementation "\
                 "of the TIGER message\n"));
  fprintf (stdout, _("digest algorithm. This code is copyright Eli Biham "\
                 "(biham@cs.technion.ac.il)\n"));
  fprintf (stdout, _("and Ross Anderson (rja14@cl.cam.ac.uk). It can be used "\
                 "freely without any\n"));
  fprintf (stdout, _("restrictions.\n"));
#if defined(USE_SRP_PROTOCOL) && !defined(SH_STANDALONE)
#if (!defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H))
  fprintf (stdout, _("This product makes use of the 'bignum' library by "\
                 "Henrik Johansson\n"));
  fprintf (stdout, _("(Henrik.Johansson@Nexus.Comm.SE). If you are including "\
                 "this library in a\n"));
  fprintf (stdout, _("commercial product, be sure to distribute ALL of"\
                 " it with the product.\n"));
#endif
  fprintf (stdout, _("This product uses the 'Secure Remote Password' "\
                 "cryptographic\n"));
  fprintf (stdout, _("authentication system developed by Tom Wu "\
                 "(tjw@CS.Stanford.EDU).\n"));
#endif
  fprintf (stdout, _("\nPlease refer to the file COPYING in the source "\
                 "distribution for a"));
  fprintf (stdout, _("\nfull list of incorporated code and associated "\
                 "licenses.\n"));

  if (dummy)
    _exit (EXIT_SUCCESS);
  else
    _exit (EXIT_SUCCESS);
  /*@notreached@*/
  return 0; /* make compilers happy */
}

/*@noreturn@*/
static int sh_getopt_usage (char * dummy)
{
  int  i;
  char fmt[64];

  char opts[64];

  for (i = 0; i < 64; ++i) /* splint does not grok char opts[64] = { '\0' }; */
    opts[i] = '\0';

  fprintf (stdout,
         _("This is samhain (%s), "\
           "(c) 1999-2005 Rainer Wichmann (http://la-samhna.de).\n"),
         VERSION);
  fprintf (stdout, _("This software comes with ABSOLUTELY NO WARRANTY. "));
  fprintf (stdout, _("Use at own risk.\n"));

  fprintf (stdout, _("Usage:\n\n"));

  for (i = 0; op_table[i].longopt != NULL; ++i) {

    if (i == 63)
      break;

    if (op_table[i].shortopt != '-' && 
      strchr(opts, op_table[i].shortopt) != NULL)
      fprintf (stdout, _("Short option char collision !\n"));
    opts[i] = op_table[i].shortopt;


    if (op_table[i].hasArg == HAS_ARG_NO) {
      if (sl_strlen(op_table[i].longopt) < 10) 
      strcpy(fmt,_("%c%c%c        --%-s,\t\t\t %s\n"));/* known to fit  */
      else if (sl_strlen(op_table[i].longopt) < 17)
      strcpy(fmt, _("%c%c%c        --%-s,\t\t %s\n")); /* known to fit  */
      else 
      strcpy(fmt, _("%c%c%c        --%-s,\t %s\n"));   /* known to fit  */
      /*@-formatconst@*/
      fprintf (stdout,
             fmt,
             (op_table[i].shortopt == '-') ? ' ' : '-',
             (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
             (op_table[i].shortopt == '-') ? ' ' : ',',
             _(op_table[i].longopt),
             _(op_table[i].usage));
      /*@+formatconst@*/
    } else {
      if (sl_strlen(op_table[i].longopt) < 12) 
      strcpy(fmt,                                      /* known to fit  */
             _("%c%c %s  --%-s=<arg>,\t\t %s\n"));  
      else 
      strcpy(fmt,                                      /* known to fit  */ 
             _("%c%c %s  --%-s=<arg>,\t %s\n"));   
      /*@-formatconst@*/
      fprintf (stdout,
             fmt,
             (op_table[i].shortopt == '-') ? ' ' : '-',
             (op_table[i].shortopt == '-') ? ' ' : op_table[i].shortopt,
             (op_table[i].shortopt == '-') ? _("      ") : _("<arg>,"),
             _(op_table[i].longopt),
             _(op_table[i].usage));
      /*@+formatconst@*/
    }
  }

  fprintf (stdout, 
         _("\nPlease report bugs to support@la-samhna.de.\n"));

  (void) fflush(stdout);

  if ( dummy != NULL) 
    {
      if (sl_strcmp( dummy, _("fail")) == 0 ) 
        _exit (EXIT_FAILURE);
    }

  _exit (EXIT_SUCCESS);
  /*@notreached@*/
  return 0; /* make compilers happy */
}

#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
static int sh_getopt_forever (char * dummy)
{
  dummy = (void *) dummy;
  SL_ENTER(_("sh_getopt_forever"));
  sh.flag.loop = S_TRUE;
  SL_RETURN(0, _("sh_getopt_forever"));
}
#endif  

int sh_getopt_get (int argc, char * argv[])
{
  int           count   = 0;
  size_t        len     = 0;
  int           foundit = 0;
  int           i;
  size_t        k;
  char        * theequal;

  SL_ENTER(_("sh_getopt_get"));

  /* -- Return if no args. --
   */
  if (argc < 2) 
    SL_RETURN(0, _("sh_getopt_get"));
 
  while (argc > 1  && argv[1][0] == '-') 
    {

      /* Initialize
       */
      foundit = 0;
      len     = sl_strlen (argv[1]);
    
      /* a '-' with no argument: error
       */
      if (len == 1)
      (void) sh_getopt_usage(_("fail"));

      /* a '--' with no argument: stop argument processing
       */
      if (len == 2 && argv[1][1] == '-') 
      SL_RETURN( count, _("sh_getopt_get"));

      /* a short option: process it
       */
      if (len >= 2 && argv[1][1] != '-') 
      {
        for (k = 1; k < len; ++k)
          {
            for (i = 0; op_table[i].shortopt != '\0'; ++i) 
            {
              
              if ( op_table[i].shortopt == argv[1][k] ) 
                {
                  foundit = 1;
                  if ( op_table[i].hasArg == HAS_ARG_YES ) 
                  {
                    if (k != (len - 1))
                      {
                        /* not last option
                         */
                        fprintf (stderr, 
                               _("Error: short option with argument is not last in option string\n"));
                        (void) sh_getopt_usage(_("fail"));
                      }
                    if (argc < 3) 
                      { 
                        /* argument required, but no avail 
                         */
                        fprintf (stderr, _("Error: missing argument\n"));
                        (void) sh_getopt_usage(_("fail"));
                      } 
                    else 
                      {
                        /* call function with argument */
                        --argc; ++argv;
                        if (0 != (* op_table[i].func )(argv[1]))
                        fprintf (stderr, 
                               _("Error processing option -%c"),
                               op_table[i].shortopt);
                        break;
                      }
                  } 
                  else 
                  {
                    if (0 != (* op_table[i].func )(NULL))
                      fprintf (stderr, 
                             _("Error processing option -%c"),
                             op_table[i].shortopt);
                    break;
                  }
                }
            }
          }

        /* 'break' should get here 
         */
        if (foundit == 1) 
          {
            --argc; ++argv;
            continue;
          } 
        else 
          {
            /* unrecognized short option */
            fprintf (stderr, _("Error: unrecognized short option\n"));
            (void) sh_getopt_usage(_("fail"));
          }
      }

      /* a long option: process it
       */
      if (len > 2) 
      {

        for (i = 0; op_table[i].longopt != NULL; ++i) 
          {
      
            if (sl_strncmp(_(op_table[i].longopt), 
                       &argv[1][2], 
                       sl_strlen(op_table[i].longopt)) == 0 ) 
            {
              foundit = 1; 
              if ( op_table[i].hasArg == HAS_ARG_YES ) 
                {
                  if ( (theequal = strchr(argv[1], '=')) == NULL) 
                  { 
                    fprintf (stderr, _("Error: missing argument\n"));
                    /* argument required, but no avail */
                    (void) sh_getopt_usage(_("fail"));
                  } 
                  else 
                  {
                    if (sl_strlen (theequal) > 1) 
                      {
                        ++theequal;
                        /* call function with argument */
                        if (0 != (* op_table[i].func )(theequal))
                        fprintf (stderr, 
                               _("Error processing option -%s"),
                               op_table[i].longopt);
                        break;
                      } 
                    else 
                      {
                        fprintf (stderr, _("Error: invalid argument\n"));
                        /* argument required, but no avail */
                        (void) sh_getopt_usage(_("fail"));
                      }
                  }
                } 
              else 
                {
                  if (0 != (* op_table[i].func )(NULL))
                  fprintf (stderr, 
                         _("Error processing option -%s"),
                         op_table[i].longopt);
                  break;
                }
            }
          }

        /* 'break' should get here */
        if (foundit == 1) 
          {
            ++count;
            --argc; 
            ++argv;
            continue;
          } 
        else 
          {
            /* unrecognized long option */
            fprintf (stderr, _("Error: unrecognized long option\n"));
            (void) sh_getopt_usage(_("fail"));
          }
      }
    }

  SL_RETURN( count, _("sh_getopt_get"));
}

Generated by  Doxygen 1.6.0   Back to index