/*************************************************** */
/* Rule Set Based Access Control                     */
/*                                                   */
/* Author and (c) 1999-2014: Amon Ott <ao@rsbac.org> */
/*                                                   */
/* Last modified: 16/Oct/2014                        */
/*************************************************** */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/kdev_t.h>
#include <rsbac/types.h>
#include <rsbac/syscalls.h>
#include <rsbac/error.h>
#include <rsbac/getname.h>
#include "nls.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#define SETPROG "switch_adf_log"

char * progname;

void use(void)
    {
      printf(gettext("%s (RSBAC %s)\n***\n"), progname, VERSION);
      printf(gettext("Use: %s request [target] [value]\n"), progname);
      printf(gettext("request = request name or ALL, value = [012]\n"));
      printf(gettext("target = target type name, leave out for ALL\n"));
      printf(gettext(" -h = this help, -- = no more flags,\n"));
      printf(gettext(" -n = list all requests, -t = list all target types\n"));
      printf(gettext(" -b = backup log level settings\n"));
      printf(gettext(" -g = get not set, -s = scripting mode\n"));
      printf(gettext(" -V version = supply RSBAC integer version number for upgrading\n"));
    }

int main(int argc, char ** argv)
{
  int res = 0;
  int i,j;
  u_int request,target,value;
  char name[RSBAC_MAXNAMELEN];
  int verbose = 0;
  int getmode = 0;
  int scripting = 0;
  u_int stopflags = FALSE;

  locale_init();

  progname = argv[0];

  while((argc > 1) && (argv[1][0] == '-') && !stopflags)
    {
      char * pos = argv[1];
      pos++;
      while(*pos)
        {
          switch(*pos)
            {
              case '-':
                stopflags = TRUE;
                break;
              case 'h':
                use();
                return 0;
              case 'v':
                verbose++;
                break;
              case 'g':
                getmode=1;
                break;
              case 's':
                scripting=1;
                break;
              case 'n':
                {
                  int i;

                  for(i=0; i<R_NONE; i++)
                    printf("%s\n", get_request_name(name, i));
                  return 0;
                }
              case 't':
                {
                  int i;

                  for(i=0; i<=T_NONE; i++)
                    if(i != T_FD)
                      printf("%s\n", get_target_name_only(name, i));
                  exit(0);
                }

              case 'b':
                {
                  int i,j;
                  char name2[RSBAC_MAXNAMELEN];

                  for(i=0;i<R_NONE;i++)
                    {
                      for(j=0;j<=T_NONE;j++)
                        {
                          if(j != T_FD)
                            {
                              res = rsbac_get_adf_log(i,j,&value);
                              if(   !res
                                 && (value != LL_denied)
                                )
                                printf("%s -V %u %s %s %u\n",
                                       SETPROG,
                                       RSBAC_VERSION_NR,
                                       get_request_name(name,i),
                                       get_target_name_only(name2,j),
                                       value);
                            }
                        }
                    }
                  exit(0);
                }
              case 'V':
                if(argc < 3)
                  {
                    fprintf(stderr, gettext("%s: no version number for switch V\n"), progname);
                    exit(1);
                  }
                argv++;
                argc--;
                break;

              default:
                fprintf(stderr, gettext("%s: unknown parameter %c\n"), progname, *pos);
                use();
                exit(1);
            }
          pos++;
        }
      argv++;
      argc--;
    }

  if(getmode)
    {
      switch(argc)
        {
          case 2:
          case 3:
            request=get_request_nr(argv[1]);
            if(request == R_NONE)
              return(-RSBAC_EINVALIDREQUEST);
            if(verbose)
              printf(gettext("%s: getting log settings for request %s\n"),
                     progname,argv[1]);
            if(argc == 3)
              {
                target=get_target_nr(argv[2]);
                if(   (target == T_NONE)
                   && strcmp(argv[2],"NONE")
                  )
                  error_exit(-RSBAC_EINVALIDTARGET);
                if(target == T_FD)
                  error_exit(-RSBAC_EINVALIDTARGET);
                res = rsbac_get_adf_log(request,target,&value);
                error_exit(res);
                if(scripting)
                  {
                    printf("%u\n",
                           value);
                  }
                else
                  {
                    printf("%s: %u\n",
                            get_target_name_only(name,target),
                            value);
                  }
              }
            else
              {
                if(scripting)
                  {
                    for(j=0;j<=T_NONE;j++)
                      {
                        if(j != T_FD)
                          {
                            res = rsbac_get_adf_log(request,j,&value);
                            if(res)
                              {
                                printf("\n");
                                error_exit(res);
                              }
                            printf("%u",
                                   value);
                          }
                      }
                    printf("\n");
                  }
                else
                  {
                    for(j=0;j<=T_NONE;j++)
                      {
                        if(j != T_FD)
                          {
                            res = rsbac_get_adf_log(request,j,&value);
                            error_exit(res);
                            printf("%-14s: %u\n",
                                   get_target_name_only(name,j),
                                   value);
                          }
                      }
                  }
              }
            exit(0);

          default:
            use();
            exit(1);
        }
    }
  if (argc == 3)
    {
      if(!strcmp(argv[1],"ALL"))
        {
          value=strtol(argv[2],0,10);
          if(   (value > LL_request)
             || (!value && strcmp(argv[2],"0"))
            )
            error_exit(-RSBAC_EINVALIDVALUE);
          if(verbose)
            printf(gettext("%s: switching logging for ALL requests and targets to %i\n"),
                   progname,value);
          for(i=0;i<R_NONE;i++)
            {
              for(j=0;j<=T_NONE;j++)
                {
                  if(j != T_FD)
                    {
                      res = rsbac_adf_log_switch(i,j,value);
                      error_exit(res);
                    }
                }
            }
        }
      else
        {
          request=get_request_nr(argv[1]);
          if(request == R_NONE)
            return(-RSBAC_EINVALIDREQUEST);
          value=strtol(argv[2],0,10);
          if(   (value > LL_request)
             || (!value && strcmp(argv[2],"0"))
            )
            error_exit(-RSBAC_EINVALIDVALUE);
          if(verbose)
            printf(gettext("%s: switching logging for request %s and all target types to %i\n"), progname,argv[1],value);
          for(j=0;j<=T_NONE;j++)
            {
              if(j != T_FD)
                {
                  if(verbose)
                    printf(gettext("%s: target %s\n"),
                           progname,get_target_name_only(name,j));
                  res = rsbac_adf_log_switch(request,j,value);
                  error_exit(res);
                }
            }
        }
    }
  else
  if (argc == 4)
    {
      if(!strcmp(argv[1],"ALL"))
        {
          target=get_target_nr(argv[2]);
          if(   (target == T_NONE)
             && strcmp(argv[2],"NONE")
            )
            error_exit(-RSBAC_EINVALIDTARGET);
          if(target == T_FD)
            error_exit(-RSBAC_EINVALIDTARGET);
          value=strtol(argv[3],0,10);
          if(   (value > LL_request)
             || (!value && strcmp(argv[3],"0"))
            )
            error_exit(-RSBAC_EINVALIDVALUE);
          if(verbose)
            printf(gettext("%s: switching logging for ALL requests and target type %s to %i\n"),
                   progname,argv[2], value);
          for(i=0;i<R_NONE;i++)
            {
              if(verbose)
                printf(gettext("%s: target %s\n"),
                       progname,get_request_name(name,i));
              res = rsbac_adf_log_switch(i,target,value);
              error_exit(res);
            }
        }
      else
        {
          request=get_request_nr(argv[1]);
          if(request == R_NONE)
            return(-RSBAC_EINVALIDREQUEST);
          target=get_target_nr(argv[2]);
          if(   (target == T_NONE)
             && strcmp(argv[2],"NONE")
            )
            error_exit(-RSBAC_EINVALIDTARGET);
          if(target == T_FD)
            error_exit(-RSBAC_EINVALIDTARGET);
          value=strtol(argv[3],0,10);
          if(   (value > LL_request)
             || (!value && strcmp(argv[3],"0"))
            )
            error_exit(-RSBAC_EINVALIDVALUE);
          if(verbose)
            printf(gettext("%s: switching logging for request %s and target type %s to %i\n"), progname,argv[1],argv[2],value);
          res = rsbac_adf_log_switch(request,target,value);
          error_exit(res);
        }
    }
  else
    {
      use();
      return 1;
    }
    
  return (res);
}
