Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcvs2svn <>2002-09-22 16:04:17 +0400
committercvs2svn <>2002-09-22 16:04:17 +0400
commite8038acb1b5f441fe7b2570c9448cf73b2038477 (patch)
tree9bc675d4928360fc4998eb5a43727fd1a4ce427d /winsup/cygwin/grp.cc
parent9783ce28caf426c5ab39d1d6aefa31cfdb1b8234 (diff)
This commit was manufactured by cvs2svn to create tagZ-cygwin_daemon_merge_HEAD
'Z-cygwin_daemon_merge_HEAD'. Sprout from cygwin_daemon 2002-01-02 00:06:36 UTC cvs2svn 'This commit was manufactured by cvs2svn to create branch 'cygwin_daemon'.' Cherrypick from cygwin_daemon 2002-02-25 17:47:52 UTC cvs2svn 'This commit was manufactured by cvs2svn to create branch 'cygwin_daemon'.': winsup/cygwin/how-spawn-works.txt winsup/cygwin/wsock_event.h Cherrypick from cygwin_daemon 2002-06-06 15:35:10 UTC cvs2svn 'This commit was manufactured by cvs2svn to create branch 'cygwin_daemon'.': winsup/cygwin/include/netinet/udp.h winsup/cygwin/stackdump.sgml Cherrypick from cygwin_daemon 2002-01-17 10:39:38 UTC cvs2svn 'This commit was manufactured by cvs2svn to create branch 'cygwin_daemon'.': winsup/cygwin/libc/fnmatch.c Cherrypick from cygwin_daemon 2002-07-03 20:31:40 UTC cvs2svn 'This commit was manufactured by cvs2svn to create branch 'cygwin_daemon'.': winsup/cygwin/include/sys/statfs.h Cherrypick from cygwin_daemon 2002-09-04 15:17:25 UTC cvs2svn 'This commit was manufactured by cvs2svn to create branch 'cygwin_daemon'.': winsup/cygwin/how-autoload-works.txt Cherrypick from master 2002-09-22 12:04:15 UTC Conrad Scott <conrad.scott@dsl.pipex.com> '2002-09-22 Conrad Scott <conrad.scott@dsl.pipex.com>': winsup/cygserver/threaded_queue.cc winsup/cygserver/woutsup.h winsup/cygwin/CYGWIN_LICENSE winsup/cygwin/ChangeLog winsup/cygwin/ChangeLog-1998 winsup/cygwin/ChangeLog-1999 winsup/cygwin/ChangeLog-2000 winsup/cygwin/Makefile.in winsup/cygwin/assert.cc winsup/cygwin/autoload.cc winsup/cygwin/child_info.h winsup/cygwin/configure winsup/cygwin/configure.in winsup/cygwin/cygerrno.h winsup/cygwin/cygheap.cc winsup/cygwin/cygheap.h winsup/cygwin/cygmagic winsup/cygwin/cygmalloc.h winsup/cygwin/cygrun.c winsup/cygwin/cygserver.cc winsup/cygwin/cygserver_client.cc winsup/cygwin/cygserver_ipc.h winsup/cygwin/cygserver_process.cc winsup/cygwin/cygserver_shm.cc winsup/cygwin/cygserver_shm.h winsup/cygwin/cygserver_transport.cc winsup/cygwin/cygserver_transport_pipes.cc winsup/cygwin/cygserver_transport_sockets.cc winsup/cygwin/cygthread.cc winsup/cygwin/cygthread.h winsup/cygwin/cygwin.din winsup/cygwin/cygwin.sc winsup/cygwin/dcrt0.cc winsup/cygwin/debug.cc winsup/cygwin/debug.h winsup/cygwin/dir.cc winsup/cygwin/dlfcn.cc winsup/cygwin/dll_init.cc winsup/cygwin/dll_init.h winsup/cygwin/dlmalloc.c winsup/cygwin/dtable.cc winsup/cygwin/dtable.h winsup/cygwin/environ.cc winsup/cygwin/environ.h winsup/cygwin/errno.cc winsup/cygwin/exceptions.cc winsup/cygwin/exec.cc winsup/cygwin/external.cc winsup/cygwin/fcntl.cc winsup/cygwin/fhandler.cc winsup/cygwin/fhandler.h winsup/cygwin/fhandler_clipboard.cc winsup/cygwin/fhandler_console.cc winsup/cygwin/fhandler_disk_file.cc winsup/cygwin/fhandler_dsp.cc winsup/cygwin/fhandler_floppy.cc winsup/cygwin/fhandler_mem.cc winsup/cygwin/fhandler_proc.cc winsup/cygwin/fhandler_process.cc winsup/cygwin/fhandler_random.cc winsup/cygwin/fhandler_raw.cc winsup/cygwin/fhandler_registry.cc winsup/cygwin/fhandler_serial.cc winsup/cygwin/fhandler_socket.cc winsup/cygwin/fhandler_tape.cc winsup/cygwin/fhandler_termios.cc winsup/cygwin/fhandler_tty.cc winsup/cygwin/fhandler_virtual.cc winsup/cygwin/fhandler_windows.cc winsup/cygwin/fhandler_zero.cc winsup/cygwin/fork.cc winsup/cygwin/glob.c winsup/cygwin/gmon.c winsup/cygwin/grp.cc winsup/cygwin/heap.cc winsup/cygwin/heap.h winsup/cygwin/hires.h winsup/cygwin/how-cygheap-works.txt winsup/cygwin/how-fhandlers-work.txt winsup/cygwin/how-signals-work.txt winsup/cygwin/how-to-debug-cygwin.txt winsup/cygwin/include/cygwin/acl.h winsup/cygwin/include/cygwin/cygserver.h winsup/cygwin/include/cygwin/cygserver_process.h winsup/cygwin/include/cygwin/cygserver_transport.h winsup/cygwin/include/cygwin/cygserver_transport_pipes.h winsup/cygwin/include/cygwin/cygserver_transport_sockets.h winsup/cygwin/include/cygwin/grp.h winsup/cygwin/include/cygwin/if.h winsup/cygwin/include/cygwin/ipc.h winsup/cygwin/include/cygwin/msg.h winsup/cygwin/include/cygwin/mtio.h winsup/cygwin/include/cygwin/sem.h winsup/cygwin/include/cygwin/shm.h winsup/cygwin/include/cygwin/socket.h winsup/cygwin/include/cygwin/stat.h winsup/cygwin/include/cygwin/types.h winsup/cygwin/include/cygwin/version.h winsup/cygwin/include/fnmatch.h winsup/cygwin/include/getopt.h winsup/cygwin/include/glob.h winsup/cygwin/include/limits.h winsup/cygwin/include/netdb.h winsup/cygwin/include/netinet/ip.h winsup/cygwin/include/netinet/tcp.h winsup/cygwin/include/pthread.h winsup/cygwin/include/sys/cygwin.h winsup/cygwin/include/sys/ioctl.h winsup/cygwin/include/sys/mount.h winsup/cygwin/include/sys/resource.h winsup/cygwin/include/sys/socket.h winsup/cygwin/include/sys/soundcard.h winsup/cygwin/include/sys/strace.h winsup/cygwin/include/sys/sysmacros.h winsup/cygwin/include/sys/termios.h winsup/cygwin/include/sys/uio.h winsup/cygwin/include/sys/un.h winsup/cygwin/include/sys/vfs.h winsup/cygwin/init.cc winsup/cygwin/ioctl.cc winsup/cygwin/ipc.cc winsup/cygwin/lib/cygwin_crt0.c winsup/cygwin/lib/dll_main.cc winsup/cygwin/lib/getopt.c winsup/cygwin/localtime.cc winsup/cygwin/malloc.cc winsup/cygwin/malloc_wrapper.cc winsup/cygwin/miscfuncs.cc winsup/cygwin/mkvers.sh winsup/cygwin/mmap.cc winsup/cygwin/msg.cc winsup/cygwin/net.cc winsup/cygwin/ntdll.h winsup/cygwin/ntea.cc winsup/cygwin/passwd.cc winsup/cygwin/path.cc winsup/cygwin/path.h winsup/cygwin/perthread.h winsup/cygwin/pinfo.cc winsup/cygwin/pinfo.h winsup/cygwin/pipe.cc winsup/cygwin/poll.cc winsup/cygwin/pthread.cc winsup/cygwin/pwdgrp.h winsup/cygwin/regex/regcomp.c winsup/cygwin/registry.cc winsup/cygwin/resource.cc winsup/cygwin/safe_memory.h winsup/cygwin/sched.cc winsup/cygwin/sec_acl.cc winsup/cygwin/sec_helper.cc winsup/cygwin/security.cc winsup/cygwin/security.h winsup/cygwin/select.cc winsup/cygwin/sem.cc winsup/cygwin/shared.cc winsup/cygwin/shared_info.h winsup/cygwin/shm.cc winsup/cygwin/signal.cc winsup/cygwin/sigproc.cc winsup/cygwin/sigproc.h winsup/cygwin/smallprint.c winsup/cygwin/spawn.cc winsup/cygwin/speclib winsup/cygwin/strace.cc winsup/cygwin/sync.cc winsup/cygwin/sync.h winsup/cygwin/syscalls.cc winsup/cygwin/sysconf.cc winsup/cygwin/syslog.cc winsup/cygwin/termios.cc winsup/cygwin/thread.cc winsup/cygwin/thread.h winsup/cygwin/threaded_queue.cc winsup/cygwin/threaded_queue.h winsup/cygwin/times.cc winsup/cygwin/tty.cc winsup/cygwin/tty.h winsup/cygwin/uinfo.cc winsup/cygwin/uname.cc winsup/cygwin/wait.cc winsup/cygwin/winbase.h winsup/cygwin/wincap.cc winsup/cygwin/wincap.h winsup/cygwin/window.cc winsup/cygwin/winsup.h winsup/cygwin/winver.rc winsup/cygwin/woutsup.h Delete: winsup/cygwin/include/cygwin/ip.h winsup/cygwin/include/sys/ipc.h winsup/cygwin/include/sys/shm.h winsup/cygwin/include/wchar.h winsup/cygwin/lib/_cygwin_S_IEXEC.cc winsup/cygwin/regexp/regerror.c winsup/cygwin/regexp/regexp.3 winsup/cygwin/regexp/regexp.c winsup/cygwin/regexp/regsub.c winsup/cygwin/shortcut.c winsup/cygwin/shortcut.h winsup/cygwin/test.c
Diffstat (limited to 'winsup/cygwin/grp.cc')
-rw-r--r--winsup/cygwin/grp.cc323
1 files changed, 238 insertions, 85 deletions
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index 87cc4b484..175fd241f 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -1,6 +1,6 @@
/* grp.cc
- Copyright 1996, 1997, 1998, 2000, 2001 Red Hat, Inc.
+ Copyright 1996, 1997, 1998, 2000, 2001, 2002 Red Hat, Inc.
Original stubs by Jason Molenda of Cygnus Support, crash@cygnus.com
First implementation by Gunther Ebert, gunther.ebert@ixos-leipzig.de
@@ -17,28 +17,25 @@ details. */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
-#include "sync.h"
-#include "sigproc.h"
#include "pinfo.h"
#include "security.h"
#include "fhandler.h"
#include "path.h"
#include "dtable.h"
-#include "cygheap.h"
#include "cygerrno.h"
+#include "cygheap.h"
#include "pwdgrp.h"
/* Read /etc/group only once for better performance. This is done
on the first call that needs information from it. */
-static NO_COPY const char *etc_group = "/etc/group";
-static struct group *group_buf; /* group contents in memory */
+static struct __group32 *group_buf; /* group contents in memory */
static int curr_lines;
static int max_lines;
/* Position in the group cache */
#ifdef _MT_SAFE
-#define grp_pos _reent_winsup()->_grp_pos
+#define grp_pos _reent_winsup ()->_grp_pos
#else
static int grp_pos = 0;
#endif
@@ -46,22 +43,19 @@ static int grp_pos = 0;
static pwdgrp_check group_state;
static int
-parse_grp (struct group &grp, const char *line)
+parse_grp (struct __group32 &grp, char *line)
{
- int len = strlen(line);
- char *newline = (char *) malloc (len + 1);
- (void) memcpy (newline, line, len + 1);
-
- if (newline[--len] == '\n')
- newline[len] = '\0';
+ int len = strlen (line);
+ if (line[--len] == '\r')
+ line[len] = '\0';
- char *dp = strchr (newline, ':');
+ char *dp = strchr (line, ':');
if (!dp)
return 0;
*dp++ = '\0';
- grp.gr_name = newline;
+ grp.gr_name = line;
grp.gr_passwd = dp;
dp = strchr (grp.gr_passwd, ':');
@@ -106,12 +100,12 @@ parse_grp (struct group &grp, const char *line)
/* Read one line from /etc/group into the group cache */
static void
-add_grp_line (const char *line)
+add_grp_line (char *line)
{
if (curr_lines == max_lines)
{
max_lines += 10;
- group_buf = (struct group *) realloc (group_buf, max_lines * sizeof (struct group));
+ group_buf = (struct __group32 *) realloc (group_buf, max_lines * sizeof (struct __group32));
}
if (parse_grp (group_buf[curr_lines], line))
curr_lines++;
@@ -119,17 +113,23 @@ add_grp_line (const char *line)
class group_lock
{
- pthread_mutex_t mutex;
+ bool armed;
+ static NO_COPY pthread_mutex_t mutex;
public:
- group_lock (): mutex ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER) {}
- void arm () {pthread_mutex_lock (&mutex); }
+ group_lock (bool doit)
+ {
+ if (armed = doit)
+ pthread_mutex_lock (&mutex);
+ }
~group_lock ()
{
- if (mutex != (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)
+ if (armed)
pthread_mutex_unlock (&mutex);
}
};
+pthread_mutex_t NO_COPY group_lock::mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
+
/* Cygwin internal */
/* Read in /etc/group and save contents in the group cache */
/* This sets group_in_memory_p to 1 so functions in this file can
@@ -139,15 +139,9 @@ class group_lock
void
read_etc_group ()
{
- char linebuf [200];
- char group_name [UNLEN + 1];
- DWORD group_name_len = UNLEN + 1;
+ static pwdgrp_read gr;
- strncpy (group_name, "Administrators", sizeof (group_name));
-
- static NO_COPY group_lock here;
- if (cygwin_finished_initializing)
- here.arm ();
+ group_lock here (cygwin_finished_initializing);
/* if we got blocked by the mutex, then etc_group may have been processed */
if (group_state != uninitialized)
@@ -156,64 +150,100 @@ read_etc_group ()
if (group_state != initializing)
{
group_state = initializing;
- if (max_lines) /* When rereading, free allocated memory first. */
- {
- for (int i = 0; i < curr_lines; ++i)
- {
- free (group_buf[i].gr_name);
- free (group_buf[i].gr_mem);
- }
- curr_lines = 0;
- }
-
- FILE *f = fopen (etc_group, "rt");
-
- if (f)
+ if (gr.open ("/etc/group"))
{
- while (fgets (linebuf, sizeof (linebuf), f) != NULL)
- {
- if (strlen (linebuf))
- add_grp_line (linebuf);
- }
+ char *line;
+ while ((line = gr.gets ()) != NULL)
+ if (strlen (line))
+ add_grp_line (line);
- group_state.set_last_modified (f);
- fclose (f);
+ group_state.set_last_modified (gr.get_fhandle (), gr.get_fname ());
group_state = loaded;
+ gr.close ();
+ debug_printf ("Read /etc/group, %d lines", curr_lines);
}
else /* /etc/group doesn't exist -- create default one in memory */
{
+ char group_name [UNLEN + 1];
+ DWORD group_name_len = UNLEN + 1;
char domain_name [INTERNET_MAX_HOST_NAME_LENGTH + 1];
DWORD domain_name_len = INTERNET_MAX_HOST_NAME_LENGTH + 1;
SID_NAME_USE acType;
- debug_printf ("Emulating /etc/group");
- if (! LookupAccountSidA (NULL ,
- well_known_admins_sid,
- group_name,
- &group_name_len,
- domain_name,
- &domain_name_len,
- &acType))
+ static char linebuf [200];
+
+ if (wincap.has_security ())
{
- strcpy (group_name, "unknown");
- debug_printf ("Failed to get local admins group name. %E");
+ HANDLE ptok;
+ cygsid tg;
+ DWORD siz;
+
+ if (OpenProcessToken (hMainProc, TOKEN_QUERY, &ptok))
+ {
+ if (GetTokenInformation (ptok, TokenPrimaryGroup, &tg,
+ sizeof tg, &siz)
+ && LookupAccountSidA (NULL, tg, group_name,
+ &group_name_len, domain_name,
+ &domain_name_len, &acType))
+ {
+ char strbuf[100];
+ snprintf (linebuf, sizeof (linebuf), "%s:%s:%lu:",
+ group_name,
+ tg.string (strbuf),
+ *GetSidSubAuthority (tg,
+ *GetSidSubAuthorityCount (tg) - 1));
+ debug_printf ("Emulating /etc/group: %s", linebuf);
+ add_grp_line (linebuf);
+ group_state = emulated;
+ }
+ CloseHandle (ptok);
+ }
+ }
+ if (group_state != emulated)
+ {
+ strncpy (group_name, "Administrators", sizeof (group_name));
+ if (!LookupAccountSidA (NULL, well_known_admins_sid, group_name,
+ &group_name_len, domain_name,
+ &domain_name_len, &acType))
+ {
+ strcpy (group_name, "unknown");
+ debug_printf ("Failed to get local admins group name. %E");
+ }
+ snprintf (linebuf, sizeof (linebuf), "%s::%u:", group_name,
+ (unsigned) DEFAULT_GID);
+ debug_printf ("Emulating /etc/group: %s", linebuf);
+ add_grp_line (linebuf);
+ group_state = emulated;
}
-
- snprintf (linebuf, sizeof (linebuf), "%s::%u:\n", group_name, DEFAULT_GID);
- add_grp_line (linebuf);
- group_state = emulated;
}
}
return;
}
+static
+struct __group16 *
+grp32togrp16 (struct __group16 *gp16, struct __group32 *gp32)
+{
+ if (!gp16 || !gp32)
+ return NULL;
+
+ /* Copying the pointers is actually unnecessary. Just having the correct
+ return type is important. */
+ gp16->gr_name = gp32->gr_name;
+ gp16->gr_passwd = gp32->gr_passwd;
+ gp16->gr_gid = (__gid16_t) gp32->gr_gid; /* Not loss-free */
+ gp16->gr_mem = gp32->gr_mem;
+
+ return gp16;
+}
+
extern "C"
-struct group *
-getgrgid (gid_t gid)
+struct __group32 *
+getgrgid32 (__gid32_t gid)
{
- struct group * default_grp = NULL;
+ struct __group32 * default_grp = NULL;
if (group_state <= initializing)
- read_etc_group();
+ read_etc_group ();
for (int i = 0; i < curr_lines; i++)
{
@@ -223,15 +253,24 @@ getgrgid (gid_t gid)
return group_buf + i;
}
- return default_grp;
+ return allow_ntsec ? NULL : default_grp;
}
extern "C"
-struct group *
-getgrnam (const char *name)
+struct __group16 *
+getgrgid (__gid16_t gid)
+{
+ static struct __group16 g16;
+
+ return grp32togrp16 (&g16, getgrgid32 ((__gid32_t) gid));
+}
+
+extern "C"
+struct __group32 *
+getgrnam32 (const char *name)
{
if (group_state <= initializing)
- read_etc_group();
+ read_etc_group ();
for (int i = 0; i < curr_lines; i++)
if (strcasematch (group_buf[i].gr_name, name))
@@ -242,18 +281,27 @@ getgrnam (const char *name)
}
extern "C"
+struct __group16 *
+getgrnam (const char *name)
+{
+ static struct __group16 g16;
+
+ return grp32togrp16 (&g16, getgrnam32 (name));
+}
+
+extern "C"
void
-endgrent()
+endgrent ()
{
grp_pos = 0;
}
extern "C"
-struct group *
-getgrent()
+struct __group32 *
+getgrent32 ()
{
if (group_state <= initializing)
- read_etc_group();
+ read_etc_group ();
if (grp_pos < curr_lines)
return group_buf + grp_pos++;
@@ -262,6 +310,15 @@ getgrent()
}
extern "C"
+struct __group16 *
+getgrent ()
+{
+ static struct __group16 g16;
+
+ return grp32togrp16 (&g16, getgrent32 ());
+}
+
+extern "C"
void
setgrent ()
{
@@ -269,11 +326,11 @@ setgrent ()
}
/* Internal function. ONLY USE THIS INTERNALLY, NEVER `getgrent'!!! */
-struct group *
+struct __group32 *
internal_getgrent (int pos)
{
if (group_state <= initializing)
- read_etc_group();
+ read_etc_group ();
if (pos < curr_lines)
return group_buf + pos;
@@ -281,15 +338,16 @@ internal_getgrent (int pos)
}
int
-getgroups (int gidsetsize, gid_t *grouplist, gid_t gid, const char *username)
+getgroups32 (int gidsetsize, __gid32_t *grouplist, __gid32_t gid,
+ const char *username)
{
HANDLE hToken = NULL;
DWORD size;
int cnt = 0;
- struct group *gr;
+ struct __group32 *gr;
if (group_state <= initializing)
- read_etc_group();
+ read_etc_group ();
if (allow_ntsec &&
OpenProcessToken (hMainProc, TOKEN_QUERY, &hToken))
@@ -307,7 +365,8 @@ getgroups (int gidsetsize, gid_t *grouplist, gid_t gid, const char *username)
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
if (sid.getfromgr (gr))
for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
- if (sid == groups->Groups[pg].Sid)
+ if (sid == groups->Groups[pg].Sid &&
+ sid != well_known_world_sid)
{
if (cnt < gidsetsize)
grouplist[cnt] = gr->gr_gid;
@@ -356,14 +415,108 @@ error:
extern "C"
int
-getgroups (int gidsetsize, gid_t *grouplist)
+getgroups32 (int gidsetsize, __gid32_t *grouplist)
{
- return getgroups (gidsetsize, grouplist, myself->gid, cygheap->user.name ());
+ return getgroups32 (gidsetsize, grouplist, myself->gid,
+ cygheap->user.name ());
+}
+
+extern "C"
+int
+getgroups (int gidsetsize, __gid16_t *grouplist)
+{
+ __gid32_t *grouplist32 = NULL;
+
+ if (gidsetsize < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (gidsetsize > 0 && grouplist)
+ grouplist32 = (__gid32_t *) alloca (gidsetsize * sizeof (__gid32_t));
+
+ int ret = getgroups32 (gidsetsize, grouplist32, myself->gid,
+ cygheap->user.name ());
+
+ if (gidsetsize > 0 && grouplist)
+ for (int i = 0; i < ret; ++ i)
+ grouplist[i] = grouplist32[i];
+
+ return ret;
}
extern "C"
int
-initgroups (const char *, gid_t)
+initgroups32 (const char *, __gid32_t)
{
+ if (wincap.has_security ())
+ cygheap->user.groups.clear_supp ();
return 0;
}
+
+extern "C"
+int
+initgroups (const char * name, __gid16_t gid)
+{
+ return initgroups32 (name, gid16togid32(gid));
+}
+
+/* setgroups32: standards? */
+extern "C"
+int
+setgroups32 (int ngroups, const __gid32_t *grouplist)
+{
+ if (ngroups < 0 || (ngroups > 0 && !grouplist))
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ if (!wincap.has_security ())
+ return 0;
+
+ cygsidlist gsids (cygsidlist_alloc, ngroups);
+ struct __group32 *gr;
+
+ if (ngroups && !gsids.sids)
+ return -1;
+
+ for (int gidx = 0; gidx < ngroups; ++gidx)
+ {
+ for (int gidy = 0; gidy < gidx; gidy++)
+ if (grouplist[gidy] == grouplist[gidx])
+ goto found; /* Duplicate */
+ for (int gidy = 0; (gr = internal_getgrent (gidy)); ++gidy)
+ if (gr->gr_gid == (__gid32_t) grouplist[gidx])
+ {
+ if (gsids.addfromgr (gr))
+ goto found;
+ break;
+ }
+ debug_printf ("No sid found for gid %d", grouplist[gidx]);
+ gsids.free_sids ();
+ set_errno (EINVAL);
+ return -1;
+ found:
+ continue;
+ }
+ cygheap->user.groups.update_supp (gsids);
+ return 0;
+}
+
+extern "C"
+int
+setgroups (int ngroups, const __gid16_t *grouplist)
+{
+ __gid32_t *grouplist32 = NULL;
+
+ if (ngroups > 0 && grouplist)
+ {
+ grouplist32 = (__gid32_t *) alloca (ngroups * sizeof (__gid32_t));
+ if (grouplist32 == NULL)
+ return -1;
+ for (int i = 0; i < ngroups; i++)
+ grouplist32[i] = grouplist[i];
+ }
+ return setgroups32 (ngroups, grouplist32);
+}