summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure52
-rw-r--r--sysif.c110
-rw-r--r--txr.178
3 files changed, 240 insertions, 0 deletions
diff --git a/configure b/configure
index 9a71902b..aa9c8f05 100755
--- a/configure
+++ b/configure
@@ -122,6 +122,7 @@ have_posix_sigs=
need_darwin_c_source=
have_git=
have_pwuid=
+have_grgid=
have_alloca=
have_termios=
have_winsize=
@@ -2108,6 +2109,57 @@ int main(void)
fi
fi
+printf "Checking for old school getgrent, getgrgid and getgrnam ... "
+
+cat > conftest.c <<!
+#include <sys/types.h>
+#include <grp.h>
+
+int main(void)
+{
+ struct group *g = getgrent();
+ struct group *h = getgrnam("root");
+ struct group *i = getgrgid(0);
+ setgrent();
+ endgrent();
+ return 0;
+}
+!
+
+if conftest ; then
+ printf "yes\n"
+ printf "#define HAVE_GRGID 1\n" >> $config_h
+ have_grgid=y
+else
+ printf "no\n"
+fi
+
+if [ "$have_grgid" ]; then
+ printf "Checking for getgrgid_r and getgrnam_r ... "
+
+ cat > conftest.c <<!
+#include <sys/types.h>
+#include <grp.h>
+
+int main(void)
+{
+ struct group gr;
+ struct group *g;
+ char buf[1024];
+ int r1 = getgrgid_r(0, &gr, buf, sizeof buf, &g);
+ int r2 = getgrnam_r("root", &gr, buf, sizeof buf, &g);
+ return 0;
+}
+!
+
+ if conftest ; then
+ printf "yes\n"
+ printf "#define HAVE_GRGID_R 1\n" >> $config_h
+ else
+ printf "no\n"
+ fi
+fi
+
printf "Checking for alloca ... "
for try_header in alloca.h malloc.h ; do
diff --git a/sysif.c b/sysif.c
index a077ea4c..68971468 100644
--- a/sysif.c
+++ b/sysif.c
@@ -59,6 +59,9 @@
#if HAVE_PWUID
#include <pwd.h>
#endif
+#if HAVE_GRGID
+#include <grp.h>
+#endif
#include ALLOCA_H
#include "lib.h"
#include "stream.h"
@@ -85,6 +88,10 @@ val atime_s, mtime_s, ctime_s;
val passwd_s, name_s, gecos_s, dir_s, shell_s;
#endif
+#if HAVE_GRGID
+val group_s, mem_s;
+#endif
+
static val errno_wrap(val newval)
{
val oldval = num(errno);
@@ -944,6 +951,93 @@ static val getpwnam_wrap(val wname)
#endif
+#if HAVE_GRGID
+
+static val setgrent_wrap(void)
+{
+ setgrent();
+ return nil;
+}
+
+static val endgrent_wrap(void)
+{
+ endgrent();
+ return nil;
+}
+
+static void fill_group(val to, struct group *from)
+{
+ list_collect_decl (out, ptail);
+ int i;
+
+ slotset(to, name_s, string_utf8(from->gr_name));
+ slotset(to, passwd_s, string_utf8(from->gr_passwd));
+ slotset(to, gid_s, num(from->gr_gid));
+
+ for (i = 0; from->gr_mem[i] != 0; i++)
+ ptail = list_collect(ptail, string_utf8(from->gr_mem[i]));
+
+ slotset(to, mem_s, out);
+}
+
+static val make_grstruct(struct group *g)
+{
+ args_decl(args, ARGS_MIN);
+ val out = make_struct(group_s, nil, args);
+ fill_group(out, g);
+ return out;
+}
+
+
+static val getgrent_wrap(void)
+{
+ struct group *g = getgrent();
+ return (g != 0) ? make_grstruct(g) : nil;
+}
+
+
+#endif
+
+#if HAVE_GRGID_R
+
+static val getgrgid_wrap(val uid)
+{
+ char buf[1024];
+ struct group gr, *g;
+ int res = getgrgid_r(c_num(uid), &gr, buf, sizeof buf, &g);
+
+ return (res == 0 && g != 0) ? make_grstruct(&gr) : nil;
+}
+
+static val getgrnam_wrap(val wname)
+{
+ char buf[1024];
+ struct group gr, *g;
+ char *name = utf8_dup_to(c_str(wname));
+ int res = getgrnam_r(name, &gr, buf, sizeof buf, &g);
+
+ free(name);
+ return (res == 0 && g != 0) ? make_grstruct(&gr) : nil;
+}
+
+#elif HAVE_GRGID
+
+static val getgrgid_wrap(val uid)
+{
+ struct group *g = getgrgid(c_num(uid));
+ return (g != 0) ? make_grstruct(g) : nil;
+}
+
+static val getgrnam_wrap(val wname)
+{
+ char *name = utf8_dup_to(c_str(wname));
+ struct group *g = getgrnam(name);
+ free(name);
+ return (g != 0) ? make_grstruct(g) : nil;
+}
+
+#endif
+
void sysif_init(void)
{
stat_s = intern(lit("stat"), user_package);
@@ -980,6 +1074,10 @@ void sysif_init(void)
dir_s = intern(lit("dir"), user_package);
shell_s = intern(lit("shell"), user_package);
#endif
+#if HAVE_GRGID
+ group_s = intern(lit("group"), user_package);
+ mem_s = intern(lit("mem"), user_package);
+#endif
make_struct_type(stat_s, nil,
list(dev_s, ino_s, mode_s, nlink_s, uid_s, gid_s,
@@ -990,6 +1088,10 @@ void sysif_init(void)
list(name_s, passwd_s, uid_s, gid_s,
gecos_s, dir_s, shell_s, nao), nil, nil);
#endif
+#if HAVE_GRGID
+ make_struct_type(group_s, nil,
+ list(name_s, passwd_s, gid_s, mem_s, nao), nil, nil);
+#endif
reg_fun(intern(lit("errno"), user_package), func_n1o(errno_wrap, 0));
reg_fun(intern(lit("exit"), user_package), func_n1(exit_wrap));
@@ -1196,6 +1298,14 @@ void sysif_init(void)
reg_fun(intern(lit("getpwnam"), user_package), func_n1(getpwnam_wrap));
#endif
+#if HAVE_GRGID
+ reg_fun(intern(lit("setgrent"), user_package), func_n0(setgrent_wrap));
+ reg_fun(intern(lit("endgrent"), user_package), func_n0(endgrent_wrap));
+ reg_fun(intern(lit("getgrent"), user_package), func_n0(getgrent_wrap));
+ reg_fun(intern(lit("getgrgid"), user_package), func_n1(getgrgid_wrap));
+ reg_fun(intern(lit("getgrnam"), user_package), func_n1(getgrnam_wrap));
+#endif
+
#if HAVE_POLL
reg_fun(intern(lit("poll"), user_package), func_n2o(poll_wrap, 1));
#endif
diff --git a/txr.1 b/txr.1
index 8fd09ca0..8a3d1402 100644
--- a/txr.1
+++ b/txr.1
@@ -31308,6 +31308,84 @@ If the search fails,
.code nil
is returned.
+.SS* Unix Group Database
+
+.coNP Structure * group
+.synb
+.mets (defstruct group nil
+.mets \ \ name passwd gid mem)
+.syne
+.desc
+The
+.code group
+structure corresponds to the C type
+.codn struct group .
+Objects of this struct are produced by the password database
+query functions
+.codn getgrent ,
+.codn getgrgid ,
+and
+.codn getgrnam .
+
+.coNP Functions @, getgrent @ setgrent and @ endgrent
+.synb
+.mets (getgrent)
+.mets (setgrent)
+.mets (endgrent)
+.syne
+.desc
+The first time
+.code getgrent
+function is called, it returns the first group database entry.
+On subsequent calls it returns successive entries.
+Entries are returned as instances of the
+.code passwd
+structure. If the function cannot retrieve an entry for any reason,
+it returns
+.codn nil .
+
+The
+.code setgrent
+function rewinds the database scan.
+
+The
+.code endgrent
+function releases the resources associated with the scan.
+
+.coNP Function @ getgrgid
+.synb
+.mets (getgrgid << gid )
+.syne
+.desc
+The
+.code getgrgid
+searches the group database for an entry whose group ID field
+is equal to the numeric
+.metn gid .
+If the search is successful, then a
+.code group
+structure representing the database entry is returned.
+If the search fails,
+.code nil
+is returned.
+
+.coNP Function @ getgrnam
+.synb
+.mets (getgrnam << name )
+.syne
+.desc
+The
+.code getgrnam
+searches the group database for an entry whose group name
+is equal to
+.metn name .
+If the search is successful, then a
+.code group
+structure representing the database entry is returned.
+If the search fails,
+.code nil
+is returned.
+
.SS* Unix Signal Handling
On platforms where certain advanced features of POSIX signal handling are