diff options
Diffstat (limited to 'src/groups.c')
-rw-r--r-- | src/groups.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/groups.c b/src/groups.c new file mode 100644 index 0000000..12bd224 --- /dev/null +++ b/src/groups.c @@ -0,0 +1,179 @@ +/* + * SPDX-FileCopyrightText: 1991 - 1993, Julianne Frances Haugh + * SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz + * SPDX-FileCopyrightText: 2001 - 2006, Tomasz Kłoczko + * SPDX-FileCopyrightText: 2007 - 2008, Nicolas François + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <config.h> + +#ident "$Id$" + +#include <grp.h> +#include <pwd.h> +#include <stdio.h> +#include "defines.h" +#include "prototypes.h" +#include "shadowlog.h" +/* + * Global variables + */ +const char *Prog; + +/* local function prototypes */ +static void print_groups (const char *member); + +/* + * print_groups - print the groups which the named user is a member of + * + * print_groups() scans the groups file for the list of groups which + * the user is listed as being a member of. + */ +static void print_groups (const char *member) +{ + int groups = 0; + struct group *grp; + struct passwd *pwd; + bool flag = false; + + pwd = getpwnam (member); /* local, no need for xgetpwnam */ + if (NULL == pwd) { + (void) fprintf (stderr, _("%s: unknown user %s\n"), + Prog, member); + exit (EXIT_FAILURE); + } + + setgrent (); + while ((grp = getgrent ()) != NULL) { + if (is_on_list (grp->gr_mem, member)) { + if (0 != groups) { + (void) putchar (' '); + } + groups++; + + (void) printf ("%s", grp->gr_name); + if (grp->gr_gid == pwd->pw_gid) { + flag = true; + } + } + } + endgrent (); + + /* The user may not be in the list of members of its primary group */ + if (!flag) { + grp = getgrgid (pwd->pw_gid); /* local, no need for xgetgrgid */ + if (NULL != grp) { + if (0 != groups) { + (void) putchar (' '); + } + groups++; + + (void) printf ("%s", grp->gr_name); + } + } + + if (0 != groups) { + (void) putchar ('\n'); + } +} + +/* + * groups - print out the groups a process is a member of + */ +int main (int argc, char **argv) +{ + long sys_ngroups; + GETGROUPS_T *groups; + + sys_ngroups = sysconf (_SC_NGROUPS_MAX); + groups = (GETGROUPS_T *) malloc (sizeof (GETGROUPS_T) * sys_ngroups); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); + (void) textdomain (PACKAGE); + + /* + * Get the program name so that error messages can use it. + */ + Prog = Basename (argv[0]); + log_set_progname(Prog); + log_set_logfd(stderr); + + if (argc == 1) { + + /* + * Called with no arguments - give the group set for the + * current user. + */ + + int i; + int pri_grp; /* TODO: should be GETGROUPS_T */ + /* + * This system supports concurrent group sets, so I can ask + * the system to tell me which groups are currently set for + * this process. + */ + int ngroups = getgroups (sys_ngroups, groups); + if (ngroups < 0) { + perror ("getgroups"); + exit (EXIT_FAILURE); + } + + /* + * The groupset includes the primary group as well. + */ + pri_grp = getegid (); + for (i = 0; i < ngroups; i++) { + if (pri_grp == (int) groups[i]) { + break; + } + } + + if (i != ngroups) { + pri_grp = -1; + } + + /* + * Print out the name of every group in the current group + * set. Unknown groups are printed as their decimal group ID + * values. + */ + if (-1 != pri_grp) { + struct group *gr; + /* local, no need for xgetgrgid */ + gr = getgrgid (pri_grp); + if (NULL != gr) { + (void) printf ("%s", gr->gr_name); + } else { + (void) printf ("%d", pri_grp); + } + } + + for (i = 0; i < ngroups; i++) { + struct group *gr; + if ((0 != i) || (-1 != pri_grp)) { + (void) putchar (' '); + } + + /* local, no need for xgetgrgid */ + gr = getgrgid (groups[i]); + if (NULL != gr) { + (void) printf ("%s", gr->gr_name); + } else { + (void) printf ("%ld", (long) groups[i]); + } + } + (void) putchar ('\n'); + } else { + + /* + * The invoker wanted to know about some other user. Use + * that name to look up the groups instead. + */ + print_groups (argv[1]); + } + return EXIT_SUCCESS; +} + |