/*************************************************** */
/* 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/types.h>
#include <unistd.h>
#include <time.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 GROUP_PROG "acl_group"
#define MAX_ENTRIES 200

rsbac_list_ta_number_t ta_number = 0;
char * progname;

void use(void)
    {
      printf(gettext("%s (RSBAC %s)\n***\n"), progname, VERSION);
      printf(gettext("Use: %s [switches] function params\n"), progname);  
      printf(gettext("  -v = verbose, -g = also list global groups of other users,\n"));
      printf(gettext("  -b = backup mode, -n = use numerical values,\n"));
      printf(gettext("  -s = scripting mode\n"));
      printf(gettext("  -t = set relative time-to-live for this membership in seconds (add_member only)\n"));
      printf(gettext("  -T = set absolute time-to-live for this trustee in seconds (add_member only)\n"));
      printf(gettext("  -D = set relative time-to-live for this membership in days (add_member only)\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("- function and params = one of\n"));
      printf(gettext("  add_group P[RIVATE]|G[LOBAL] name [id]\n"));
      printf(gettext("  change_group group-id new-owner P[RIVATE]|G[LOBAL] name\n"));
      printf(gettext("  remove_group group-id\n"));
      printf(gettext("  get_group_entry group-id\n"));
      printf(gettext("  get_group_name group-id\n"));
      printf(gettext("  get_group_type group-id\n"));
      printf(gettext("  get_group_owner group-id\n"));
      printf(gettext("  list_groups\n"));
      printf(gettext("  add_member group-id user1 ...\n"));
      printf(gettext("  remove_member group-id user1 ...\n"));
      printf(gettext("  get_user_groups [user]\n"));
      printf(gettext("  get_group_members group-id\n"));
    }

char * acl_get_group_name(rsbac_acl_group_id_t group, char * name)
  {
    union  rsbac_acl_group_syscall_arg_t arg;
    struct rsbac_acl_group_entry_t entry;

    arg.get_group_entry.id = group;
    arg.get_group_entry.entry_p = &entry;
    if(!rsbac_acl_group(ta_number, ACLGS_get_group_entry, &arg))
      {
        strcpy(name, entry.name);
      }
    else
      {
        strcpy(name, gettext("*unknown*"));
      }
    return name;
  }

int main(int argc, char ** argv)
{
  int res = 0;
  int i;
  enum  rsbac_acl_group_syscall_type_t call;
  int verbose=0;
  int global=0;
  int backup=0;
  int scripting=0;
  int numerical=0;
  rsbac_version_t version=RSBAC_VERSION_NR;
  rsbac_time_t ttl=RSBAC_LIST_TTL_KEEP;
  union rsbac_acl_group_syscall_arg_t arg;

  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 'g':
                global=1;
                break;
              case 'b':
                backup=1;
                break;
              case 'n':
                numerical=1;
                break;
              case 's':
                scripting=1;
                break;
              case 't':
                if(argc > 2)
                  {
                    ttl = strtoul(argv[2], 0, 10);
                    argc--;
                    argv++;
                  }
                else
                  fprintf(stderr, gettext("%s: missing ttl value for parameter %c\n"), progname, *pos);
                break;
              case 'D':
                if(argc > 2)
                  {
                    ttl = 86400 * strtoul(argv[2], 0, 10);
                    argc--;
                    argv++;
                  }
                else
                  fprintf(stderr, gettext("%s: missing ttl value for parameter %c\n"), progname, *pos);
                break;
              case 'T':
                if(argc > 2)
                  {
                    rsbac_time_t now = time(NULL);
                    ttl = strtoul(argv[2], 0, 10);
                    if(ttl > now)
                      {
                        ttl -= now;
                        argc--;
                        argv++;
                      }
                    else
                      {
                        fprintf(stderr,
                                gettext("%s: ttl value for parameter %c is in the past, exiting\n"), progname, *pos);
                        exit(1);
                      }
                  }
                else
                  fprintf(stderr, gettext("%s: missing ttl value for parameter %c\n"), progname, *pos);
                break;
              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)
     && ((call = get_acl_group_syscall_nr(argv[1])) != ACLGS_none)
    )
    {
      switch(call)
        {
          case ACLGS_add_group:
            {
              rsbac_acl_group_id_t group = 0;

              if(argc <= 3)
                {
                  fprintf(stderr, gettext("%s: too few arguments for function %s\n"), progname, argv[1]);
                  exit(1);
                }
              if(argv[2][0] == 'P')
                arg.add_group.type = ACLG_PRIVATE;
              else
              if(argv[2][0] == 'G')
                arg.add_group.type = ACLG_GLOBAL;
              else
                {
                  fprintf(stderr, gettext("%s: %s: invalid group type %s\n"), progname, argv[1], argv[2]);
                  exit(1);
                }
              arg.add_group.name = argv[3];
              if(argc > 4)
                {
                  group = strtol(argv[4],0,10);
                }
              arg.add_group.group_id_p = &group;
              res = rsbac_acl_group(ta_number, call, &arg);
              error_exit(res);
              if(verbose)
                printf(gettext("%s group %u '%s' added\n"),
                       argv[2], group, argv[3]);
              break;
            }

          case ACLGS_change_group:
            {
              if(argc <= 5)
                {
                  fprintf(stderr, gettext("%s: too few arguments for function %s\n"), progname, argv[1]);
                  exit(1);
                }
              arg.change_group.id = strtol(argv[2],0,10);
              if(rsbac_get_uid(ta_number, &arg.change_group.owner, argv[3]))
                {
                  fprintf(stderr, gettext("%s: Invalid User %s!\n"),
                          progname, argv[3]);
                  exit(1);
                }
              if(argv[4][0] == 'P')
                arg.change_group.type = ACLG_PRIVATE;
              else
              if(argv[4][0] == 'G')
                arg.change_group.type = ACLG_GLOBAL;
              else
                {
                  fprintf(stderr, gettext("%s: %s: invalid group type %s\n"), progname, argv[1], argv[2]);
                  exit(1);
                }
              arg.change_group.name = argv[5];
              res = rsbac_acl_group(ta_number, call, &arg);
              error_exit(res);
              if(verbose) {
                if (RSBAC_UID_SET(arg.change_group.owner))
                  printf(gettext("Group %u changed to owner %u/%u, type %s, name '%s'\n"),
                         arg.change_group.id,
                         RSBAC_UID_SET(arg.change_group.owner),
                         RSBAC_UID_NUM(arg.change_group.owner),
                         argv[4], arg.change_group.name);
                else
                  printf(gettext("Group %u changed to owner %u, type %s, name '%s'\n"),
                         arg.change_group.id,
                         RSBAC_UID_NUM(arg.change_group.owner),
                         argv[4], arg.change_group.name);
              }
              break;
            }

          case ACLGS_remove_group:
            {
              char name[RSBAC_ACL_GROUP_NAMELEN];

              if(argc <= 2)
                {
                  fprintf(stderr, gettext("%s: too few arguments for function %s\n"), progname, argv[1]);
                  exit(1);
                }
              arg.remove_group.id = strtol(argv[2],0,10);
              if(verbose)
                acl_get_group_name(arg.remove_group.id, name);
              res = rsbac_acl_group(ta_number, call, &arg);
              error_exit(res);
              if(verbose)
                printf(gettext("Group %u '%s' removed\n"),
                       arg.remove_group.id, name);
              break;
            }

          case ACLGS_get_group_entry:
            {
              struct rsbac_acl_group_entry_t entry;
                     char type;
                     char tmp[80];

              if(argc <= 2)
                {
                  fprintf(stderr, gettext("%s: too few arguments for function %s\n"), progname, argv[1]);
                  exit(1);
                }
              arg.get_group_entry.id = strtol(argv[2],0,10);
              arg.get_group_entry.entry_p = &entry;
              res = rsbac_acl_group(ta_number, call, &arg);
              error_exit(res);
              if(entry.type == ACLG_PRIVATE)
                type = 'P';
              else
                type = 'G';
              if(scripting)
                {
                  if(numerical) {
                    if (RSBAC_UID_SET(entry.owner))
                      printf("'%s'-%c-%u/%u\n",
                             entry.name, type,
                             RSBAC_UID_SET(entry.owner),
                             RSBAC_UID_NUM(entry.owner));
                    else
                      printf("'%s'-%c-%u\n",
                             entry.name, type, RSBAC_UID_NUM(entry.owner));
                  } else
                    printf("'%s'-%c-%s\n",
                           entry.name, type, get_user_name(ta_number, entry.owner, tmp));
                }
              else {
                if (RSBAC_UID_SET(entry.owner))
                  printf(gettext("Group %u: owner %u/%u (%s), type %c, name '%s'\n"),
                         entry.id, RSBAC_UID_SET(entry.owner),
                         RSBAC_UID_NUM(entry.owner),
                         get_user_name(ta_number, entry.owner, tmp), type, entry.name);
                else
                  printf(gettext("Group %u: owner %u (%s), type %c, name '%s'\n"),
                         entry.id, RSBAC_UID_NUM(entry.owner), get_user_name(ta_number, entry.owner, tmp), type, entry.name);
              }
              break;
            }

          case ACLGS_list_groups:
            {
              struct rsbac_acl_group_entry_t entry_array[MAX_ENTRIES];
                     char type;
                     char tmp[RSBAC_MAXNAMELEN];

              arg.list_groups.maxnum = MAX_ENTRIES;
              arg.list_groups.include_global = global;
              arg.list_groups.group_entry_array = entry_array;
              res = rsbac_acl_group(ta_number, call, &arg);
              error_exit(res);
              if(verbose)
                {
                  if(res < MAX_ENTRIES)
                    printf(gettext("%i groups listed:\n"),
                           res);
                  else
                    printf(gettext("%i groups listed (list truncated):\n"),
                           res);
                }
              for(i=0; i<res; i++)
                {
                  if(entry_array[i].type == ACLG_PRIVATE)
                    type = 'P';
                  else
                    type = 'G';
                  if(backup)
                    printf("%s -V %u add_group %c '%s' %u\n",
                           GROUP_PROG,
                           RSBAC_VERSION_NR,
                           type,
                           entry_array[i].name,
                           entry_array[i].id);
                  else
                  if(scripting)
                    {
                      if(numerical)
                        printf("%u\n",
                               entry_array[i].id);
                      else
                        printf("%u %s %c '%s'\n",
                               entry_array[i].id,
                               get_user_name(ta_number, entry_array[i].owner, tmp),
                               type, entry_array[i].name);
                    }
                  else {
                    if (RSBAC_UID_SET(entry_array[i].owner))
                      printf(gettext("Group %u: owner %u/%u (%s), type %c, name '%s'\n"),
                             entry_array[i].id,
                             RSBAC_UID_SET(entry_array[i].owner),
                             RSBAC_UID_NUM(entry_array[i].owner),
                             get_user_name(ta_number, entry_array[i].owner, tmp),
                             type, entry_array[i].name);
                    else
                      printf(gettext("Group %u: owner %u (%s), type %c, name '%s'\n"),
                             entry_array[i].id, RSBAC_UID_NUM(entry_array[i].owner),
                             get_user_name(ta_number, entry_array[i].owner, tmp),
                             type, entry_array[i].name);
                  }
                }
              if(res == MAX_ENTRIES)
                fprintf(stderr, gettext("(truncated)\n"));
              break;
            }

          case ACLGS_add_member:
            {
              char tmp[80];
              char name[RSBAC_ACL_GROUP_NAMELEN];

              if(argc <= 3)
                {
                  fprintf(stderr, gettext("%s: too few arguments for function %s\n"),
                          progname, argv[1]);
                  exit(1);
                }
              arg.add_member.group = strtol(argv[2],0,10);
              arg.add_member.ttl = ttl;
              for(i=3;i<argc;i++)
                {
                  if(rsbac_get_uid(ta_number, &arg.add_member.user, argv[i]))
                    {
                      fprintf(stderr, gettext("%s: Invalid User %s!\n"),
                              progname, argv[i]);
                    }
                  else
                    {
                      res = rsbac_acl_group(ta_number, call, &arg);
                      error_exit(res);
                      if(verbose) {
                        if (RSBAC_UID_SET(arg.add_member.user))
                          printf(gettext("Member %u/%u (%s) added to group %u '%s'\n"),
                            RSBAC_UID_SET(arg.add_member.user),
                            RSBAC_UID_NUM(arg.add_member.user),
                            get_user_name(ta_number, arg.add_member.user, tmp),
                            arg.add_member.group, acl_get_group_name(arg.add_member.group, name));
                        else
                          printf(gettext("Member %u (%s) added to group %u '%s'\n"),
                            RSBAC_UID_NUM(arg.add_member.user), get_user_name(ta_number, arg.add_member.user, tmp),
                            arg.add_member.group, acl_get_group_name(arg.add_member.group, name));
                      }
                    }
                }
              break;
            }

          case ACLGS_remove_member:
            {
              char tmp[80];
              char name[RSBAC_ACL_GROUP_NAMELEN];

              if(argc <= 3)
                {
                  fprintf(stderr, gettext("%s: too few arguments for function %s\n"), progname, argv[1]);
                  exit(1);
                }
              arg.remove_member.group = strtol(argv[2],0,10);
              for(i=3;i<argc;i++)
                {
                  if(rsbac_get_uid(ta_number, &arg.remove_member.user, argv[i]))
                    {
                      fprintf(stderr, gettext("%s: Invalid User %s!\n"),
                              progname, argv[i]);
                    }
                  else
                    {
                      res = rsbac_acl_group(ta_number, call, &arg);
                      error_exit(res);
                      if(verbose) {
                        if (RSBAC_UID_SET(arg.remove_member.user))
                          printf(gettext("Member %u/%u (%s) removed from group %u '%s'\n"),
                               RSBAC_UID_SET(arg.remove_member.user),
                               RSBAC_UID_NUM(arg.remove_member.user),
                               get_user_name(ta_number, arg.remove_member.user, tmp),
                               arg.remove_member.group, acl_get_group_name(arg.remove_member.group, name));
                        else
                          printf(gettext("Member %u (%s) removed from group %u '%s'\n"),
                               RSBAC_UID_NUM(arg.remove_member.user), get_user_name(ta_number, arg.remove_member.user, tmp),
                               arg.remove_member.group, acl_get_group_name(arg.remove_member.group, name));
                      }
                    }
                }
              break;
            }

          case ACLGS_get_user_groups:
            {
                     rsbac_acl_group_id_t group_array[MAX_ENTRIES];
                     rsbac_time_t ttl_array[MAX_ENTRIES];
                     char tmp[RSBAC_MAXNAMELEN];

              if(argc <= 2)
                arg.get_user_groups.user = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, getuid());
              else
                if(rsbac_get_uid(ta_number, &arg.get_user_groups.user, argv[2]))
                  {
                    fprintf(stderr, gettext("%s: Invalid User %s!\n"),
                            progname, argv[2]);
                    exit(-RSBAC_EINVALIDVALUE);
                  }
              arg.get_user_groups.maxnum = MAX_ENTRIES;
              arg.get_user_groups.group_array = group_array;
              arg.get_user_groups.ttl_array = ttl_array;
              res = rsbac_acl_group(ta_number, call, &arg);
              error_exit(res);
              if(verbose)
                {
                  if(res < MAX_ENTRIES) {
                    if (RSBAC_UID_SET(arg.get_user_groups.user))
                      printf(gettext("%i group memberships for user %u/%u (%s): "),
                           res,
                           RSBAC_UID_SET(arg.get_user_groups.user),
                           RSBAC_UID_NUM(arg.get_user_groups.user),
                           get_user_name(ta_number, arg.get_user_groups.user, tmp));
                    else
                      printf(gettext("%i group memberships for user %u (%s): "),
                           res,
                           RSBAC_UID_NUM(arg.get_user_groups.user),
                           get_user_name(ta_number, arg.get_user_groups.user, tmp));
                  } else {
                    if (RSBAC_UID_SET(arg.get_user_groups.user))
                      printf(gettext("%i group memberships for user %u/%u (%s) (list truncated): "),
                           res,
                           RSBAC_UID_SET(arg.get_user_groups.user),
                           RSBAC_UID_NUM(arg.get_user_groups.user),
                           get_user_name(ta_number, arg.get_user_groups.user, tmp));
                    else
                      printf(gettext("%i group memberships for user %u (%s) (list truncated): "),
                           res,
                           RSBAC_UID_NUM(arg.get_user_groups.user),
                           get_user_name(ta_number, arg.get_user_groups.user, tmp));
                  }
                }
              for(i=0; i<res; i++)
                {
                  if(ttl_array[i])
                    printf("%u (ttl %is) ", group_array[i], ttl_array[i]);
                  else
                    printf("%u ", group_array[i]);
                }
              printf("\n");
              if(res == MAX_ENTRIES)
                fprintf(stderr, gettext("(truncated)\n"));
              break;
            }

          case ACLGS_get_group_members:
            {
              rsbac_uid_t user_array[MAX_ENTRIES];
              rsbac_time_t ttl_array[MAX_ENTRIES];
              char tmp[RSBAC_MAXNAMELEN];
              char name[RSBAC_ACL_GROUP_NAMELEN];

              if(argc <= 2)
                {
                  fprintf(stderr, gettext("%s: too few arguments for function %s\n"), progname, argv[1]);
                  exit(1);
                }
              arg.get_group_members.group = strtol(argv[2],0,10);
              arg.get_group_members.maxnum = MAX_ENTRIES;
              arg.get_group_members.user_array = user_array;
              arg.get_group_members.ttl_array = ttl_array;
              res = rsbac_acl_group(ta_number, call, &arg);
              error_exit(res);
              if(verbose)
                {
                  if(res < MAX_ENTRIES)
                    printf(gettext("%i members of group %u '%s':\n"),
                           res,
                           arg.get_group_members.group,
                           acl_get_group_name(arg.get_group_members.group, name));
                  else
                    printf(gettext("%i members of group %u '%s' (list truncated):\n"),
                           res,
                           arg.get_group_members.group,
                           acl_get_group_name(arg.get_group_members.group, name));
                }
              if(backup && (res>0))
                {
                  rsbac_time_t now = time(NULL);

                  printf("%s -V %u add_member %u",
                         GROUP_PROG,
                         RSBAC_VERSION_NR,
                         arg.get_group_members.group);
                  for(i=0; i<res; i++)
                    {
                      if(!ttl_array[i])
                        {
                          if(numerical) {
                            if (RSBAC_UID_SET(user_array[i]))
                              printf(" %u/%u",
                                   RSBAC_UID_SET(user_array[i]),
                                   RSBAC_UID_NUM(user_array[i]));
                            else
                              printf(" %u",
                                   RSBAC_UID_NUM(user_array[i]));
                          } else
                            printf(" %s",
                                   get_user_name(ta_number, user_array[i], tmp));
                        }
                    }
                  printf("\n");
                  for(i=0; i<res; i++)
                    {
                      if(ttl_array[i])
                        {
                          if(numerical) {
                            if (RSBAC_UID_SET(user_array[i]))
                              printf("%s -V %u -T %u add_member %u %u/%u\n",
                                   GROUP_PROG,
                                   RSBAC_VERSION_NR,
                                   ttl_array[i] + now,
                                   arg.get_group_members.group,
                                   RSBAC_UID_SET(user_array[i]),
                                   RSBAC_UID_NUM(user_array[i]));
                            else
                              printf("%s -V %u -T %u add_member %u %u\n",
                                   GROUP_PROG,
                                   RSBAC_VERSION_NR,
                                   ttl_array[i] + now,
                                   arg.get_group_members.group,
                                   RSBAC_UID_NUM(user_array[i]));
                          } else
                            printf("%s -V %u -T %u add_member %u %s\n",
                                   GROUP_PROG,
                                   RSBAC_VERSION_NR,
                                   ttl_array[i] + now,
                                   arg.get_group_members.group,
                                   get_user_name(ta_number, user_array[i], tmp));
                        }
                    }
                }
              else
                if(scripting)
                  {
                    if(numerical)
                      {
                        for(i=0; i<res; i++)
                          {
                            if (RSBAC_UID_SET(user_array[i]))
                              printf("%u/%u\n",
                                RSBAC_UID_SET(user_array[i]),
                                RSBAC_UID_NUM(user_array[i]));
                            else
                              printf("%u\n", RSBAC_UID_NUM(user_array[i]));
                          }
                      }
                    else
                      {
                        for(i=0; i<res; i++)
                          {
                            printf("%s\n", get_user_name(ta_number, user_array[i], tmp));
                          }
                      }
                  }
                else
                  {
                    for(i=0; i<res; i++)
                      {
                        if(ttl_array[i]) {
                          if (RSBAC_UID_SET(user_array[i]))
                            printf("%u/%u(ttl:%is)\t%s\n",
                                 RSBAC_UID_SET(user_array[i]),
                                 RSBAC_UID_NUM(user_array[i]),
                                 ttl_array[i],
                                 get_user_name(ta_number, user_array[i], tmp));
                          else
                            printf("%u(ttl:%is)\t%s\n",
                                 RSBAC_UID_NUM(user_array[i]),
                                 ttl_array[i],
                                 get_user_name(ta_number, user_array[i], tmp));
                        } else {
                          if (RSBAC_UID_SET(user_array[i]))
                            printf("%u/%u\t\t%s\n",
                              RSBAC_UID_SET(user_array[i]),
                              RSBAC_UID_NUM(user_array[i]),
                              get_user_name(ta_number, user_array[i], tmp));
                          else
                            printf("%u\t\t%s\n",
                              RSBAC_UID_NUM(user_array[i]),
                              get_user_name(ta_number, user_array[i], tmp));
                        }
                      }
                  }
              if(res == MAX_ENTRIES)
                fprintf(stderr, gettext("(truncated)\n"));
              break;
            }

          default:
            fprintf(stderr, gettext("%s: internal error: invalid function number %u\n"), progname, call);
            exit(1);
        }
      exit(0);
    }
  else
  if(   (argc > 2)
     && (!strncmp(argv[1], "get_group_", 10))
    )
    {
      struct rsbac_acl_group_entry_t entry;
      char tmp[80];

      arg.get_group_entry.id = strtol(argv[2],0,10);
      arg.get_group_entry.entry_p = &entry;
      res = rsbac_acl_group(ta_number, ACLGS_get_group_entry, &arg);
      error_exit(res);
      switch(argv[1][10])
        {
          case 't':
            if(entry.type == ACLG_PRIVATE)
              printf("PRIVATE\n");
            else
              printf("GLOBAL\n");
            break;

          case 'o':
            if(numerical) {
              if (RSBAC_UID_SET(entry.owner))
                printf("%u/%u\n",
                       RSBAC_UID_SET(entry.owner),
                       RSBAC_UID_NUM(entry.owner));
              else
                printf("%u\n",
                       RSBAC_UID_NUM(entry.owner));
            } else
              printf("%s\n",
                     get_user_name(ta_number, entry.owner, tmp));
            break;

          case 'n':
            printf("%s\n", entry.name);
            break;

          default:
            break;
        }
    }
  else
    {
      use();
      exit(1);
    }
  exit(0);
}

