From 3785beb7f5596125e55610f587b534837fc3e73b Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Tue, 1 Oct 2013 22:23:50 +0200 Subject: [PATCH] Implement the API properly. --- Makefile | 1 + libc/Makefile | 12 +- libc/grp/endgrent.cpp | 34 +++++ libc/grp/fgetgrent.cpp | 57 ++++++++ libc/grp/fgetgrent_r.cpp | 211 +++++++++++++++++++++++++++ libc/grp/getgrent.cpp | 35 +++++ libc/grp/getgrent_r.cpp | 39 +++++ libc/grp/{grent.cpp => getgrgid.cpp} | 69 ++++----- libc/grp/getgrgid_r.cpp | 54 +++++++ libc/grp/getgrnam.cpp | 58 ++++++++ libc/grp/getgrnam_r.cpp | 55 +++++++ libc/grp/opengr.cpp | 31 ++++ libc/grp/setgrent.cpp | 34 +++++ libc/include/grp.h | 27 +++- 14 files changed, 671 insertions(+), 46 deletions(-) create mode 100644 libc/grp/endgrent.cpp create mode 100644 libc/grp/fgetgrent.cpp create mode 100644 libc/grp/fgetgrent_r.cpp create mode 100644 libc/grp/getgrent.cpp create mode 100644 libc/grp/getgrent_r.cpp rename libc/grp/{grent.cpp => getgrgid.cpp} (52%) create mode 100644 libc/grp/getgrgid_r.cpp create mode 100644 libc/grp/getgrnam.cpp create mode 100644 libc/grp/getgrnam_r.cpp create mode 100644 libc/grp/opengr.cpp create mode 100644 libc/grp/setgrent.cpp diff --git a/Makefile b/Makefile index b81e6fae..1e7628fa 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ sysroot-fsh: mkdir -p "$(SYSROOT)/src" mkdir -p "$(SYSROOT)/tmp" echo "root::0:0:root:/root:sh" > "$(SYSROOT)/etc/passwd" + echo "root::0:root" > "$(SYSROOT)/etc/group" .PHONY: sysroot-base-headers sysroot-base-headers: sysroot-fsh diff --git a/libc/Makefile b/libc/Makefile index 30cf5e9e..9e7c5b4e 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -235,7 +235,17 @@ fsmarshall/fsm_recv.o \ fsmarshall/fsm_send.o \ getopt/getopt_long.o \ getopt/getopt.o \ -grp/grent.o \ +grp/endgrent.o \ +grp/fgetgrent.o \ +grp/fgetgrent_r.o \ +grp/getgrent.o \ +grp/getgrent_r.o \ +grp/getgrgid.o \ +grp/getgrgid_r.o \ +grp/getgrnam.o \ +grp/getgrnam_r.o \ +grp/opengr.o \ +grp/setgrent.o \ init/init.o \ ioleast/preadall.o \ ioleast/preadleast.o \ diff --git a/libc/grp/endgrent.cpp b/libc/grp/endgrent.cpp new file mode 100644 index 00000000..efaa9517 --- /dev/null +++ b/libc/grp/endgrent.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/endgrent.cpp + Closes the group database. + +*******************************************************************************/ + +#include +#include + +extern "C" void endgrent(void) +{ + if ( !__grp_file ) + return; + fclose(__grp_file); + __grp_file = NULL; +} diff --git a/libc/grp/fgetgrent.cpp b/libc/grp/fgetgrent.cpp new file mode 100644 index 00000000..c1cdd331 --- /dev/null +++ b/libc/grp/fgetgrent.cpp @@ -0,0 +1,57 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/fgetgrent.cpp + Reads a group entry from a FILE in a thread-insecure manner. + +*******************************************************************************/ + +#include +#include +#include + +extern "C" struct group* fgetgrent(FILE* fp) +{ + static struct group result_object; + static char* buf = NULL; + static size_t buflen = 0; + if ( !buf ) + { + size_t new_buflen = 64; + if ( !(buf = (char*) malloc(new_buflen)) ) + return NULL; + buflen = new_buflen; + } + struct group* result; +retry: + int errnum = fgetgrent_r(fp, &result_object, buf, buflen, &result); + if ( errnum == ERANGE ) + { + size_t new_buflen = 2 * buflen; + char* new_buf = (char*) realloc(buf, new_buflen); + if ( !new_buf ) + return NULL; + buf = new_buf; + buflen = new_buflen; + goto retry; + } + if ( errnum < 0 ) + return errno = errnum, (struct group*) NULL; + return result; +} diff --git a/libc/grp/fgetgrent_r.cpp b/libc/grp/fgetgrent_r.cpp new file mode 100644 index 00000000..de6b565e --- /dev/null +++ b/libc/grp/fgetgrent_r.cpp @@ -0,0 +1,211 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/fgetgrent_r.cpp + Reads a group entry from a FILE. + +*******************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +static char* next_field(char** current) +{ + char* result = *current; + if ( result ) + { + char* next = result; + while ( *next && *next != ':' ) + next++; + if ( !*next ) + next = NULL; + else + *next++ = '\0'; + *current = next; + } + return result; +} + +static id_t next_field_id(char** current) +{ + char* id_str = next_field(current); + if ( !id_str ) + return -1; + char* id_endptr; + intmax_t id_imax = strtoimax(id_str, &id_endptr, 10); + if ( id_imax < 0 || *id_endptr ) + return -1; + id_t id = (id_t) id_imax; + if ( id != id_imax ) + return -1; + return id; +} + +static size_t count_num_members(const char* member_string) +{ + size_t result = 0; + while ( *member_string ) + { + result++; + while ( *member_string && *member_string != ',' ) + member_string++; + } + return result; +} + +static char* next_member(char** current) +{ + char* result = *current; + if ( result ) + { + char* next = result; + while ( *next && *next != ',' ) + next++; + if ( !*next ) + next = NULL; + else + *next++ = '\0'; + *current = next; + } + return result; +} + +extern "C" +int fgetgrent_r(FILE* restrict fp, + struct group* restrict result, + char* restrict buf, + size_t buf_len, + struct group** restrict result_pointer) +{ + if ( !result_pointer ) + return errno = EINVAL; + + if ( !fp || !result || !buf ) + return *result_pointer = NULL, errno = EINVAL; + + int original_errno = errno; + + flockfile(fp); + + off_t original_offset = ftello(fp); + if ( original_offset < 0 ) + { + funlockfile(fp); + return *result_pointer = NULL, errno; + } + + size_t buf_used = 0; + int ic; + while ( (ic = fgetc(fp)) != EOF ) + { + if ( ic == '\n' ) + break; + + if ( buf_used == buf_len ) + { + fseeko(fp, original_offset, SEEK_SET); + funlockfile(fp); + return *result_pointer = NULL, errno = ERANGE; + } + + buf[buf_used++] = (char) ic; + } + + if ( ferror(fp) ) + { + int original_error = errno; + fseeko(fp, original_offset, SEEK_SET); + funlockfile(fp); + return *result_pointer = NULL, original_error; + } + + if ( !buf_used && feof(fp) ) + { + funlockfile(fp); + return *result_pointer = NULL, errno = original_errno, NULL; + } + + if ( buf_used == buf_len ) + { + fseeko(fp, original_offset, SEEK_SET); + funlockfile(fp); + return *result_pointer = NULL, errno = ERANGE; + } + buf[buf_used++] = '\0'; + + if ( false ) + { + parse_failure: + fseeko(fp, original_offset, SEEK_SET); + funlockfile(fp); + return errno = EINVAL; + } + + if ( false ) + { + range_failure: + fseeko(fp, original_offset, SEEK_SET); + funlockfile(fp); + return *result_pointer = NULL, errno = ERANGE; + } + + char* parse_str = buf; + if ( !(result->gr_name = next_field(&parse_str)) ) + goto parse_failure; + if ( !(result->gr_passwd = next_field(&parse_str)) ) + goto parse_failure; + if ( !(result->gr_gid = next_field_id(&parse_str)) < 0 ) + goto parse_failure; + char* member_string; + if ( !(member_string = next_field(&parse_str)) ) + goto parse_failure; + if ( parse_str ) + goto parse_failure; + + while ( buf_used % alignof(char*) != 0 ) + { + if ( buf_used == buf_len ) + goto range_failure; + buf_used++; + } + + size_t num_members = count_num_members(member_string); + size_t member_list_bytes = (num_members + 1) * sizeof(char*); + size_t available_bytes = buf_len < buf_used; + if ( available_bytes < member_list_bytes ) + goto range_failure; + + result->gr_mem = (char**) (buf + buf_used); + buf_used += member_list_bytes; + + char* member_parse_str = member_string; + for ( size_t i = 0; i < num_members + 1; i++ ) + result->gr_mem[i] = next_member(&member_parse_str); + + funlockfile(fp); + + return *result_pointer = result, 0; +} diff --git a/libc/grp/getgrent.cpp b/libc/grp/getgrent.cpp new file mode 100644 index 00000000..0f96b124 --- /dev/null +++ b/libc/grp/getgrent.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/getgrent.cpp + Reads a group entry in a thread-insecure manner. + +*******************************************************************************/ + +#include +#include + +extern "C" { FILE* __grp_file = NULL; } + +extern "C" struct group* getgrent(void) +{ + if ( !__grp_file && !(__grp_file = opengr()) ) + return NULL; + return fgetgrent(__grp_file); +} diff --git a/libc/grp/getgrent_r.cpp b/libc/grp/getgrent_r.cpp new file mode 100644 index 00000000..8ed74c72 --- /dev/null +++ b/libc/grp/getgrent_r.cpp @@ -0,0 +1,39 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/getgrent_r.cpp + Reads a group entry (but not fully thread-securely). + +*******************************************************************************/ + +#include +#include + +extern "C" +int getgrent_r(struct group* restrict result, + char* restrict buf, + size_t buflen, + struct group** restrict result_pointer) +{ + if ( !result_pointer ) + return errno = EINVAL; + if ( !__grp_file && !(__grp_file = opengr()) ) + return errno; + return fgetgrent_r(__grp_file, result, buf, buflen, result_pointer); +} diff --git a/libc/grp/grent.cpp b/libc/grp/getgrgid.cpp similarity index 52% rename from libc/grp/grent.cpp rename to libc/grp/getgrgid.cpp index c1d13931..cdb88d47 100644 --- a/libc/grp/grent.cpp +++ b/libc/grp/getgrgid.cpp @@ -17,51 +17,42 @@ You should have received a copy of the GNU Lesser General Public License along with the Sortix C Library. If not, see . - grp/grent.cpp - Group database. + grp/getgrgid.cpp + Searchs the group database for a group with the given numeric group id in a + thread-insecure manner. *******************************************************************************/ -#include - +#include #include #include -#include - -const gid_t ROOT_GID = 0; -const char* const ROOT_NAME = "root"; - -static struct group global_group; - -static struct group* fill_group(struct group* gr) -{ - const char* env_groupname = getenv("GROUPNAME"); - strcpy(gr->gr_name, env_groupname ? env_groupname : ROOT_NAME); - const char* env_groupid = getenv("GROUPID"); - gr->gr_gid = env_groupid ? atoi(env_groupid) : ROOT_GID; - return gr; -} - -static gid_t lookup_groupname(const char* name) -{ - const char* env_groupname = getenv("GROUPNAME"); - const char* my_groupname = env_groupname ? env_groupname : ROOT_NAME; - if ( !strcmp(my_groupname, name) ) - { - const char* env_groupid = getenv("GROUPID"); - if ( env_groupid ) - return atoi(env_groupid); - } - return 1; -} extern "C" struct group* getgrgid(gid_t gid) { - (void) gid; - return fill_group(&global_group); -} - -extern "C" struct group* getgrnam(const char* name) -{ - return getgrgid(lookup_groupname(name)); + static struct group result_object; + static char* buf = NULL; + static size_t buflen = 0; + if ( !buf ) + { + size_t new_buflen = 64; + if ( !(buf = (char*) malloc(new_buflen)) ) + return NULL; + buflen = new_buflen; + } + struct group* result; +retry: + int errnum = getgrgid_r(gid, &result_object, buf, buflen, &result); + if ( errnum == ERANGE ) + { + size_t new_buflen = 2 * buflen; + char* new_buf = (char*) realloc(buf, new_buflen); + if ( !new_buf ) + return NULL; + buf = new_buf; + buflen = new_buflen; + goto retry; + } + if ( errnum < 0 ) + return errno = errnum, (struct group*) NULL; + return result; } diff --git a/libc/grp/getgrgid_r.cpp b/libc/grp/getgrgid_r.cpp new file mode 100644 index 00000000..f5188462 --- /dev/null +++ b/libc/grp/getgrgid_r.cpp @@ -0,0 +1,54 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/getgrgid_r.cpp + Searchs the group database for a group with the given numeric group id. + +*******************************************************************************/ + +#include +#include +#include + +extern "C" +int getgrgid_r(gid_t gid, + struct group* restrict ret, + char* restrict buf, + size_t buflen, + struct group** restrict ret_ptr) +{ + if ( !ret_ptr ) + return errno = EINVAL; + if ( !ret || !buf ) + return *ret_ptr = NULL, errno = EINVAL; + FILE* fgroup = opengr(); + if ( !fgroup ) + return *ret_ptr = NULL, errno; + int errnum; + while ( (errnum = fgetgrent_r(fgroup, ret, buf, buflen, ret_ptr)) == 0 && + *ret_ptr ) + { + if ( (*ret_ptr)->gr_gid != gid ) + continue; + fclose(fgroup); + return *ret_ptr = *ret_ptr, 0; + } + fclose(fgroup); + return *ret_ptr = NULL, errnum ? errnum : errno = ENOGROUP; +} diff --git a/libc/grp/getgrnam.cpp b/libc/grp/getgrnam.cpp new file mode 100644 index 00000000..b00b7c2e --- /dev/null +++ b/libc/grp/getgrnam.cpp @@ -0,0 +1,58 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/getgrnam.cpp + Searches the group database for a user with the given groupname in a + thread-insecure manner. + +*******************************************************************************/ + +#include +#include +#include + +extern "C" struct group* getgrnam(const char* groupname) +{ + static struct group result_object; + static char* buf = NULL; + static size_t buflen = 0; + if ( !buf ) + { + size_t new_buflen = 64; + if ( !(buf = (char*) malloc(new_buflen)) ) + return NULL; + buflen = new_buflen; + } + struct group* result; +retry: + int errnum = getgrnam_r(groupname, &result_object, buf, buflen, &result); + if ( errnum == ERANGE ) + { + size_t new_buflen = 2 * buflen; + char* new_buf = (char*) realloc(buf, new_buflen); + if ( !new_buf ) + return NULL; + buf = new_buf; + buflen = new_buflen; + goto retry; + } + if ( errnum < 0 ) + return errno = errnum, (struct group*) NULL; + return result; +} diff --git a/libc/grp/getgrnam_r.cpp b/libc/grp/getgrnam_r.cpp new file mode 100644 index 00000000..11ef93c1 --- /dev/null +++ b/libc/grp/getgrnam_r.cpp @@ -0,0 +1,55 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/getgrnam_r.cpp + Searchs the group database for a group with the given groupname. + +*******************************************************************************/ + +#include +#include +#include +#include + +extern "C" +int getgrnam_r(const char* restrict groupname, + struct group* restrict ret, + char* restrict buf, + size_t buflen, + struct group** restrict ret_ptr) +{ + if ( !ret_ptr ) + return errno = EINVAL; + if ( !groupname || !ret || !buf ) + return *ret_ptr = NULL, errno = EINVAL; + FILE* fgroup = opengr(); + if ( !fgroup ) + return *ret_ptr = NULL, errno; + int errnum; + while ( (errnum = fgetgrent_r(fgroup, ret, buf, buflen, ret_ptr)) == 0 && + *ret_ptr ) + { + if ( strcmp((*ret_ptr)->gr_name, groupname) != 0 ) + continue; + fclose(fgroup); + return *ret_ptr = *ret_ptr, 0; + } + fclose(fgroup); + return *ret_ptr = NULL, errnum ? errnum : errno = ENOGROUP; +} diff --git a/libc/grp/opengr.cpp b/libc/grp/opengr.cpp new file mode 100644 index 00000000..8b5c9dee --- /dev/null +++ b/libc/grp/opengr.cpp @@ -0,0 +1,31 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/opengr.cpp + Opens the group database and returns a FILE to it. + +*******************************************************************************/ + +#include +#include + +extern "C" FILE* opengr(void) +{ + return fopen("/etc/group", "r"); +} diff --git a/libc/grp/setgrent.cpp b/libc/grp/setgrent.cpp new file mode 100644 index 00000000..c8476f87 --- /dev/null +++ b/libc/grp/setgrent.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + grp/setgrent.cpp + Rewinds the group database. + +*******************************************************************************/ + +#include +#include + +extern "C" void setgrent(void) +{ + if ( __grp_file ) + fseeko(__grp_file, 0, SEEK_SET); + else + __grp_file = opengr(); +} diff --git a/libc/include/grp.h b/libc/include/grp.h index 7287d040..f5f4161b 100644 --- a/libc/include/grp.h +++ b/libc/include/grp.h @@ -31,21 +31,36 @@ __BEGIN_DECLS +@include(FILE.h) @include(gid_t.h) -@include(uid_t.h) @include(size_t.h) -#define _GROUP_BUFFER_SIZE 64 - struct group { - char gr_name[_GROUP_BUFFER_SIZE]; gid_t gr_gid; char** gr_mem; + char* gr_name; + char* gr_passwd; }; -struct group* getgrgid(gid_t gid); -struct group* getgrnam(const char* name); +#if __is_sortix_libc +extern FILE* __grp_file; +#endif + +void endgrent(void); +struct group* fgetgrent(FILE*); +int fgetgrent_r(FILE* __restrict, struct group* __restrict, char* __restrict, + size_t, struct group** __restrict); +struct group* getgrent(void); +int getgrent_r(struct group* __restrict, char* __restrict, size_t, + struct group** __restrict); +struct group* getgrgid(gid_t); +int getgrgid_r(gid_t, struct group* __restrict, char* __restrict, size_t, + struct group** __restrict); +struct group* getgrnam(const char*); +int getgrnam_r(const char*, struct group*, char*, size_t, struct group**); +FILE* opengr(void); +void setgrent(void); __END_DECLS