diff options
-rwxr-xr-x | configure | 53 | ||||
-rw-r--r-- | sysif.c | 114 | ||||
-rw-r--r-- | txr.1 | 79 |
3 files changed, 246 insertions, 0 deletions
@@ -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 @@ -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 @@ -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 |