#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <rsbac/types.h>
#include <rsbac/getname.h>
#include <rsbac/syscalls.h>
#include <rsbac/error.h>
#include <rsbac/aci_data_structures.h>

const char   set_prog[] = "attr_set_user";
int attr_list[RSBAC_USER_NR_ATTRIBUTES] = RSBAC_USER_ATTR_LIST;
int alluser = 0;
int verbose = 0;
FILE * tfile;

int process(char * name)
  {
    struct rsbac_user_aci_t default_u_aci = DEFAULT_U_ACI;
    int def_attr[RSBAC_USER_NR_ATTRIBUTES] = {
      default_u_aci.pseudo,
      default_u_aci.access_appr,
      default_u_aci.system_role,
      default_u_aci.integrity_role,
      default_u_aci.cwi_rel_id,
      default_u_aci.pm_task_set,
      default_u_aci.pm_role
      };
    int res = 0;
    char tmp1[120],tmp2[120];
    int j;
    union rsbac_target_id_t       tid;
    union rsbac_attribute_value_t value;
    struct passwd * user_info_p;

    if(   (!(user_info_p = getpwnam(name)))
       && (   (!(user_info_p = getpwuid(strtol(name,0,0))))
           || (!(user_info_p->pw_uid) && strcmp("0",name)) )
      )
        {
          fprintf(stderr, "Invalid user %s - skipped!\n", name);
          exit(1);
        }
    tid.user = user_info_p->pw_uid;
    if(verbose)
      printf("Processing user %s\n", user_info_p->pw_name);
    for (j=0;j < RSBAC_USER_NR_ATTRIBUTES;j++)
      {
        value.dummy = -1;
        res = rsbac_get_attr(T_USER, &tid, attr_list[j], &value, 0);
        if(res)
          {
            if((res > -RSBAC_EPERM) || (res < -RSBAC_EDECISIONMISMATCH))
              fprintf(stderr, "%s (%s): %s\n",
                               user_info_p->pw_name,
                               get_attribute_name(tmp2,attr_list[j]),
                               strerror(-res));
            else
              {
                get_error_name(tmp1,res);
                get_attribute_name(tmp2,attr_list[j]);
                fprintf(stderr, "%s (%s): %s\n",
                        user_info_p->pw_name, tmp2, tmp1);
              }
          }
        else
          {
            printf(" ");
            switch(attr_list[j])
              {
                default:
                  if(value.dummy != def_attr[j])
                    fprintf(tfile,
                            "%s %s %s %i\n",
                            set_prog,
                            name,
                            get_attribute_name(tmp1,attr_list[j]),
                            value.dummy);
              }
          }
      }
    return(res);
  }

int main(int argc, char ** argv)
{
  int res = 0;
  char tmp1[80],tmp2[120];
  int i,j;
  char * progname;

  progname = argv[0];
  if ((argc > 1) && (!strcmp("-a",argv[1])) )
    {
      alluser=1;
      argv++;
      argc--;
    }  
  if ((argc > 1) && (!strcmp("-v",argv[1])) )
    {
      verbose=1;
      argv++;
      argc--;
    }  
  if (   (argc > 2)
      || (alluser && (argc >1)) )
    {
      if (!(tfile=fopen(argv[1],"w")))
        {
          fprintf(stderr, "opening target file returned error: %s\n", strerror(errno));
        }
      if(alluser)
        {
          struct passwd * pwent_p;
          printf("%s: processing all users\n", progname);
          while ((pwent_p = getpwent()))
            {
              process(pwent_p->pw_name);
            }
          endpwent();
        }
      else
        {
          printf("%s: %i targets\n", progname, argc - 2);
          for (i=1;i < (argc-1);i++)
            {
              process(argv[i+1]);
            }
        }
      fclose(tfile);
    }
  else
    {
      printf("%s (RSBAC %s)\n***\n", argv[0], VERSION);
      printf("Use: %s [-a] [-v] target-file [username(s)]\n", progname);  
      printf("- should be called by root with all rsbac modules switched off,\n");
      printf("- -a = process all users, -v = verbose,\n");
      printf("- target-file = name of restore script to be created,\n");
      printf("- attributes and values in backup = see following list:\n");
      for (j=0;j<RSBAC_USER_NR_ATTRIBUTES;j++)
        {
          get_attribute_name(tmp1,attr_list[j]);
          get_attribute_param(tmp2,attr_list[j]);
          printf("%s \t%s\n",tmp1,tmp2);
        }
    }
  return (res);
}
