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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <pwd.h>
#include <rsbac/types.h>
#include <rsbac/getname.h>
#include <rsbac/acl_getname.h>
#include <rsbac/syscalls.h>
#include <rsbac/error.h>
#include <rsbac/helpers.h>
#include "nls.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#define MASK_PROG "acl_mask"
#define ROOM 10

int verbose=0;
int recurse=0;
int printall=0;
int backup=0;
int alluser = 0;
int numdev = 0;
int alldev = 0;
rsbac_version_t version=RSBAC_VERSION_NR;
rsbac_list_ta_number_t ta_number = 0;
union rsbac_attribute_value_t value;
enum rsbac_target_t target;
char * target_n;
enum rsbac_attribute_t attr;
char * progname;
rsbac_acl_rights_vector_t rights_vector;
rsbac_boolean_t set = FALSE;

void use(void)
    {
      printf(gettext("%s (RSBAC %s)\n***\n"), progname, VERSION);
      printf(gettext("Use: %s [switches] [rights] target-type file/dirname(s)\n"), progname);  
      printf(gettext(" -v = verbose, -r = recurse into subdirs,\n"));
      printf(gettext(" -p = print right names, -s = set mask, not get\n"));
      printf(gettext(" -b = backup mode, -n = list valid SCD names\n"));
      printf(gettext(" -d = numeric device specification ({b|c}major[:minor])\n"));
      printf(gettext(" -D = process all existing device masks,\n"));
      printf(gettext(" -V version = supply RSBAC integer version number for upgrading\n"));
      printf(gettext(" -N ta = transaction number (default = value of RSBAC_TA, if set, or 0)\n"));
      printf(gettext("  rights = list of space-separated right names (requests and ACL specials),\n"));
      printf(gettext("        also request groups R (read requests), RW (read-write),\n"));
      printf(gettext("        SY (system), SE (security), A (all)\n"));
      printf(gettext("        S (ACL special rights)\n"));
      printf(gettext("        and NWx with x = S R W C E A F M (similar to well-known network system)\n"));
      printf(gettext("  target-type = FILE, DIR, FIFO, SYMLINK, DEV, SCD, NETDEV,\n"));
      printf(gettext("                NETTEMP_NT, NETTEMP, NETOBJ or FD\n"));
      printf(gettext("  (FD: let %s decide between FILE, DIR, FIFO and SYMLINK, no DEV),\n"), progname);
    }

int process(char * name, struct rsbac_dev_desc_t * desc_p, rsbac_uid_t uid)
  {
    int res = 0;
    char tmp1[RSBAC_MAXNAMELEN];
    char tmp2[RSBAC_MAXNAMELEN];
    rsbac_acl_rights_vector_t def_mask;
    struct stat buf;
    struct rsbac_acl_syscall_arg_t   arg;
    struct rsbac_acl_syscall_n_arg_t arg_n;

    if(name && !strcmp(name,":DEFAULT:"))
      {
        def_mask = 0;
        switch(target)
          {
            case T_FILE:
            case T_DIR:
            case T_FIFO:
            case T_SYMLINK:
            case T_FD:
              arg_n.name = NULL;
              break;

            case T_DEV:
              if(numdev)
                arg.tid.dev = RSBAC_ZERO_DEV_DESC;
              else
                arg_n.name = NULL;
              break;

            case T_IPC:
              arg.tid.ipc.type = I_none;
              break;
            case T_SCD:
              arg.tid.scd = AST_none;
              break;
            case T_USER:
              arg.tid.user = RSBAC_NO_USER;
              break;
            case T_PROCESS:
              arg.tid.process = 0;
              break;
            case T_GROUP:
              arg.tid.group = RSBAC_NO_GROUP;
              break;
            case T_NETDEV:
              arg.tid.netdev[0] = 0;
              break;
            case T_NETTEMP_NT:
              arg.tid.nettemp = 0;
              break;
            case T_NETOBJ:
              arg.tid.netobj.sock_p = NULL;
              arg.tid.netobj.local_addr = NULL;
              arg.tid.netobj.local_len = 0;
              arg.tid.netobj.remote_addr = NULL;
              arg.tid.netobj.remote_len = 0;
              break;

            default:
              fprintf(stderr, gettext("Invalid target %u for %s, skipped!\n"),
                      target, name);
              return(1);
          }
      }
    else
      {
        switch(target)
          {
            case T_FILE:
            case T_DIR:
            case T_FIFO:
            case T_SYMLINK:
            case T_FD:
              arg_n.name = name;
              def_mask = RSBAC_ACL_DEFAULT_FD_MASK;
              break;
            case T_DEV:
              if(numdev)
                {
                  if(desc_p)
                    arg.tid.dev = *desc_p;
                  else
                  if(strtodevdesc(name, &arg.tid.dev))
                    {
                      fprintf(stderr, gettext("%s is no valid device specification, skipped\n"),
                              name);
                      return(1);
                    }
                }
              else
                arg_n.name = name;
              def_mask = RSBAC_ACL_DEFAULT_DEV_MASK;
              break;
            case T_SCD:
              arg.tid.scd = get_acl_scd_type_nr(name);
              if((arg.tid.scd == ST_none) || (arg.tid.scd == AST_none))
                {
                  fprintf(stderr, gettext("%s is no valid SCD name, skipped\n"),
                           name);
                  return(1);
                }
              def_mask = RSBAC_ACL_DEFAULT_SCD_MASK;
              break;
            case T_USER:
              if(name && rsbac_get_uid(ta_number, &uid, name))
                {
                  fprintf(stderr, gettext("%s: Invalid User %s!\n"),
                          progname, name);
                  exit(1);
                }
              else
                arg.tid.user = uid;
              def_mask = RSBAC_ACL_DEFAULT_U_MASK;
              break;
            case T_GROUP:
              if(rsbac_get_gid(ta_number, &arg.tid.group, name))
                {
                  fprintf(stderr, gettext("%s: Invalid Group %s!\n"),
                          progname, name);
                  exit(1);
                }
              def_mask = RSBAC_ACL_DEFAULT_G_MASK;
              break;
            case T_NETDEV:
              strncpy((char *)arg.tid.netdev, name, RSBAC_IFNAMSIZ);
              arg.tid.netdev[RSBAC_IFNAMSIZ] = 0;
              def_mask = RSBAC_ACL_DEFAULT_NETDEV_MASK;
              break;
            case T_NETTEMP_NT:
              arg.tid.nettemp = strtoul(name, 0, 10);
              def_mask = RSBAC_ACL_DEFAULT_NETTEMP_MASK;
              break;
            case T_NETTEMP:
              arg.tid.nettemp = strtoul(name, 0, 10);
              def_mask = RSBAC_ACL_DEFAULT_NETOBJ_MASK;
              break;
            case T_NETOBJ:
              arg.tid.netobj.sock_p = (void *) strtoul(name, 0, 0);
              arg.tid.netobj.remote_addr = NULL;
              arg.tid.netobj.remote_len = 0;
              def_mask = RSBAC_ACL_DEFAULT_NETOBJ_MASK;
              break;

            default:
              fprintf(stderr, gettext("Invalid target %u for %s, skipped!\n"),
                      target, name);
              def_mask = 0;
              return(1);
          }
      }
    if(verbose)
      {
        if(name)
          printf(gettext("# Processing %s '%s'\n"),
                 target_n,
                 name);
        else
        if(desc_p)
          printf(gettext("# Processing %s '%s'\n"),
                 target_n,
                 devdesctostr(tmp1, *desc_p));
      }
    
    if(set)
      {
        switch(target)
          {
            case T_FILE:
            case T_DIR:
            case T_FIFO:
            case T_SYMLINK:
            case T_FD:
              arg_n.target = target;
              arg_n.rights = rights_vector;
              res = rsbac_acl_n(ta_number, ACLC_set_mask, &arg_n);
              break;

            case T_DEV:
              if(!numdev)
                {
                  arg_n.target = target;
                  arg_n.rights = rights_vector;
                  res = rsbac_acl_n(ta_number, ACLC_set_mask, &arg_n);
                  break;
                }
              /* fall through */

            default:
              arg.target = target;
              arg.rights = rights_vector;
              res = rsbac_acl(ta_number, ACLC_set_mask, &arg);
          }
      }
    else
      {
        switch(target)
          {
            case T_FILE:
            case T_DIR:
            case T_FIFO:
            case T_SYMLINK:
            case T_FD:
              res = rsbac_acl_get_mask_n(ta_number, target, name, &rights_vector);
              break;

            case T_DEV:
              if(numdev)
                res = rsbac_acl_get_mask(ta_number, target, &arg.tid, &rights_vector);
              else
                res = rsbac_acl_get_mask_n(ta_number, target, name, &rights_vector);
              break;

            default:
              res = rsbac_acl_get_mask(ta_number, target, &arg.tid, &rights_vector);
          }
      }
    if(res)
      {
        if(   verbose
           || (errno != RSBAC_EINVALIDTARGET)
          )
          {
            get_error_name(tmp1,res);
            if(name)
              fprintf(stderr, gettext("%s: error: %s\n"), name, tmp1);
            else
              fprintf(stderr, gettext("%s: error: %s\n"),
                      devdesctostr(tmp2, *desc_p), tmp1);
          }
        goto do_recurse;
      }
    if(!set)
      {
        if(backup)
          {
            if(rights_vector != def_mask)
              {
                printf("%s -V %u -sv%c",
                       MASK_PROG,
                       RSBAC_VERSION_NR,
                       numdev ? 'd' : ' ');
                if(printall)
                  {
                    int i;

                    for (i=0; i<R_NONE; i++)
                      if(rights_vector & ((rsbac_acl_rights_vector_t) 1 << i))
                        printf(" %s", get_request_name(tmp1,i));
                    for (i=RSBAC_ACL_SPECIAL_RIGHT_BASE; i<ACLR_NONE; i++)
                      if(rights_vector & ((rsbac_acl_rights_vector_t) 1 << i))
                        printf(" %s", get_acl_special_right_name(tmp1,i));
                  }
                else
                  {
                    printf(" %s", u64tostracl(tmp1, rights_vector));
                  }
                if(name)
                  printf(" %s \"%s\"\n", target_n, name);
                else
                if(desc_p)
                  printf(" %s \"%s\"\n", target_n, devdesctostr(tmp1, *desc_p));
                else {
                  if (RSBAC_UID_SET(uid))
                    printf(" %s %u/%u\n", target_n,
                      RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
                  else
                    printf(" %s %u\n", target_n, RSBAC_UID_NUM(uid));
                }
              }
          }
        else /* no backup */
          {
            if(name)
              printf("%s: %s\n",
                     name,
                     u64tostracl(tmp1, rights_vector));
            else
            if(desc_p)
              printf("%s: %s\n",
                     devdesctostr(tmp2, *desc_p),
                     u64tostracl(tmp1, rights_vector));
            else {
              if (RSBAC_UID_SET(uid))
                printf("%u/%u: %s\n",
                     RSBAC_UID_SET(uid),
                     RSBAC_UID_NUM(uid),
                     u64tostracl(tmp1, rights_vector));
              else
                printf("%u: %s\n",
                     RSBAC_UID_NUM(uid),
                     u64tostracl(tmp1, rights_vector));
            }
            if(printall)
              {
                int i;

                for (i=0; i<R_NONE; i++)
                  if(rights_vector & ((rsbac_acl_rights_vector_t) 1 << i))
                    printf("  %s\n", get_request_name(tmp1,i));
                for (i=RSBAC_ACL_SPECIAL_RIGHT_BASE; i<ACLR_NONE; i++)
                  if(rights_vector & ((rsbac_acl_rights_vector_t) 1 << i))
                    printf("  %s\n", get_acl_special_right_name(tmp1,i));
              }
          }
      }

do_recurse:
    if(   name
       && !lstat(name,&buf)
       && S_ISDIR(buf.st_mode)
       && recurse)
      {
        DIR * dir_stream_p;
        struct dirent * dirent_p;
        char name2[PATH_MAX];

        if(S_ISLNK(buf.st_mode))
          return(0);
        if(!(dir_stream_p = opendir(name)))
          {
            fprintf(stderr, gettext("opendir for dir %s returned error: %s\n"),
                   name,
                   strerror(errno));
            return(-2);
          }
        while((dirent_p = readdir(dir_stream_p)))
          {
            if(   (strcmp(".",dirent_p->d_name))
               && (strcmp("..",dirent_p->d_name)) )
              {
                strcpy(name2,name);
                strcat(name2,"/");
                strcat(name2,dirent_p->d_name);
                process(name2, NULL, RSBAC_NO_USER);
              }
          }
        closedir(dir_stream_p);
      }
    return(0);
  }

int main(int argc, char ** argv)
{
  int res = 0;
  int i;
  enum  rsbac_acl_special_rights_t right;
  rsbac_boolean_t rused = FALSE;
  rsbac_boolean_t wused = FALSE;
  char none_name[] = "FD";

  locale_init();

  progname = argv[0];
  {
    char * env = getenv("RSBAC_TA");

    if(env)
      ta_number = strtoul(env,0,0);
  }
  while((argc > 1) && (argv[1][0] == '-'))
    {
      char * pos = argv[1];
      pos++;
      while(*pos)
        {
          switch(*pos)
            {
              case 'h':
                use();
                return 0;
              case 'v':
                verbose++;
                break;
              case 'r':
                recurse=1;
                break;
              case 's':
                set = TRUE;
                break;
              case 'p':
                printall=1;
                break;
              case 'b':
                backup=1;
                break;
              case 'a':
                alluser=1;
                break;
              case 'd':
                numdev=1;
                break;
              case 'D':
                alldev=1;
                numdev=1;
                break;
              case 'n':
                {
                  char tmp[RSBAC_MAXNAMELEN];

                  for(i=0; i<ST_none; i++)
                    printf("%s\n", get_scd_type_name(tmp, i));
                  for(i=AST_min; i<AST_none; i++)
                    printf("%s\n", get_acl_scd_type_name(tmp, i));
                  exit(0);
                }
              case 'V':
                if(argc < 3)
                  {
                    fprintf(stderr, gettext("%s: no version number for switch V\n"), progname);
                    exit(1);
                  }
                version = strtol(argv[2],0,10);
                argv++;
                argc--;
                break;
              case 'N':
                if(argc > 2)
                  {
                    ta_number = strtoul(argv[2], 0, 10);
                    argc--;
                    argv++;
                  }
                else
                  {
                    fprintf(stderr, gettext("%s: missing transaction number value for parameter %c\n"), progname, *pos);
                    exit(1);
                  }
                break;
              default:
                fprintf(stderr, gettext("%s: unknown parameter %c\n"), progname, *pos);
                exit(1);
            }
          pos++;
        }
      argv++;
      argc--;
    }
  if (argc > 1 || alluser || alldev)
    {
      while(argc > 2)
        {
          if(strlen(argv[1]) == ACLR_NONE)
            {
              int j;
              rsbac_acl_rights_vector_t tmp_rv;

              for(j=0; j<ACLR_NONE; j++)
                if(   (argv[1][j] != '0')
                   && (argv[1][j] != '1')
                  )
                  {
                    fprintf(stderr, gettext("%s: Invalid mask vector %s\n"), progname, argv[1]);
                    exit(1);
                  }
              strtou64acl(argv[1], &tmp_rv);
              rights_vector |= tmp_rv;
              argv++;
              argc--;
              continue;
            }
          right = get_acl_special_right_nr(argv[1]);
          if((right == R_NONE) || (right == ACLR_NONE))
            {
              right = strtol(argv[1],0,10);
              if(   (   (right >= R_NONE)
                     && (right < RSBAC_ACL_SPECIAL_RIGHT_BASE)
                    )
                 || (right >= ACLR_NONE)
                 || (   (right == 0)
                     && strcmp(argv[1],"0")
                    )
                )
                {
                  if(!strcmp(argv[1],"UA"))
                    {
                      rights_vector &= RSBAC_ACL_SPECIAL_RIGHTS_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"RW"))
                    {
                      rights_vector |= RSBAC_READ_WRITE_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"SY"))
                    {
                      rights_vector |= RSBAC_SYSTEM_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"SE"))
                    {
                      rights_vector |= RSBAC_SECURITY_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"S"))
                    {
                      rights_vector |= RSBAC_ACL_SPECIAL_RIGHTS_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"R"))
                    {
                      rights_vector |= RSBAC_READ_REQUEST_VECTOR;
                      rused = TRUE;
                    }
                  else
                  if(!strcmp(argv[1],"W"))
                    {
                      rights_vector |= RSBAC_WRITE_REQUEST_VECTOR;
                      wused = TRUE;
                    }
                  else
                  if(!strcmp(argv[1],"A"))
                    {
                      rights_vector |= RSBAC_ALL_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"NWS"))
                    {
                      rights_vector |= RSBAC_NWS_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"NWR"))
                    {
                      rights_vector |= RSBAC_NWR_REQUEST_VECTOR;
                      rused = TRUE;
                    }
                  else
                  if(!strcmp(argv[1],"NWW"))
                    {
                      rights_vector |= RSBAC_NWW_REQUEST_VECTOR;
                      wused = TRUE;
                    }
                  else
                  if(!strcmp(argv[1],"NWC"))
                    {
                      rights_vector |= RSBAC_NWC_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"NWE"))
                    {
                      rights_vector |= RSBAC_NWE_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"NWA"))
                    {
                      rights_vector |= RSBAC_NWA_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"NWF"))
                    {
                      rights_vector |= RSBAC_NWF_REQUEST_VECTOR;
                    }
                  else
                  if(!strcmp(argv[1],"NWM"))
                    {
                      rights_vector |= RSBAC_NWM_REQUEST_VECTOR;
                    }
                  else
                    { /* end of rights */
                      break;
                    }
                }
            }
          else
            {
              rights_vector |= ((rsbac_acl_rights_vector_t) 1 << right);
            }
          argv++;
          argc--;
        }
      if(rused && wused)
        {
          rights_vector |= RSBAC_READ_WRITE_OPEN_REQUEST_VECTOR;
        }

      target = get_target_nr(argv[1]);
      target_n = argv[1];
      /* trim rights_vector for target */
      switch(target)
        {
          case T_DIR:
          case T_FILE:
          case T_FIFO:
          case T_SYMLINK:
          case T_FD:
            argv++;
            argc--;
            rights_vector &= (RSBAC_ALL_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_DEV:
            argv++;
            argc--;
            rights_vector &= (RSBAC_ALL_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_IPC:
            argv++;
            argc--;
            rights_vector &= (RSBAC_IPC_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_SCD:
            argv++;
            argc--;
            rights_vector &= (RSBAC_SCD_REQUEST_VECTOR | RSBAC_NONE_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_USER:
            argv++;
            argc--;
            rights_vector &= (RSBAC_ACL_USER_RIGHTS_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_GROUP:
            argv++;
            argc--;
            rights_vector &= (RSBAC_ACL_GROUP_RIGHTS_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_PROCESS:
            argv++;
            argc--;
            rights_vector &= (RSBAC_PROCESS_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_NETDEV:
            argv++;
            argc--;
            rights_vector &= (RSBAC_NETDEV_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_NETTEMP_NT:
            argv++;
            argc--;
            rights_vector &= (RSBAC_NETTEMP_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_NETTEMP:
          case T_NETOBJ:
            argv++;
            argc--;
            rights_vector &= (RSBAC_NETOBJ_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          case T_NONE:
            if(!alldev)
              fprintf(stderr, "%s: No target type given, assuming FD\n", progname);
            target = T_FD;
            target_n = none_name;
            rights_vector &= (RSBAC_ALL_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR);
            break;
          default:
            fprintf(stderr, gettext("%s: Invalid target type %s\n"), progname, argv[1]);
            exit(1);
        }
      if(verbose)
        {
          char tmp1[RSBAC_MAXNAMELEN];

          if(set)
            {
              printf(gettext("Set mask: %s\n"),
                     u64tostracl(tmp1, rights_vector));
              if(printall)
              {
                int i;

                for (i=0; i<R_NONE; i++)
                  if(rights_vector & ((rsbac_acl_rights_vector_t) 1 << i))
                    printf("  %s\n", get_request_name(tmp1,i));
                for (i=RSBAC_ACL_SPECIAL_RIGHT_BASE; i<ACLR_NONE; i++)
                  if(rights_vector & ((rsbac_acl_rights_vector_t) 1 << i))
                    printf("  %s\n", get_acl_special_right_name(tmp1,i));
              }
            }
          else
            {
              printf(gettext("# Get mask.\n"));
            }
        }
      if(verbose>1)
        printf(gettext("\n# %s: %i targets\n\n"), progname, argc - 1);
      if(target == T_USER && alluser)
        {
          int count;
          rsbac_uid_t * id_array;

          if(verbose)
            printf(gettext("# %s: processing all users\n"), progname);
          count = rsbac_acl_list_all_user(ta_number, NULL, 0);
          error_exit(count);
          if(!count)
            exit(0);
          count += ROOM;
          id_array = malloc(count * sizeof(*id_array));
          if(!id_array)
            error_exit(-ENOMEM);
          count = rsbac_acl_list_all_user(ta_number, id_array, count);
          error_exit(count);
          if(verbose)
            printf(gettext("# %s: %i targets\n"), progname, count);
          if(count > 0)
            {
              char tmp[RSBAC_MAXNAMELEN];

              qsort(id_array, count, sizeof(*id_array), rsbac_user_compare);
              target = T_USER;
              target_n = "USER";
              for(i=0; i < count ; i++)
                {
                  if(get_user_name(ta_number, id_array[i], tmp))
                    process(tmp, NULL, id_array[i]);
                  else
                    process(NULL, NULL, id_array[i]);
                }
            }
          free(id_array);
        }
      else
      if(alldev)
        {
          int count;
          struct rsbac_dev_desc_t * id_array;

          if(verbose)
            printf(gettext("# %s: processing all devices\n"), progname);
          count = rsbac_acl_list_all_dev(ta_number, NULL, 0);
          error_exit(count);
          if(!count)
            exit(0);
          if(verbose)
            printf(gettext("# %s: %i targets\n"), progname, count);
          count += ROOM;
          id_array = malloc(count * sizeof(*id_array));
          if(!id_array)
            error_exit(-ENOMEM);
          count = rsbac_acl_list_all_dev(ta_number, id_array, count);
          if(count > 0)
            {
              qsort(id_array, count, sizeof(*id_array), rsbac_dev_compare);
              target = T_DEV;
              target_n = "DEV";
              for(i=0; i < count ; i++)
                process(NULL, &id_array[i], RSBAC_NO_USER);
            }
          free(id_array);
        }
      else
      for (i=1;i < (argc);i++)
        {
          process(argv[i], NULL, RSBAC_NO_USER);
        }
    }
  else
    {
      use();
      return 1;
    }
  return (res);
}

