diff options
-rwxr-xr-x | configure | 52 | ||||
-rw-r--r-- | sysif.c | 110 | ||||
-rw-r--r-- | txr.1 | 78 |
3 files changed, 240 insertions, 0 deletions
@@ -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 @@ -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 @@ -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 |