diff options
Diffstat (limited to 'ext/etc/etc.c')
| -rw-r--r-- | ext/etc/etc.c | 194 |
1 files changed, 130 insertions, 64 deletions
diff --git a/ext/etc/etc.c b/ext/etc/etc.c index 6c7145b40b..8d50a96a62 100644 --- a/ext/etc/etc.c +++ b/ext/etc/etc.c @@ -54,9 +54,11 @@ static VALUE sGroup; # include <stdlib.h> # endif #endif -char *getlogin(); +RUBY_EXTERN char *getlogin(void); -#define RUBY_ETC_VERSION "1.4.2" +#define RUBY_ETC_VERSION "1.4.6" + +#define SYMBOL_LIT(str) ID2SYM(rb_intern_const(str "")) #ifdef HAVE_RB_DEPRECATE_CONSTANT void rb_deprecate_constant(VALUE mod, const char *name); @@ -66,6 +68,17 @@ void rb_deprecate_constant(VALUE mod, const char *name); #include "constdefs.h" +#ifndef HAVE_RB_IO_DESCRIPTOR +static int +io_descriptor_fallback(VALUE io) +{ + rb_io_t *fptr; + GetOpenFile(io, fptr); + return fptr->fd; +} +#define rb_io_descriptor io_descriptor_fallback +#endif + #ifdef HAVE_RUBY_ATOMIC_H # include "ruby/atomic.h" #else @@ -192,7 +205,7 @@ setup_passwd(struct passwd *pwd) #endif /* call-seq: - * getpwuid(uid) -> Passwd + * getpwuid(uid) -> Etc::Passwd * * Returns the <tt>/etc/passwd</tt> information for the user with the given * integer +uid+. @@ -204,7 +217,7 @@ setup_passwd(struct passwd *pwd) * * See the unix manpage for <code>getpwuid(3)</code> for more detail. * - * === Example: + * *Example:* * * Etc.getpwuid(0) * #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash"> @@ -232,7 +245,7 @@ etc_getpwuid(int argc, VALUE *argv, VALUE obj) } /* call-seq: - * getpwnam(name) -> Passwd + * getpwnam(name) -> Etc::Passwd * * Returns the <tt>/etc/passwd</tt> information for the user with specified * login +name+. @@ -241,7 +254,7 @@ etc_getpwuid(int argc, VALUE *argv, VALUE obj) * * See the unix manpage for <code>getpwnam(3)</code> for more detail. * - * === Example: + * *Example:* * * Etc.getpwnam('root') * #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash"> @@ -296,8 +309,8 @@ each_passwd(void) #endif /* call-seq: - * Etc.passwd { |struct| block } -> Passwd - * Etc.passwd -> Passwd + * passwd { |struct| block } + * passwd -> Etc::Passwd * * Provides a convenient Ruby iterator which executes a block for each entry * in the <tt>/etc/passwd</tt> file. @@ -306,7 +319,7 @@ each_passwd(void) * * See ::getpwent above for details. * - * Example: + * *Example:* * * require 'etc' * @@ -332,7 +345,7 @@ etc_passwd(VALUE obj) } /* call-seq: - * Etc::Passwd.each { |struct| block } -> Passwd + * Etc::Passwd.each { |struct| block } -> Etc::Passwd * Etc::Passwd.each -> Enumerator * * Iterates for each entry in the <tt>/etc/passwd</tt> file if a block is @@ -344,7 +357,7 @@ etc_passwd(VALUE obj) * * See Etc.getpwent above for details. * - * Example: + * *Example:* * * require 'etc' * @@ -366,7 +379,10 @@ etc_each_passwd(VALUE obj) return obj; } -/* Resets the process of reading the <tt>/etc/passwd</tt> file, so that the +/* call-seq: + * setpwent + * + * Resets the process of reading the <tt>/etc/passwd</tt> file, so that the * next call to ::getpwent will return the first entry again. */ static VALUE @@ -378,7 +394,10 @@ etc_setpwent(VALUE obj) return Qnil; } -/* Ends the process of scanning through the <tt>/etc/passwd</tt> file begun +/* call-seq: + * endpwent + * + * Ends the process of scanning through the <tt>/etc/passwd</tt> file begun * with ::getpwent, and closes the file. */ static VALUE @@ -390,7 +409,10 @@ etc_endpwent(VALUE obj) return Qnil; } -/* Returns an entry from the <tt>/etc/passwd</tt> file. +/* call-seq: + * getpwent -> Etc::Passwd + * + * Returns an entry from the <tt>/etc/passwd</tt> file. * * The first time it is called it opens the file and returns the first entry; * each successive call returns the next entry, or +nil+ if the end of the file @@ -438,7 +460,7 @@ setup_group(struct group *grp) #endif /* call-seq: - * getgrgid(group_id) -> Group + * getgrgid(group_id) -> Etc::Group * * Returns information about the group with specified integer +group_id+, * as found in <tt>/etc/group</tt>. @@ -447,7 +469,7 @@ setup_group(struct group *grp) * * See the unix manpage for <code>getgrgid(3)</code> for more detail. * - * === Example: + * *Example:* * * Etc.getgrgid(100) * #=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]> @@ -476,7 +498,7 @@ etc_getgrgid(int argc, VALUE *argv, VALUE obj) } /* call-seq: - * getgrnam(name) -> Group + * getgrnam(name) -> Etc::Group * * Returns information about the group with specified +name+, as found in * <tt>/etc/group</tt>. @@ -485,7 +507,7 @@ etc_getgrgid(int argc, VALUE *argv, VALUE obj) * * See the unix manpage for <code>getgrnam(3)</code> for more detail. * - * === Example: + * *Example:* * * Etc.getgrnam('users') * #=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]> @@ -518,7 +540,6 @@ group_ensure(VALUE _) return Qnil; } - static VALUE group_iterate(VALUE _) { @@ -541,14 +562,18 @@ each_group(void) } #endif -/* Provides a convenient Ruby iterator which executes a block for each entry +/* call-seq: + * group { |struct| block } + * group -> Etc::Group + * + * Provides a convenient Ruby iterator which executes a block for each entry * in the <tt>/etc/group</tt> file. * * The code block is passed an Group struct. * * See ::getgrent above for details. * - * Example: + * *Example:* * * require 'etc' * @@ -575,7 +600,7 @@ etc_group(VALUE obj) #ifdef HAVE_GETGRENT /* call-seq: - * Etc::Group.each { |group| block } -> obj + * Etc::Group.each { |group| block } -> Etc::Group * Etc::Group.each -> Enumerator * * Iterates for each entry in the <tt>/etc/group</tt> file if a block is @@ -585,7 +610,7 @@ etc_group(VALUE obj) * * The code block is passed a Group struct. * - * Example: + * *Example:* * * require 'etc' * @@ -606,7 +631,10 @@ etc_each_group(VALUE obj) } #endif -/* Resets the process of reading the <tt>/etc/group</tt> file, so that the +/* call-seq: + * setgrent + * + * Resets the process of reading the <tt>/etc/group</tt> file, so that the * next call to ::getgrent will return the first entry again. */ static VALUE @@ -618,7 +646,10 @@ etc_setgrent(VALUE obj) return Qnil; } -/* Ends the process of scanning through the <tt>/etc/group</tt> file begun +/* call-seq: + * endgrent + * + * Ends the process of scanning through the <tt>/etc/group</tt> file begun * by ::getgrent, and closes the file. */ static VALUE @@ -630,7 +661,10 @@ etc_endgrent(VALUE obj) return Qnil; } -/* Returns an entry from the <tt>/etc/group</tt> file. +/* call-seq: + * getgrent -> Etc::Group + * + * Returns an entry from the <tt>/etc/group</tt> file. * * The first time it is called it opens the file and returns the first entry; * each successive call returns the next entry, or +nil+ if the end of the file @@ -659,9 +693,21 @@ etc_getgrent(VALUE obj) VALUE rb_w32_special_folder(int type); UINT rb_w32_system_tmpdir(WCHAR *path, UINT len); VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc); +#elif defined(LOAD_RELATIVE) +static inline VALUE +rbconfig(void) +{ + VALUE config; + rb_require("rbconfig"); + config = rb_const_get(rb_path2class("RbConfig"), rb_intern_const("CONFIG")); + Check_Type(config, T_HASH); + return config; +} #endif -/* +/* call-seq: + * sysconfdir -> String + * * Returns system configuration directory. * * This is typically <code>"/etc"</code>, but is modified by the prefix used @@ -676,12 +722,16 @@ etc_sysconfdir(VALUE obj) { #ifdef _WIN32 return rb_w32_special_folder(CSIDL_COMMON_APPDATA); +#elif defined(LOAD_RELATIVE) + return rb_hash_aref(rbconfig(), rb_str_new_lit("sysconfdir")); #else return rb_filesystem_str_new_cstr(SYSCONFDIR); #endif } -/* +/* call-seq: + * systmpdir -> String + * * Returns system temporary directory; typically "/tmp". */ static VALUE @@ -725,13 +775,15 @@ etc_systmpdir(VALUE _) } #ifdef HAVE_UNAME -/* +/* call-seq: + * uname -> hash + * * Returns the system information obtained by uname system call. * * The return value is a hash which has 5 keys at least: * :sysname, :nodename, :release, :version, :machine * - * Example: + * *Example:* * * require 'etc' * require 'pp' @@ -773,18 +825,14 @@ etc_uname(VALUE obj) sysname = "Windows"; break; } - rb_hash_aset(result, ID2SYM(rb_intern("sysname")), rb_str_new_cstr(sysname)); + rb_hash_aset(result, SYMBOL_LIT("sysname"), rb_str_new_cstr(sysname)); release = rb_sprintf("%lu.%lu.%lu", v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber); - rb_hash_aset(result, ID2SYM(rb_intern("release")), release); + rb_hash_aset(result, SYMBOL_LIT("release"), release); version = rb_sprintf("%s Version %"PRIsVALUE": %"PRIsVALUE, sysname, release, rb_w32_conv_from_wchar(v.szCSDVersion, rb_utf8_encoding())); - rb_hash_aset(result, ID2SYM(rb_intern("version")), version); + rb_hash_aset(result, SYMBOL_LIT("version"), version); -# if defined _MSC_VER && _MSC_VER < 1300 -# define GET_COMPUTER_NAME(ptr, plen) GetComputerNameW(ptr, plen) -# else # define GET_COMPUTER_NAME(ptr, plen) GetComputerNameExW(ComputerNameDnsFullyQualified, ptr, plen) -# endif GET_COMPUTER_NAME(NULL, &len); buf = ALLOCV_N(WCHAR, vbuf, len); if (GET_COMPUTER_NAME(buf, &len)) { @@ -792,7 +840,7 @@ etc_uname(VALUE obj) } ALLOCV_END(vbuf); if (NIL_P(nodename)) nodename = rb_str_new(0, 0); - rb_hash_aset(result, ID2SYM(rb_intern("nodename")), nodename); + rb_hash_aset(result, SYMBOL_LIT("nodename"), nodename); # ifndef PROCESSOR_ARCHITECTURE_AMD64 # define PROCESSOR_ARCHITECTURE_AMD64 9 @@ -816,7 +864,7 @@ etc_uname(VALUE obj) break; } - rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(mach)); + rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(mach)); #else struct utsname u; int ret; @@ -827,11 +875,11 @@ etc_uname(VALUE obj) rb_sys_fail("uname"); result = rb_hash_new(); - rb_hash_aset(result, ID2SYM(rb_intern("sysname")), rb_str_new_cstr(u.sysname)); - rb_hash_aset(result, ID2SYM(rb_intern("nodename")), rb_str_new_cstr(u.nodename)); - rb_hash_aset(result, ID2SYM(rb_intern("release")), rb_str_new_cstr(u.release)); - rb_hash_aset(result, ID2SYM(rb_intern("version")), rb_str_new_cstr(u.version)); - rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(u.machine)); + rb_hash_aset(result, SYMBOL_LIT("sysname"), rb_str_new_cstr(u.sysname)); + rb_hash_aset(result, SYMBOL_LIT("nodename"), rb_str_new_cstr(u.nodename)); + rb_hash_aset(result, SYMBOL_LIT("release"), rb_str_new_cstr(u.release)); + rb_hash_aset(result, SYMBOL_LIT("version"), rb_str_new_cstr(u.version)); + rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(u.machine)); #endif return result; @@ -841,7 +889,9 @@ etc_uname(VALUE obj) #endif #ifdef HAVE_SYSCONF -/* +/* call-seq: + * sysconf(name) -> Integer + * * Returns system configuration variable using sysconf(). * * _name_ should be a constant under <code>Etc</code> which begins with <code>SC_</code>. @@ -875,7 +925,9 @@ etc_sysconf(VALUE obj, VALUE arg) #endif #ifdef HAVE_CONFSTR -/* +/* call-seq: + * confstr(name) -> String + * * Returns system configuration variable using confstr(). * * _name_ should be a constant under <code>Etc</code> which begins with <code>CS_</code>. @@ -922,7 +974,9 @@ etc_confstr(VALUE obj, VALUE arg) #endif #ifdef HAVE_FPATHCONF -/* +/* call-seq: + * pathconf(name) -> Integer + * * Returns pathname configuration variable using fpathconf(). * * _name_ should be a constant under <code>Etc</code> which begins with <code>PC_</code>. @@ -941,14 +995,11 @@ io_pathconf(VALUE io, VALUE arg) { int name; long ret; - rb_io_t *fptr; name = NUM2INT(arg); - GetOpenFile(io, fptr); - errno = 0; - ret = fpathconf(fptr->fd, name); + ret = fpathconf(rb_io_descriptor(io), name); if (ret == -1) { if (errno == 0) /* no limit */ return Qnil; @@ -1017,7 +1068,9 @@ etc_nprocessors_affin(void) } #endif -/* +/* call-seq: + * nprocessors -> Integer + * * Returns the number of online processors. * * The result is intended as the number of processes to @@ -1027,7 +1080,7 @@ etc_nprocessors_affin(void) * - sched_getaffinity(): Linux * - sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX * - * Example: + * *Example:* * * require 'etc' * p Etc.nprocessors #=> 4 @@ -1036,7 +1089,7 @@ etc_nprocessors_affin(void) * process is bound to specific cpus. This is intended for getting better * parallel processing. * - * Example: (Linux) + * *Example:* (Linux) * * linux$ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2 * @@ -1086,7 +1139,7 @@ etc_nprocessors(VALUE obj) * The Etc module provides a more reliable way to access information about * the logged in user than environment variables such as +$USER+. * - * == Example: + * *Example:* * * require 'etc' * @@ -1106,13 +1159,26 @@ Init_etc(void) { VALUE mEtc; -#ifdef HAVE_RB_EXT_RACTOR_SAFE - RB_EXT_RACTOR_SAFE(true); -#endif mEtc = rb_define_module("Etc"); + /* The version */ rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION)); init_constants(mEtc); + /* Ractor-safe methods */ +#ifdef HAVE_RB_EXT_RACTOR_SAFE + RB_EXT_RACTOR_SAFE(true); +#endif + rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0); + rb_define_module_function(mEtc, "uname", etc_uname, 0); + rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1); + rb_define_module_function(mEtc, "confstr", etc_confstr, 1); + rb_define_method(rb_cIO, "pathconf", io_pathconf, 1); + rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0); + + /* Non-Ractor-safe methods, see https://bugs.ruby-lang.org/issues/21115 */ +#ifdef HAVE_RB_EXT_RACTOR_SAFE + RB_EXT_RACTOR_SAFE(false); +#endif rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0); rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1); @@ -1128,13 +1194,9 @@ Init_etc(void) rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0); rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0); rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0); + + /* Uses RbConfig::CONFIG so does not work in a Ractor */ rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0); - rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0); - rb_define_module_function(mEtc, "uname", etc_uname, 0); - rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1); - rb_define_module_function(mEtc, "confstr", etc_confstr, 1); - rb_define_method(rb_cIO, "pathconf", io_pathconf, 1); - rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0); sPasswd = rb_struct_define_under(mEtc, "Passwd", "name", @@ -1245,4 +1307,8 @@ Init_etc(void) rb_extend_object(sGroup, rb_mEnumerable); rb_define_singleton_method(sGroup, "each", etc_each_group, 0); #endif + +#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT) + (void)safe_setup_str; +#endif } |
