1
0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-09-28 15:01:21 +02:00

28638: add $usergroups parameter

This commit is contained in:
Peter Stephenson 2011-01-19 12:42:53 +00:00
parent aa58d139ff
commit 94225e07fc
5 changed files with 176 additions and 2 deletions

@ -1,3 +1,9 @@
2011-01-19 Peter Stephenson <pws@csr.com>
* 28638: Doc/Zsh/parameter.yo, Src/zsh.h,
Src/Modules/parameter.c, plus NEWS added: add $usergroups hash
mapping from user's own groups by name to GID.
2011-01-18 Peter Stephenson <pws@csr.com>
* Mikael: 28637: Src/subst.c: ${foo:0:} caused crash.
@ -14147,5 +14153,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
* $Revision: 1.5188 $
* $Revision: 1.5189 $
*****************************************************

@ -164,6 +164,12 @@ item(tt(userdirs))(
This associative array maps user names to the pathnames of their home
directories.
)
vindex(usergroups)
item(tt(usergroups))(
This associative array maps names of system groups of which the current
user is a member to the corresponding group identifiers. The contents
are the same as the groups output by the tt(id) command.
)
vindex(funcfiletrace)
item(tt(funcfiletrace))(
This array contains the absolute line numbers and corresponding file

8
NEWS

@ -4,6 +4,14 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH
Note also the list of incompatibilities in the README file.
Changes since 4.3.11
--------------------
The zsh/parameter module has a new readonly associative array
$usergroups whose keys are the names of system groups of which the
current user is a member and whose values are the corresponding
group identifiers.
Changes between versions 4.3.10 and 4.3.11
------------------------------------------

@ -1820,6 +1820,141 @@ scanpmdissaliases(HashTable ht, ScanFunc func, int flags)
scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX|DISABLED);
}
/* Functions for the usergroups special parameter */
/*
* Get GID and names for groups of which the current user is a member.
*/
/**/
static Groupset get_all_groups(void)
{
Groupset gs = zhalloc(sizeof(*gs));
Groupmap gaptr;
gid_t *list, *lptr, egid;
int add_egid;
struct group *grptr;
egid = getegid();
add_egid = 1;
gs->num = getgroups(0, NULL);
if (gs->num > 0) {
list = zhalloc(gs->num * sizeof(*list));
if (getgroups(gs->num, list) < 0) {
return NULL;
}
/*
* It's unspecified whether $EGID is included in the
* group set, so check.
*/
for (lptr = list; lptr < list + gs->num; lptr++) {
if (*lptr == egid) {
add_egid = 0;
break;
}
}
gs->array = zhalloc((gs->num + add_egid) * sizeof(*gs->array));
/* Put EGID if needed first */
gaptr = gs->array + add_egid;
for (lptr = list; lptr < list + gs->num; lptr++) {
gaptr->gid = *lptr;
gaptr++;
}
gs->num += add_egid;
} else {
/* Just use effective GID */
gs->num = 1;
gs->array = zhalloc(sizeof(*gs->array));
}
if (add_egid) {
gs->array->gid = egid;
}
/* Get group names */
for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
grptr = getgrgid(gaptr->gid);
if (!grptr) {
return NULL;
}
gaptr->name = dupstring(grptr->gr_name);
}
return gs;
}
/* Standard hash element lookup. */
/**/
static HashNode
getpmusergroups(UNUSED(HashTable ht), const char *name)
{
Param pm = NULL;
Groupset gs = get_all_groups();
Groupmap gaptr;
pm = (Param)hcalloc(sizeof(struct param));
pm->node.nam = dupstring(name);
pm->node.flags = PM_SCALAR | PM_READONLY;
pm->gsu.s = &nullsetscalar_gsu;
if (!gs) {
zerr("failed to retrieve groups for user: %e", errno);
pm->u.str = dupstring("");
pm->node.flags |= PM_UNSET;
return &pm->node;
}
for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
if (!strcmp(name, gaptr->name)) {
char buf[DIGBUFSIZE];
sprintf(buf, "%d", (int)gaptr->gid);
pm->u.str = dupstring(buf);
return &pm->node;
}
}
pm->u.str = dupstring("");
pm->node.flags |= PM_UNSET;
return &pm->node;
}
/* Standard hash scan. */
/**/
static void
scanpmusergroups(UNUSED(HashTable ht), ScanFunc func, int flags)
{
struct param pm;
Groupset gs = get_all_groups();
Groupmap gaptr;
if (!gs) {
zerr("failed to retrieve groups for user: %e", errno);
return;
}
memset((void *)&pm, 0, sizeof(pm));
pm.node.flags = PM_SCALAR | PM_READONLY;
pm.gsu.s = &nullsetscalar_gsu;
for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
pm.node.nam = gaptr->name;
if (func != scancountparams &&
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
!(flags & SCANPM_WANTKEYS))) {
char buf[DIGBUFSIZE];
sprintf(buf, "%d", (int)gaptr->gid);
pm.u.str = dupstring(buf);
}
func(&pm.node, flags);
}
}
/* Table for defined parameters. */
struct pardef {
@ -1926,7 +2061,9 @@ static struct paramdef partab[] = {
SPECIALPMDEF("saliases", 0,
&pmsaliases_gsu, getpmsalias, scanpmsaliases),
SPECIALPMDEF("userdirs", PM_READONLY,
NULL, getpmuserdir, scanpmuserdirs)
NULL, getpmuserdir, scanpmuserdirs),
SPECIALPMDEF("usergroups", PM_READONLY,
NULL, getpmusergroups, scanpmusergroups)
};
static struct features module_features = {

@ -1731,6 +1731,23 @@ struct nameddir {
#define ND_USERNAME (1<<1) /* nam is actually a username */
#define ND_NOABBREV (1<<2) /* never print as abbrev (PWD or OLDPWD) */
/* Storage for single group/name mapping */
typedef struct {
/* Name of group */
char *name;
/* Group identifier */
gid_t gid;
} groupmap;
typedef groupmap *Groupmap;
/* Storage for a set of group/name mappings */
typedef struct {
/* The set of name to gid mappings */
Groupmap array;
/* A count of the valid entries in groupmap. */
int num;
} groupset;
typedef groupset *Groupset;
/* flags for controlling printing of hash table nodes */
#define PRINT_NAMEONLY (1<<0)