zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: $usergroups in zsh/parameter
@ 2011-01-19 12:26 Peter Stephenson
  0 siblings, 0 replies; only message in thread
From: Peter Stephenson @ 2011-01-19 12:26 UTC (permalink / raw)
  To: Zsh Hackers' List

I didn't call it just "groups" since it's a bit ambiguous whose groups
they are.  If this was for Windows it would be mygroups, but it isn't.

I think all relevant system interfaces are long-standing standards.

Index: Doc/Zsh/mod_parameter.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_parameter.yo,v
retrieving revision 1.13
diff -p -u -r1.13 mod_parameter.yo
--- Doc/Zsh/mod_parameter.yo	18 Dec 2008 09:49:04 -0000	1.13
+++ Doc/Zsh/mod_parameter.yo	19 Jan 2011 12:23:31 -0000
@@ -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
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.173
diff -p -u -r1.173 zsh.h
--- Src/zsh.h	6 Jan 2011 16:49:26 -0000	1.173
+++ Src/zsh.h	19 Jan 2011 12:23:31 -0000
@@ -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)
Index: Src/Modules/parameter.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v
retrieving revision 1.52
diff -p -u -r1.52 parameter.c
--- Src/Modules/parameter.c	12 Dec 2010 22:44:51 -0000	1.52
+++ Src/Modules/parameter.c	19 Jan 2011 12:23:31 -0000
@@ -1820,6 +1820,141 @@ scanpmdissaliases(HashTable ht, ScanFunc
     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 = {


-- 
Peter Stephenson <pws@csr.com>            Software Engineer
Tel: +44 (0)1223 692070                   Cambridge Silicon Radio Limited
Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, UK


Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-01-19 12:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-19 12:26 PATCH: $usergroups in zsh/parameter Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).