man getgroups notes that no more than NGROUPS_MAX will be returned by the function, suggesting that this is an upper bound on the gidset array that can be used by an application. However, the man page lists only sys/types.h and unistd.h as required include files, and NGROUPS_MAX is not defined in either of those. To get NGROUPS_MAX, it is necessary to include sys/syslimits.h. SYNOPSIS #include <sys/types.h> #include <unistd.h> int getgroups(int gidsetlen, gid_t *gidset) ... number of entries that may be placed in gidset. Getgroups() returns the actual number of groups returned in gidset. No more than NGROUPS_MAX will ever be returned. If gidsetlen is zero, getgroups() returns the number of supplementary group IDs associated with the calling process without modifying the array pointed to by gidset. Fix: Modify man page to include syslimits.h, replicate value into types.h, other bogosities of namespace, remove reference to NGROUPS_MAX in the man page. Note clear which is the worst. What does POSIX say about getgroups()? How-To-Repeat: # cat > test.c #include <sys/types.h> #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { gid_t gidset[NGROUPS_MAX]; int error; error = getgroups(NGROUPS_MAX, gidset); if (error) perror("getgroups"); return (0); } <Ctrl-D> # gcc -o test test.c test.c: In function `main': test.c:7: `NGROUPS_MAX' undeclared (first use in this function) test.c:7: (Each undeclared identifier is reported only once test.c:7: for each function it appears in.)
rwatson@freebsd.org writes: > > >Number: 26003 > >Category: docs > >Synopsis: getgroups(2) lists NGROUPS_MAX but not syslimits.h > >Fix: > > Modify man page to include syslimits.h, replicate value into types.h, > other bogosities of namespace, remove reference to NGROUPS_MAX in the man > page. Note clear which is the worst. I think mentioning syslimits.h in the man page is the best option. NGROUPS_MAX seems to fit in there nicely. If that's acceptable for you, I'll go ahead and fix that. > What does POSIX say about > getgroups()? I don't know, but wollman's "POSIX header file update" doesn't touch it (leaves it in syslimits.h), so it can't be that bad. Thanks Dima Dorfman dima@unixfreak.org
State Changed From-To: open->feedback Is mentioning syslimits.h in the man page sufficient?
-On [20010401 13:00], Bruce Evans (bde@zeta.org.au) wrote: >On Sat, 31 Mar 2001, Robert Watson wrote: > >> Dunno -- I guess this leads to a number of questions of specification-land >> -- is NGROUPS_MAX supposed to be exposed to the application, if so, how >> should the application go about including things to get the value, etc. >> Bruce might have a good answer, if not a correct one, so I've CC'd him >> :-). > >In POSIX.1-1996: > >1) NGROUPS_MAX is defined in <limits.h>. (<sys/syslimits.h> is BSD > implementation detail, so it shouldn't be documented.) > >2) NGROUPS_MAX is a "Run-Time Increasable Value". This means that > applications may find that the actual maximum number of groups is > larger than their compile time value of NGROUPS_MAX. The run time > maximum is given by sysconf(_SC_NGROUPS_MAX). > >3) Unlike some other POSIX limits, NGROUPS_MAX must be defined at > compile time, although its value is almost useless if its run time > value is larger. A footnote says that future revisions of POSIX.1 > are expected to permit omitting the definition of NGROUPS_MAX from > <limits.h> to indicate that its value is variable. Latest POSIX draft specifies: SYNOPSIS #include <unistd.h> int getgroups(int gidsetsize, gid_t grouplist[]); [...] Applications writers should note that {NGROUPS_MAX} is not necessarily a constant on all implementations. [...] Issue 6 In the SYNOPSIS, the optional include of the <sys/types.h> header is removed. The following new requirements on POSIX implementations derive from alignment with the Single UNIX Specification: · The requirement to include <sys/types.h> has been removed. Although <sys/types.h> was required for conforming implementations of previous POSIX specifications, it was not required for UNIX applications. · A return value of 0 is not permitted, because {NGROUPS_MAX} cannot be 0. This is a FIPS requirement. -- Jeroen Ruigrok van der Werven/Asmodai asmodai@[wxs.nl|freebsd.org|xmach.org] Documentation nutter/C-rated Coder, finger asmodai@ninth-circle.dnsalias.net http://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/ The human race is challenged more than ever before to demonstrate our mastery -- not over nature but of ourselves...
Responsible Changed From-To: freebsd-doc->rwatson Reading the audit trail it doesn't look as though this is a doc bug. It seems we may need to change the headers and/or examples if we want POSIX compliance. What do you think, Robert?
State Changed From-To: feedback->analyzed It seems like we understand the problem, but still no conclusion on the exact fix--perhaps unistd.h needs to find NGROUPS_MAX somehow without polluting the namespace too much more?
Responsible Changed From-To: rwatson->freebsd-standards Assign to freebsd-standards as they may have a better sense of how to deal with this one.
On Sun, 27 Jan 2008 rwatson@freebsd.org wrote: > Synopsis: getgroups(2) lists NGROUPS_MAX but not syslimits.h > It seems like we understand the problem, but still no conclusion on the > exact fix--perhaps unistd.h needs to find NGROUPS_MAX somehow without > polluting the namespace too much more? Of course not. There are only man page bugs. There is a good interface for determining the size of the array needed, and it doesn't involve {NGROUPS_MAX} -- just call getgroups() with gidsetlen == 0 to determine the size. Synopses shouldn't mention includes that are only needed for some uses of interfaces, especially here since the use is a bad one (to be unportable by hard-coding NGROUPS_MAX). The includes are already sufficient for using {NGROUPS_MAX} in its portable form sysconf(_SC_NGROUPS_MAX), except you will also need malloc(). <stdlib.h> for using malloc() is another include that doesn't belong in the synopsis. If you want better wording for {NGROUPS_MAX} in this man page, see POSIX. POSIX.1-2001-draft7 actually doesn't do much more than say {NGROUPS_MAX}+1 where FreeBSD says NGROUPS_MAX. The {FOO} markup is documented elsewhere. It is very useful for avoiding repeating the documentation of the messes required for using limits. It is barely used in FreeBSD (FreeBSD tends to document only unportabilities like hard-coding NAME_MAX and PATH_MAX). The +1 is because the euid may be returned in the list. FreeBSD apparently doesn't do this, and its man page doesn't say that it might be needed. POSIX gives an example of using sysconf(_SC_NGROUPS_MAX) will no error checking for sysconf() or malloc(). POSIX's rationale for getgroups() notes that {NGROUPS_MAX} might not be constant. Bruce
<<On Sun, 27 Jan 2008 16:00:04 GMT, Bruce Evans <brde@optusnet.com.au> said: > one (to be unportable by hard-coding NGROUPS_MAX). The includes are > already sufficient for using {NGROUPS_MAX} in its portable form > sysconf(_SC_NGROUPS_MAX), except you will also need malloc(). <stdlib.h> > for using malloc() is another include that doesn't belong in the > synopsis. What Bruce said. It would be better for constants such as this to be left completely undefined (at least when not compiling the kernel) -- although there is the inevitable tension between handling these limits correctly and handling broken applications that do things like #ifndef NGROUPS_MAX #define NGROUPS_MAX 8 #endif Those applications, at least, are clearly wrong, so my vote would be on the side of breaking the applications and doing the Right Thing by not defining NGROUPS_MAX. -GAWollman
It appears the getgroups(2) manual page has been updated while this ticket was dormant. This issue should probably be closed.
Value of NGROUPS_MAX was clarified in r217704