Blame gnulib/group-member.c

Packit Service 392537
/* group-member.c -- determine whether group id is in calling user's group list
Packit Service 392537
Packit Service 392537
   Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2016 Free Software
Packit Service 392537
   Foundation, Inc.
Packit Service 392537
Packit Service 392537
   This program is free software: you can redistribute it and/or modify
Packit Service 392537
   it under the terms of the GNU General Public License as published by
Packit Service 392537
   the Free Software Foundation; either version 3 of the License, or
Packit Service 392537
   (at your option) any later version.
Packit Service 392537
Packit Service 392537
   This program is distributed in the hope that it will be useful,
Packit Service 392537
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 392537
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 392537
   GNU General Public License for more details.
Packit Service 392537
Packit Service 392537
   You should have received a copy of the GNU General Public License
Packit Service 392537
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service 392537
Packit Service 392537
#include <config.h>
Packit Service 392537
Packit Service 392537
/* Specification.  */
Packit Service 392537
#include <unistd.h>
Packit Service 392537
Packit Service 392537
#include <stdio.h>
Packit Service 392537
#include <sys/types.h>
Packit Service 392537
#include <stdlib.h>
Packit Service 392537
Packit Service 392537
#include "xalloc-oversized.h"
Packit Service 392537
Packit Service 392537
/* Most processes have no more than this many groups, and for these
Packit Service 392537
   processes we can avoid using malloc.  */
Packit Service 392537
enum { GROUPBUF_SIZE = 100 };
Packit Service 392537
Packit Service 392537
struct group_info
Packit Service 392537
  {
Packit Service 392537
    gid_t *group;
Packit Service 392537
    gid_t groupbuf[GROUPBUF_SIZE];
Packit Service 392537
  };
Packit Service 392537
Packit Service 392537
static void
Packit Service 392537
free_group_info (struct group_info const *g)
Packit Service 392537
{
Packit Service 392537
  if (g->group != g->groupbuf)
Packit Service 392537
    free (g->group);
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
static int
Packit Service 392537
get_group_info (struct group_info *gi)
Packit Service 392537
{
Packit Service 392537
  int n_groups = getgroups (GROUPBUF_SIZE, gi->groupbuf);
Packit Service 392537
  gi->group = gi->groupbuf;
Packit Service 392537
Packit Service 392537
  if (n_groups < 0)
Packit Service 392537
    {
Packit Service 392537
      int n_group_slots = getgroups (0, NULL);
Packit Service 392537
      if (0 <= n_group_slots
Packit Service 392537
          && ! xalloc_oversized (n_group_slots, sizeof *gi->group))
Packit Service 392537
        {
Packit Service 392537
          gi->group = malloc (n_group_slots * sizeof *gi->group);
Packit Service 392537
          if (gi->group)
Packit Service 392537
            n_groups = getgroups (n_group_slots, gi->group);
Packit Service 392537
        }
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
  /* In case of error, the user loses.  */
Packit Service 392537
  return n_groups;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
/* Return non-zero if GID is one that we have in our groups list.
Packit Service 392537
   Note that the groups list is not guaranteed to contain the current
Packit Service 392537
   or effective group ID, so they should generally be checked
Packit Service 392537
   separately.  */
Packit Service 392537
Packit Service 392537
int
Packit Service 392537
group_member (gid_t gid)
Packit Service 392537
{
Packit Service 392537
  int i;
Packit Service 392537
  int found;
Packit Service 392537
  struct group_info gi;
Packit Service 392537
  int n_groups = get_group_info (&gi);
Packit Service 392537
Packit Service 392537
  /* Search through the list looking for GID. */
Packit Service 392537
  found = 0;
Packit Service 392537
  for (i = 0; i < n_groups; i++)
Packit Service 392537
    {
Packit Service 392537
      if (gid == gi.group[i])
Packit Service 392537
        {
Packit Service 392537
          found = 1;
Packit Service 392537
          break;
Packit Service 392537
        }
Packit Service 392537
    }
Packit Service 392537
Packit Service 392537
  free_group_info (&gi);
Packit Service 392537
Packit Service 392537
  return found;
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
#ifdef TEST
Packit Service 392537
Packit Service 392537
char *program_name;
Packit Service 392537
Packit Service 392537
int
Packit Service 392537
main (int argc, char **argv)
Packit Service 392537
{
Packit Service 392537
  int i;
Packit Service 392537
Packit Service 392537
  program_name = argv[0];
Packit Service 392537
Packit Service 392537
  for (i = 1; i < argc; i++)
Packit Service 392537
    {
Packit Service 392537
      gid_t gid;
Packit Service 392537
Packit Service 392537
      gid = atoi (argv[i]);
Packit Service 392537
      printf ("%d: %s\n", gid, group_member (gid) ? "yes" : "no");
Packit Service 392537
    }
Packit Service 392537
  exit (0);
Packit Service 392537
}
Packit Service 392537
Packit Service 392537
#endif /* TEST */