summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure53
-rw-r--r--sysif.c114
-rw-r--r--txr.179
3 files changed, 246 insertions, 0 deletions
diff --git a/configure b/configure
index d2ade8cc..c6452488 100755
--- a/configure
+++ b/configure
@@ -121,6 +121,7 @@ have_windres=
have_posix_sigs=
need_darwin_c_source=
have_git=
+have_pwuid=
have_alloca=
conf_dir=config
config_h=$conf_dir/config.h
@@ -2049,6 +2050,58 @@ else
printf "no\n"
fi
+printf "Checking for old school getpwent, getpwuid and getpwnam ... "
+
+cat > conftest.c <<!
+#include <sys/types.h>
+#include <pwd.h>
+
+int main(void)
+{
+ struct passwd *p = getpwent();
+ struct passwd *q = getpwnam("root");
+ struct passwd *r = getpwuid(0);
+ setpwent();
+ endpwent();
+ return 0;
+}
+!
+
+if conftest ; then
+ printf "yes\n"
+ printf "#define HAVE_PWUID 1\n" >> $config_h
+ have_pwuid=y
+else
+ printf "no\n"
+fi
+
+if [ "$have_pwuid" ]; then
+ printf "Checking for getpwent_r, getpwuid_r, and getpwnam_r ... "
+
+ cat > conftest.c <<!
+#include <sys/types.h>
+#include <pwd.h>
+
+int main(void)
+{
+ struct passwd pw;
+ struct passwd *p;
+ char buf[1024];
+ int r0 = getpwent_r(&pw, buf, sizeof buf, &p);
+ int r1 = getpwuid_r(0, &pw, buf, sizeof buf, &p);
+ int r2 = getpwnam_r("root", &pw, buf, sizeof buf, &p);
+ return 0;
+}
+!
+
+ if conftest ; then
+ printf "yes\n"
+ printf "#define HAVE_PWUID_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 4abf5ac5..5197d337 100644
--- a/sysif.c
+++ b/sysif.c
@@ -81,6 +81,10 @@ val dev_s, ino_s, mode_s, nlink_s, uid_s;
val gid_s, rdev_s, size_s, blksize_s, blocks_s;
val atime_s, mtime_s, ctime_s;
+#if HAVE_PWUID
+val passwd_s, name_s, gecos_s, dir_s, shell_s;
+#endif
+
static val errno_wrap(val newval)
{
val oldval = num(errno);
@@ -850,6 +854,96 @@ static val setegid_wrap(val nval)
#endif
+#if HAVE_PWUID
+
+static val setpwent_wrap(void)
+{
+ setpwent();
+ return nil;
+}
+
+static val endpwent_wrap(void)
+{
+ endpwent();
+ return nil;
+}
+
+static void fill_passwd(val to, struct passwd *from)
+{
+ slotset(to, name_s, string_utf8(from->pw_name));
+ slotset(to, passwd_s, string_utf8(from->pw_passwd));
+ slotset(to, uid_s, num(from->pw_uid));
+ slotset(to, gid_s, num(from->pw_gid));
+ slotset(to, gecos_s, string_utf8(from->pw_gecos));
+ slotset(to, dir_s, string_utf8(from->pw_dir));
+ slotset(to, shell_s, string_utf8(from->pw_shell));
+}
+
+static val make_pwstruct(struct passwd *p)
+{
+ args_decl(args, ARGS_MIN);
+ val out = make_struct(passwd_s, nil, args);
+ fill_passwd(out, p);
+ return out;
+}
+
+#endif
+
+#if HAVE_PWUID_R
+
+static val getpwent_wrap(void)
+{
+ char buf[1024];
+ struct passwd pw, *p;
+ int res = getpwent_r(&pw, buf, sizeof buf, &p);
+
+ return (res == 0 && p != 0) ? make_pwstruct(&pw) : nil;
+}
+
+static val getpwuid_wrap(val uid)
+{
+ char buf[1024];
+ struct passwd pw, *p;
+ int res = getpwuid_r(c_num(uid), &pw, buf, sizeof buf, &p);
+
+ return (res == 0 && p != 0) ? make_pwstruct(&pw) : nil;
+}
+
+static val getpwnam_wrap(val wname)
+{
+ char buf[1024];
+ struct passwd pw, *p;
+ char *name = utf8_dup_to(c_str(wname));
+ int res = getpwnam_r(name, &pw, buf, sizeof buf, &p);
+
+ free(name);
+ return (res == 0 && p != 0) ? make_pwstruct(&pw) : nil;
+}
+
+#elif HAVE_PWUID
+
+static val getpwent_wrap(void)
+{
+ struct passwd *p = getpwent();
+ return (p != 0) ? make_pwstruct(p) : nil;
+}
+
+static val getpwuid_wrap(val uid)
+{
+ struct passwd *p = getpwuid(c_num(uid));
+ return (p != 0) ? make_pwstruct(p) : nil;
+}
+
+static val getpwnam_wrap(val wname)
+{
+ char *name = utf8_dup_to(c_str(wname));
+ struct passwd *p = getpwnam(name);
+ free(name);
+ return (p != 0) ? make_pwstruct(p) : nil;
+}
+
+#endif
+
void sysif_init(void)
{
stat_s = intern(lit("stat"), user_package);
@@ -879,11 +973,23 @@ void sysif_init(void)
atime_s = intern(lit("atime"), user_package);
mtime_s = intern(lit("mtime"), user_package);
ctime_s = intern(lit("ctime"), user_package);
+#if HAVE_PWUID
+ passwd_s = intern(lit("passwd"), user_package);
+ name_s = intern(lit("name"), user_package);
+ gecos_s = intern(lit("gecos"), user_package);
+ dir_s = intern(lit("dir"), user_package);
+ shell_s = intern(lit("shell"), user_package);
+#endif
make_struct_type(stat_s, nil,
list(dev_s, ino_s, mode_s, nlink_s, uid_s, gid_s,
rdev_s, size_s, blksize_s, blocks_s, atime_s,
mtime_s, ctime_s, nao), nil, nil);
+#if HAVE_PWUID
+ make_struct_type(passwd_s, nil,
+ list(name_s, passwd_s, uid_s, gid_s,
+ gecos_s, dir_s, shell_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));
@@ -1082,6 +1188,14 @@ void sysif_init(void)
reg_fun(intern(lit("setegid"), user_package), func_n1(setegid_wrap));
#endif
+#if HAVE_PWUID
+ reg_fun(intern(lit("setpwent"), user_package), func_n0(setpwent_wrap));
+ reg_fun(intern(lit("endpwent"), user_package), func_n0(endpwent_wrap));
+ reg_fun(intern(lit("getpwent"), user_package), func_n0(getpwent_wrap));
+ reg_fun(intern(lit("getpwuid"), user_package), func_n1(getpwuid_wrap));
+ reg_fun(intern(lit("getpwnam"), user_package), func_n1(getpwnam_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 f4e6171a..6e90c97d 100644
--- a/txr.1
+++ b/txr.1
@@ -31034,6 +31034,85 @@ On success, they return
On failure, they throw an exception of type
.codn system-error .
+.SS* Unix Password Database
+
+.coNP Structure * passwd
+.synb
+.mets (defstruct passwd nil
+.mets \ \ name passwd uid gid
+.mets \ \ gecos dir shell)
+.syne
+.desc
+The
+.code passwd
+structure corresponds to the C type
+.codn struct passwd .
+Objects of this struct are produced by the password database
+query functions
+.codn getpwent ,
+.codn getpwuid ,
+and
+.codn getpwnam .
+
+.coNP Functions @, getpwent @ setpwent and @ endpwent
+.synb
+.mets (getpwent)
+.mets (setpwent)
+.mets (endpwent)
+.syne
+.desc
+The first time
+.code getpwent
+function is called, it returns the first password 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 setpwent
+function rewinds the database scan.
+
+The
+.code endpwent
+function releases the resources associated with the scan.
+
+.coNP Function @ getpwuid
+.synb
+.mets (getpwuid << uid )
+.syne
+.desc
+The
+.code getpwuid
+searches the password database for an entry whose user ID field
+is equal to the numeric
+.metn uid .
+If the search is successful, then a
+.code passwd
+structure representing the database entry is returned.
+If the search fails,
+.code nil
+is returned.
+
+.coNP Function @ getpwnam
+.synb
+.mets (getpwnam << name )
+.syne
+.desc
+The
+.code getpwuid
+searches the password database for an entry whose user name
+is equal to
+.metn name .
+If the search is successful, then a
+.code passwd
+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