/*************************************************** */
/* 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 <unistd.h>
#include <linux/kdev_t.h>
#include <rsbac/types.h>
#include <rsbac/syscalls.h>
#include <rsbac/getname.h>
#include <rsbac/error.h>
#include "nls.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

char * progname;

void use(void)
    {
      printf(gettext("%s (RSBAC %s)\n***\n"), progname, VERSION);
      printf(gettext("Use: %s [flags] prog args\n"), progname);
      printf(gettext("This program will set the current seclevel and categories, if supplied,\n"));
      printf(gettext("and then execute prog via execvp().\n"));
      printf(gettext("Please note that you need mac_auto to set the current values.\n"));
      printf(gettext(" -h = this help, -- = no more flags,\n"));
      printf(gettext("-v = verbose, -l = use this seclevel, -c = use this category set\n"));
    }

int main(int argc, char ** argv)
{
  int res = 0;
  rsbac_security_level_t seclevel = SL_none;
  int j;
  rsbac_mac_category_vector_t categories = RSBAC_MAC_MIN_CAT_VECTOR;
  int verbose = 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 'l':
                if(argc > 2)
                  {
                    seclevel = strtoul(argv[2], 0, 10);
                    argc--;
                    argv++;
                  }
                else
                  fprintf(stderr, gettext("%s: missing value for parameter %c\n"), progname, *pos);
                break;
              case 'c':
                if(argc > 2)
                  {
                    if(strlen(argv[2]) != RSBAC_MAC_NR_CATS)
                      {
                        fprintf(stderr, gettext("%s: Invalid category string length %i, must be %lu\n"),
                                progname,
                                strlen(argv[2]),
                                RSBAC_MAC_NR_CATS);
                        if(strlen(argv[2]) < RSBAC_MAC_NR_CATS / 2)
                          {
                            categories = strtol(argv[2],0,10);
                            fprintf(stderr, gettext("%s: Using numeric value %lu instead\n"),
                                    progname,
                                    (u_long) categories);
                          }
                        else
                          exit(1);
                      }
                    else
                      {
                        for(j=0;j<strlen(argv[2]);j++)
                          {
                            if(   argv[2][j] != '0'
                               && argv[2][j] != '1')
                              {
                                fprintf(stderr, gettext("%s: Invalid attribute value char, must be 0 or 1\n"),
                                        progname);
                                exit(1);
                              }
                          }
                        strtou64mac(argv[2], &categories);
                      }
                    argc--;
                    argv++;
                  }
                else
                  fprintf(stderr, gettext("%s: missing value for parameter %c\n"), progname, *pos);
                break;

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

  if (argc > 1)
    {
      if(verbose)
        {
          char tmp[RSBAC_MAXNAMELEN];

          printf(gettext("%s: executing %s with current_sec_level %u and mac_curr_categories %s\n"),
                 progname,argv[1],seclevel,u64tostrmac(tmp, categories));
        }
      res = rsbac_mac_set_curr_level(seclevel, &categories);
      error_exit(res);
      res = execvp(argv[1],&argv[1]);
      error_exit(res);
    }
  else
    {
      use();
      return 1;
    }
  return (res);
}

