summaryrefslogtreecommitdiff
path: root/ruby_2_2/ext/etc/etc.c
diff options
context:
space:
mode:
Diffstat (limited to 'ruby_2_2/ext/etc/etc.c')
-rw-r--r--ruby_2_2/ext/etc/etc.c1199
1 files changed, 0 insertions, 1199 deletions
diff --git a/ruby_2_2/ext/etc/etc.c b/ruby_2_2/ext/etc/etc.c
deleted file mode 100644
index 4173d33bdc..0000000000
--- a/ruby_2_2/ext/etc/etc.c
+++ /dev/null
@@ -1,1199 +0,0 @@
-/************************************************
-
- etc.c -
-
- $Author$
- created at: Tue Mar 22 18:39:19 JST 1994
-
-************************************************/
-
-#include "ruby.h"
-#include "ruby/encoding.h"
-#include "ruby/io.h"
-
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_GETPWENT
-#include <pwd.h>
-#endif
-
-#ifdef HAVE_GETGRENT
-#include <grp.h>
-#endif
-
-#include <errno.h>
-
-#ifdef HAVE_SYS_UTSNAME_H
-#include <sys/utsname.h>
-#endif
-
-#ifdef HAVE_SCHED_GETAFFINITY
-#include <sched.h>
-#endif
-
-static VALUE sPasswd;
-#ifdef HAVE_GETGRENT
-static VALUE sGroup;
-#endif
-
-#ifdef _WIN32
-#include <shlobj.h>
-#ifndef CSIDL_COMMON_APPDATA
-#define CSIDL_COMMON_APPDATA 35
-#endif
-#define HAVE_UNAME 1
-#endif
-
-#ifndef _WIN32
-char *getenv();
-#endif
-char *getlogin();
-
-#include "constdefs.h"
-
-/* call-seq:
- * getlogin -> String
- *
- * Returns the short user name of the currently logged in user.
- * Unfortunately, it is often rather easy to fool ::getlogin.
- *
- * Avoid ::getlogin for security-related purposes.
- *
- * If ::getlogin fails, try ::getpwuid.
- *
- * See the unix manpage for <code>getpwuid(3)</code> for more detail.
- *
- * e.g.
- * Etc.getlogin -> 'guest'
- */
-static VALUE
-etc_getlogin(VALUE obj)
-{
- char *login;
-
-#ifdef HAVE_GETLOGIN
- login = getlogin();
- if (!login) login = getenv("USER");
-#else
- login = getenv("USER");
-#endif
-
- if (login) {
-#ifdef _WIN32
- rb_encoding *extenc = rb_utf8_encoding();
-#else
- rb_encoding *extenc = rb_locale_encoding();
-#endif
- return rb_external_str_new_with_enc(login, strlen(login), extenc);
- }
-
- return Qnil;
-}
-
-#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
-static VALUE
-safe_setup_str(const char *str)
-{
- if (str == 0) str = "";
- return rb_tainted_str_new2(str);
-}
-
-static VALUE
-safe_setup_locale_str(const char *str)
-{
- if (str == 0) str = "";
- return rb_locale_str_new_cstr(str);
-}
-
-static VALUE
-safe_setup_filesystem_str(const char *str)
-{
- if (str == 0) str = "";
- return rb_filesystem_str_new_cstr(str);
-}
-#endif
-
-#ifdef HAVE_GETPWENT
-static VALUE
-setup_passwd(struct passwd *pwd)
-{
- if (pwd == 0) rb_sys_fail("/etc/passwd");
- return rb_struct_new(sPasswd,
- safe_setup_locale_str(pwd->pw_name),
-#ifdef HAVE_STRUCT_PASSWD_PW_PASSWD
- safe_setup_str(pwd->pw_passwd),
-#endif
- UIDT2NUM(pwd->pw_uid),
- GIDT2NUM(pwd->pw_gid),
-#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
- safe_setup_locale_str(pwd->pw_gecos),
-#endif
- safe_setup_filesystem_str(pwd->pw_dir),
- safe_setup_filesystem_str(pwd->pw_shell),
-#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
- INT2NUM(pwd->pw_change),
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_QUOTA
- INT2NUM(pwd->pw_quota),
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_AGE
- PW_AGE2VAL(pwd->pw_age),
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
- safe_setup_locale_str(pwd->pw_class),
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_COMMENT
- safe_setup_locale_str(pwd->pw_comment),
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
- INT2NUM(pwd->pw_expire),
-#endif
- 0 /*dummy*/
- );
-}
-#endif
-
-/* call-seq:
- * getpwuid(uid) -> Passwd
- *
- * Returns the /etc/passwd information for the user with the given integer +uid+.
- *
- * The information is returned as a Passwd struct.
- *
- * If +uid+ is omitted, the value from <code>Passwd[:uid]</code> is returned
- * instead.
- *
- * See the unix manpage for <code>getpwuid(3)</code> for more detail.
- *
- * === Example:
- *
- * Etc.getpwuid(0)
- * #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
- */
-static VALUE
-etc_getpwuid(int argc, VALUE *argv, VALUE obj)
-{
-#if defined(HAVE_GETPWENT)
- VALUE id;
- rb_uid_t uid;
- struct passwd *pwd;
-
- if (rb_scan_args(argc, argv, "01", &id) == 1) {
- uid = NUM2UIDT(id);
- }
- else {
- uid = getuid();
- }
- pwd = getpwuid(uid);
- if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", (int)uid);
- return setup_passwd(pwd);
-#else
- return Qnil;
-#endif
-}
-
-/* call-seq:
- * getpwnam(name) -> Passwd
- *
- * Returns the /etc/passwd information for the user with specified login
- * +name+.
- *
- * The information is returned as a Passwd struct.
- *
- * See the unix manpage for <code>getpwnam(3)</code> for more detail.
- *
- * === Example:
- *
- * Etc.getpwnam('root')
- * #=> #<struct Etc::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
- */
-static VALUE
-etc_getpwnam(VALUE obj, VALUE nam)
-{
-#ifdef HAVE_GETPWENT
- struct passwd *pwd;
-
- SafeStringValue(nam);
- pwd = getpwnam(RSTRING_PTR(nam));
- if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, nam);
- return setup_passwd(pwd);
-#else
- return Qnil;
-#endif
-}
-
-#ifdef HAVE_GETPWENT
-static int passwd_blocking = 0;
-static VALUE
-passwd_ensure(void)
-{
- endpwent();
- passwd_blocking = (int)Qfalse;
- return Qnil;
-}
-
-static VALUE
-passwd_iterate(void)
-{
- struct passwd *pw;
-
- setpwent();
- while (pw = getpwent()) {
- rb_yield(setup_passwd(pw));
- }
- return Qnil;
-}
-
-static void
-each_passwd(void)
-{
- if (passwd_blocking) {
- rb_raise(rb_eRuntimeError, "parallel passwd iteration");
- }
- passwd_blocking = (int)Qtrue;
- rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
-}
-#endif
-
-/* call-seq:
- * Etc.passwd { |struct| block } -> Passwd
- * Etc.passwd -> Passwd
- *
- * Provides a convenient Ruby iterator which executes a block for each entry
- * in the /etc/passwd file.
- *
- * The code block is passed an Passwd struct.
- *
- * See ::getpwent above for details.
- *
- * Example:
- *
- * require 'etc'
- *
- * Etc.passwd {|u|
- * puts u.name + " = " + u.gecos
- * }
- *
- */
-static VALUE
-etc_passwd(VALUE obj)
-{
-#ifdef HAVE_GETPWENT
- struct passwd *pw;
-
- if (rb_block_given_p()) {
- each_passwd();
- }
- else if (pw = getpwent()) {
- return setup_passwd(pw);
- }
-#endif
- return Qnil;
-}
-
-/* call-seq:
- * Etc::Passwd.each { |struct| block } -> Passwd
- * Etc::Passwd.each -> Enumerator
- *
- * Iterates for each entry in the /etc/passwd file if a block is given.
- *
- * If no block is given, returns the Enumerator.
- *
- * The code block is passed an Passwd struct.
- *
- * See ::getpwent above for details.
- *
- * Example:
- *
- * require 'etc'
- *
- * Etc::Passwd.each {|u|
- * puts u.name + " = " + u.gecos
- * }
- *
- * Etc::Passwd.collect {|u| u.gecos}
- * Etc::Passwd.collect {|u| u.gecos}
- *
- */
-static VALUE
-etc_each_passwd(VALUE obj)
-{
-#ifdef HAVE_GETPWENT
- RETURN_ENUMERATOR(obj, 0, 0);
- each_passwd();
-#endif
- return obj;
-}
-
-/* Resets the process of reading the /etc/passwd file, so that the next call
- * to ::getpwent will return the first entry again.
- */
-static VALUE
-etc_setpwent(VALUE obj)
-{
-#ifdef HAVE_GETPWENT
- setpwent();
-#endif
- return Qnil;
-}
-
-/* Ends the process of scanning through the /etc/passwd file begun with
- * ::getpwent, and closes the file.
- */
-static VALUE
-etc_endpwent(VALUE obj)
-{
-#ifdef HAVE_GETPWENT
- endpwent();
-#endif
- return Qnil;
-}
-
-/* Returns an entry from the /etc/passwd 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
- * has been reached.
- *
- * To close the file when processing is complete, call ::endpwent.
- *
- * Each entry is returned as a Passwd struct.
- *
- */
-static VALUE
-etc_getpwent(VALUE obj)
-{
-#ifdef HAVE_GETPWENT
- struct passwd *pw;
-
- if (pw = getpwent()) {
- return setup_passwd(pw);
- }
-#endif
- return Qnil;
-}
-
-#ifdef HAVE_GETGRENT
-static VALUE
-setup_group(struct group *grp)
-{
- VALUE mem;
- char **tbl;
-
- mem = rb_ary_new();
- tbl = grp->gr_mem;
- while (*tbl) {
- rb_ary_push(mem, safe_setup_locale_str(*tbl));
- tbl++;
- }
- return rb_struct_new(sGroup,
- safe_setup_locale_str(grp->gr_name),
-#ifdef HAVE_STRUCT_GROUP_GR_PASSWD
- safe_setup_str(grp->gr_passwd),
-#endif
- GIDT2NUM(grp->gr_gid),
- mem);
-}
-#endif
-
-/* call-seq:
- * getgrgid(group_id) -> Group
- *
- * Returns information about the group with specified integer +group_id+,
- * as found in /etc/group.
- *
- * The information is returned as a Group struct.
- *
- * See the unix manpage for <code>getgrgid(3)</code> for more detail.
- *
- * === Example:
- *
- * Etc.getgrgid(100)
- * #=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
- *
- */
-static VALUE
-etc_getgrgid(int argc, VALUE *argv, VALUE obj)
-{
-#ifdef HAVE_GETGRENT
- VALUE id;
- gid_t gid;
- struct group *grp;
-
- if (rb_scan_args(argc, argv, "01", &id) == 1) {
- gid = NUM2GIDT(id);
- }
- else {
- gid = getgid();
- }
- grp = getgrgid(gid);
- if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", (int)gid);
- return setup_group(grp);
-#else
- return Qnil;
-#endif
-}
-
-/* call-seq:
- * getgrnam(name) -> Group
- *
- * Returns information about the group with specified +name+, as found in
- * /etc/group.
- *
- * The information is returned as a Group struct.
- *
- * See the unix manpage for <code>getgrnam(3)</code> for more detail.
- *
- * === Example:
- *
- * Etc.getgrnam('users')
- * #=> #<struct Etc::Group name="users", passwd="x", gid=100, mem=["meta", "root"]>
- *
- */
-static VALUE
-etc_getgrnam(VALUE obj, VALUE nam)
-{
-#ifdef HAVE_GETGRENT
- struct group *grp;
-
- SafeStringValue(nam);
- grp = getgrnam(RSTRING_PTR(nam));
- if (grp == 0) rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, nam);
- return setup_group(grp);
-#else
- return Qnil;
-#endif
-}
-
-#ifdef HAVE_GETGRENT
-static int group_blocking = 0;
-static VALUE
-group_ensure(void)
-{
- endgrent();
- group_blocking = (int)Qfalse;
- return Qnil;
-}
-
-
-static VALUE
-group_iterate(void)
-{
- struct group *pw;
-
- setgrent();
- while (pw = getgrent()) {
- rb_yield(setup_group(pw));
- }
- return Qnil;
-}
-
-static void
-each_group(void)
-{
- if (group_blocking) {
- rb_raise(rb_eRuntimeError, "parallel group iteration");
- }
- group_blocking = (int)Qtrue;
- rb_ensure(group_iterate, 0, group_ensure, 0);
-}
-#endif
-
-/* Provides a convenient Ruby iterator which executes a block for each entry
- * in the /etc/group file.
- *
- * The code block is passed an Group struct.
- *
- * See ::getgrent above for details.
- *
- * Example:
- *
- * require 'etc'
- *
- * Etc.group {|g|
- * puts g.name + ": " + g.mem.join(', ')
- * }
- *
- */
-static VALUE
-etc_group(VALUE obj)
-{
-#ifdef HAVE_GETGRENT
- struct group *grp;
-
- if (rb_block_given_p()) {
- each_group();
- }
- else if (grp = getgrent()) {
- return setup_group(grp);
- }
-#endif
- return Qnil;
-}
-
-#ifdef HAVE_GETGRENT
-/* call-seq:
- * Etc::Group.each { |group| block } -> obj
- * Etc::Group.each -> Enumerator
- *
- * Iterates for each entry in the /etc/group file if a block is given.
- *
- * If no block is given, returns the Enumerator.
- *
- * The code block is passed a Group struct.
- *
- * Example:
- *
- * require 'etc'
- *
- * Etc::Group.each {|g|
- * puts g.name + ": " + g.mem.join(', ')
- * }
- *
- * Etc::Group.collect {|g| g.name}
- * Etc::Group.select {|g| !g.mem.empty?}
- *
- */
-static VALUE
-etc_each_group(VALUE obj)
-{
- RETURN_ENUMERATOR(obj, 0, 0);
- each_group();
- return obj;
-}
-#endif
-
-/* Resets the process of reading the /etc/group file, so that the next call
- * to ::getgrent will return the first entry again.
- */
-static VALUE
-etc_setgrent(VALUE obj)
-{
-#ifdef HAVE_GETGRENT
- setgrent();
-#endif
- return Qnil;
-}
-
-/* Ends the process of scanning through the /etc/group file begun by
- * ::getgrent, and closes the file.
- */
-static VALUE
-etc_endgrent(VALUE obj)
-{
-#ifdef HAVE_GETGRENT
- endgrent();
-#endif
- return Qnil;
-}
-
-/* Returns an entry from the /etc/group 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
- * has been reached.
- *
- * To close the file when processing is complete, call ::endgrent.
- *
- * Each entry is returned as a Group struct
- */
-static VALUE
-etc_getgrent(VALUE obj)
-{
-#ifdef HAVE_GETGRENT
- struct group *gr;
-
- if (gr = getgrent()) {
- return setup_group(gr);
- }
-#endif
- return Qnil;
-}
-
-#define numberof(array) (sizeof(array) / sizeof(*(array)))
-
-#ifdef _WIN32
-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);
-#endif
-
-/*
- * Returns system configuration directory.
- *
- * This is typically "/etc", but is modified by the prefix used when Ruby was
- * compiled. For example, if Ruby is built and installed in /usr/local, returns
- * "/usr/local/etc".
- */
-static VALUE
-etc_sysconfdir(VALUE obj)
-{
-#ifdef _WIN32
- return rb_w32_special_folder(CSIDL_COMMON_APPDATA);
-#else
- return rb_filesystem_str_new_cstr(SYSCONFDIR);
-#endif
-}
-
-/*
- * Returns system temporary directory; typically "/tmp".
- */
-static VALUE
-etc_systmpdir(void)
-{
- VALUE tmpdir;
-#ifdef _WIN32
- WCHAR path[_MAX_PATH];
- UINT len = rb_w32_system_tmpdir(path, numberof(path));
- if (!len) return Qnil;
- tmpdir = rb_w32_conv_from_wchar(path, rb_filesystem_encoding());
-#else
- const char default_tmp[] = "/tmp";
- const char *tmpstr = default_tmp;
- size_t tmplen = strlen(default_tmp);
-# if defined _CS_DARWIN_USER_TEMP_DIR
- #ifndef MAXPATHLEN
- #define MAXPATHLEN 1024
- #endif
- char path[MAXPATHLEN];
- size_t len;
- len = confstr(_CS_DARWIN_USER_TEMP_DIR, path, sizeof(path));
- if (len > 0) {
- tmpstr = path;
- tmplen = len - 1;
- }
-# endif
- tmpdir = rb_filesystem_str_new(tmpstr, tmplen);
-#endif
- FL_UNSET(tmpdir, FL_TAINT);
- return tmpdir;
-}
-
-#ifdef HAVE_UNAME
-/*
- * 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:
- *
- * require 'etc'
- * require 'pp'
- *
- * pp Etc.uname
- * #=> {:sysname=>"Linux",
- * # :nodename=>"boron",
- * # :release=>"2.6.18-6-xen-686",
- * # :version=>"#1 SMP Thu Nov 5 19:54:42 UTC 2009",
- * # :machine=>"i686"}
- *
- */
-static VALUE
-etc_uname(VALUE obj)
-{
-#ifdef _WIN32
- OSVERSIONINFOW v;
- SYSTEM_INFO s;
- const char *sysname, *mach;
- VALUE result, release, version;
- VALUE vbuf, nodename = Qnil;
- DWORD len = 0;
- WCHAR *buf;
-
- v.dwOSVersionInfoSize = sizeof(v);
- if (!GetVersionExW(&v))
- rb_sys_fail("GetVersionEx");
-
- result = rb_hash_new();
- switch (v.dwPlatformId) {
- case VER_PLATFORM_WIN32s:
- sysname = "Win32s";
- break;
- case VER_PLATFORM_WIN32_NT:
- sysname = "Windows_NT";
- break;
- case VER_PLATFORM_WIN32_WINDOWS:
- default:
- sysname = "Windows";
- break;
- }
- rb_hash_aset(result, ID2SYM(rb_intern("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);
- 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);
-
-# 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)) {
- nodename = rb_w32_conv_from_wchar(buf, rb_utf8_encoding());
- }
- ALLOCV_END(vbuf);
- if (NIL_P(nodename)) nodename = rb_str_new(0, 0);
- rb_hash_aset(result, ID2SYM(rb_intern("nodename")), nodename);
-
-# ifndef PROCESSOR_ARCHITECTURE_AMD64
-# define PROCESSOR_ARCHITECTURE_AMD64 9
-# endif
-# ifndef PROCESSOR_ARCHITECTURE_IA64
-# define PROCESSOR_ARCHITECTURE_IA64 6
-# endif
-# ifndef PROCESSOR_ARCHITECTURE_INTEL
-# define PROCESSOR_ARCHITECTURE_INTEL 0
-# endif
- GetSystemInfo(&s);
- switch (s.wProcessorArchitecture) {
- case PROCESSOR_ARCHITECTURE_AMD64:
- mach = "x64";
- break;
- case PROCESSOR_ARCHITECTURE_ARM:
- mach = "ARM";
- break;
- case PROCESSOR_ARCHITECTURE_IA64:
- mach = "IA64";
- break;
- case PROCESSOR_ARCHITECTURE_INTEL:
- mach = "x86";
- break;
- default:
- mach = "unknown";
- break;
- }
-
- rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(mach));
-#else
- struct utsname u;
- int ret;
- VALUE result;
-
- ret = uname(&u);
- if (ret == -1)
- 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));
-#endif
-
- return result;
-}
-#else
-#define etc_uname rb_f_notimplement
-#endif
-
-#ifdef HAVE_SYSCONF
-/*
- * Returns system configuration variable using sysconf().
- *
- * _name_ should be a constant under <code>Etc</code> which begins with <code>SC_</code>.
- *
- * The return value is an integer or nil.
- * nil means indefinite limit. (sysconf() returns -1 but errno is not set.)
- *
- * Etc.sysconf(Etc::SC_ARG_MAX) #=> 2097152
- * Etc.sysconf(Etc::SC_LOGIN_NAME_MAX) #=> 256
- *
- */
-static VALUE
-etc_sysconf(VALUE obj, VALUE arg)
-{
- int name;
- long ret;
-
- name = NUM2INT(arg);
-
- errno = 0;
- ret = sysconf(name);
- if (ret == -1) {
- if (errno == 0) /* no limit */
- return Qnil;
- rb_sys_fail("sysconf");
- }
- return LONG2NUM(ret);
-}
-#else
-#define etc_sysconf rb_f_notimplement
-#endif
-
-#ifdef HAVE_CONFSTR
-/*
- * Returns system configuration variable using confstr().
- *
- * _name_ should be a constant under <code>Etc</code> which begins with <code>CS_</code>.
- *
- * The return value is a string or nil.
- * nil means no configuration-defined value. (confstr() returns 0 but errno is not set.)
- *
- * Etc.confstr(Etc::CS_PATH) #=> "/bin:/usr/bin"
- *
- * # GNU/Linux
- * Etc.confstr(Etc::CS_GNU_LIBC_VERSION) #=> "glibc 2.18"
- * Etc.confstr(Etc::CS_GNU_LIBPTHREAD_VERSION) #=> "NPTL 2.18"
- *
- */
-static VALUE
-etc_confstr(VALUE obj, VALUE arg)
-{
- int name;
- char localbuf[128], *buf = localbuf;
- size_t bufsize = sizeof(localbuf), ret;
- VALUE tmp;
-
- name = NUM2INT(arg);
-
- errno = 0;
- ret = confstr(name, buf, bufsize);
- if (bufsize < ret) {
- bufsize = ret;
- buf = ALLOCV_N(char, tmp, bufsize);
- errno = 0;
- ret = confstr(name, buf, bufsize);
- }
- if (bufsize < ret)
- rb_bug("required buffer size for confstr() changed dynamically.");
- if (ret == 0) {
- if (errno == 0) /* no configuration-defined value */
- return Qnil;
- rb_sys_fail("confstr");
- }
- return rb_str_new_cstr(buf);
-}
-#else
-#define etc_confstr rb_f_notimplement
-#endif
-
-#ifdef HAVE_FPATHCONF
-/*
- * Returns pathname configuration variable using fpathconf().
- *
- * _name_ should be a constant under <code>Etc</code> which begins with <code>PC_</code>.
- *
- * The return value is an integer or nil.
- * nil means indefinite limit. (fpathconf() returns -1 but errno is not set.)
- *
- * require 'etc'
- * IO.pipe {|r, w|
- * p w.pathconf(Etc::PC_PIPE_BUF) #=> 4096
- * }
- *
- */
-static VALUE
-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);
- if (ret == -1) {
- if (errno == 0) /* no limit */
- return Qnil;
- rb_sys_fail("fpathconf");
- }
- return LONG2NUM(ret);
-}
-#else
-#define io_pathconf rb_f_notimplement
-#endif
-
-#if (defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)) || defined(_WIN32)
-
-#if defined(HAVE_SCHED_GETAFFINITY) && defined(CPU_ALLOC)
-static int
-etc_nprocessors_affin(void)
-{
- cpu_set_t *cpuset;
- size_t size;
- int ret;
- int n;
-
- /*
- * XXX:
- * man page says CPU_ALLOC takes number of cpus. But it is not accurate
- * explanation. sched_getaffinity() returns EINVAL if cpuset bitmap is
- * smaller than kernel internal bitmap.
- * That said, sched_getaffinity() can fail when a kernel have sparse bitmap
- * even if cpuset bitmap is larger than number of cpus.
- * The precious way is to use /sys/devices/system/cpu/online. But there are
- * two problems,
- * - Costly calculation
- * It is a minor issue, but possibly kill a benefit of a parallel processing.
- * - No guarantee to exist /sys/devices/system/cpu/online
- * This is an issue especially when using Linux containers.
- * So, we use hardcode number for a workaround. Current linux kernel
- * (Linux 3.17) support 8192 cpus at maximum. Then 16384 must be enough.
- */
- for (n=64; n <= 16384; n *= 2) {
- size = CPU_ALLOC_SIZE(n);
- if (size >= 1024) {
- cpuset = xcalloc(1, size);
- if (!cpuset)
- return -1;
- } else {
- cpuset = alloca(size);
- CPU_ZERO_S(size, cpuset);
- }
-
- ret = sched_getaffinity(0, size, cpuset);
- if (ret == 0) {
- /* On success, count number of cpus. */
- ret = CPU_COUNT_S(size, cpuset);
- }
-
- if (size >= 1024) {
- xfree(cpuset);
- }
- if (ret > 0) {
- return ret;
- }
- }
-
- return ret;
-}
-#endif
-
-/*
- * Returns the number of online processors.
- *
- * The result is intended as the number of processes to
- * use all available processors.
- *
- * This method is implemented using:
- * - sched_getaffinity(): Linux
- * - sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX
- *
- * Example:
- *
- * require 'etc'
- * p Etc.nprocessors #=> 4
- *
- * The result might be smaller number than physical cpus especially when ruby
- * process is bound to specific cpus. This is intended for getting better
- * parallel processing.
- *
- * Example: (Linux)
- *
- * linux$ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2
- *
- */
-static VALUE
-etc_nprocessors(VALUE obj)
-{
- long ret;
-
-#if !defined(_WIN32)
-
-#if defined(HAVE_SCHED_GETAFFINITY) && defined(CPU_ALLOC)
- int ncpus;
-
- ncpus = etc_nprocessors_affin();
- if (ncpus != -1) {
- return INT2NUM(ncpus);
- }
- /* fallback to _SC_NPROCESSORS_ONLN */
-#endif
-
- errno = 0;
- ret = sysconf(_SC_NPROCESSORS_ONLN);
- if (ret == -1) {
- rb_sys_fail("sysconf(_SC_NPROCESSORS_ONLN)");
- }
-#else
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- ret = (long)si.dwNumberOfProcessors;
-#endif
- return LONG2NUM(ret);
-}
-#else
-#define etc_nprocessors rb_f_notimplement
-#endif
-
-/*
- * The Etc module provides access to information typically stored in
- * files in the /etc directory on Unix systems.
- *
- * The information accessible consists of the information found in the
- * /etc/passwd and /etc/group files, plus information about the system's
- * temporary directory (/tmp) and configuration directory (/etc).
- *
- * The Etc module provides a more reliable way to access information about
- * the logged in user than environment variables such as +$USER+.
- *
- * == Example:
- *
- * require 'etc'
- *
- * login = Etc.getlogin
- * info = Etc.getpwnam(login)
- * username = info.gecos.split(/,/).first
- * puts "Hello #{username}, I see your login name is #{login}"
- *
- * Note that the methods provided by this module are not always secure.
- * It should be used for informational purposes, and not for security.
- *
- * All operations defined in this module are class methods, so that you can
- * include the Etc module into your class.
- */
-void
-Init_etc(void)
-{
- VALUE mEtc;
-
- mEtc = rb_define_module("Etc");
- init_constants(mEtc);
-
- rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0);
-
- rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1);
- rb_define_module_function(mEtc, "getpwnam", etc_getpwnam, 1);
- rb_define_module_function(mEtc, "setpwent", etc_setpwent, 0);
- rb_define_module_function(mEtc, "endpwent", etc_endpwent, 0);
- rb_define_module_function(mEtc, "getpwent", etc_getpwent, 0);
- rb_define_module_function(mEtc, "passwd", etc_passwd, 0);
-
- rb_define_module_function(mEtc, "getgrgid", etc_getgrgid, -1);
- rb_define_module_function(mEtc, "getgrnam", etc_getgrnam, 1);
- rb_define_module_function(mEtc, "group", etc_group, 0);
- 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);
- 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",
-#ifdef HAVE_STRUCT_PASSWD_PW_PASSWD
- "passwd",
-#endif
- "uid",
- "gid",
-#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
- "gecos",
-#endif
- "dir",
- "shell",
-#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
- "change",
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_QUOTA
- "quota",
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_AGE
- "age",
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
- "uclass",
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_COMMENT
- "comment",
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
- "expire",
-#endif
- NULL);
-#if 0
- /* Define-const: Passwd
- *
- * Passwd is a Struct that contains the following members:
- *
- * name::
- * contains the short login name of the user as a String.
- * passwd::
- * contains the encrypted password of the user as a String.
- * an 'x' is returned if shadow passwords are in use. An '*' is returned
- * if the user cannot log in using a password.
- * uid::
- * contains the integer user ID (uid) of the user.
- * gid::
- * contains the integer group ID (gid) of the user's primary group.
- * dir::
- * contains the path to the home directory of the user as a String.
- * shell::
- * contains the path to the login shell of the user as a String.
- *
- * === The following members below are optional, and must be compiled with special flags:
- *
- * gecos::
- * contains a longer String description of the user, such as
- * a full name. Some Unix systems provide structured information in the
- * gecos field, but this is system-dependent.
- * must be compiled with +HAVE_STRUCT_PASSWD_PW_GECOS+
- * change::
- * password change time(integer) must be compiled with +HAVE_STRUCT_PASSWD_PW_CHANGE+
- * quota::
- * quota value(integer) must be compiled with +HAVE_STRUCT_PASSWD_PW_QUOTA+
- * age::
- * password age(integer) must be compiled with +HAVE_STRUCT_PASSWD_PW_AGE+
- * class::
- * user access class(string) must be compiled with +HAVE_STRUCT_PASSWD_PW_CLASS+
- * comment::
- * comment(string) must be compiled with +HAVE_STRUCT_PASSWD_PW_COMMENT+
- * expire::
- * account expiration time(integer) must be compiled with +HAVE_STRUCT_PASSWD_PW_EXPIRE+
- */
- rb_define_const(mEtc, "Passwd", sPasswd);
-#endif
- rb_define_const(rb_cStruct, "Passwd", sPasswd); /* deprecated name */
- rb_extend_object(sPasswd, rb_mEnumerable);
- rb_define_singleton_method(sPasswd, "each", etc_each_passwd, 0);
-
-#ifdef HAVE_GETGRENT
- sGroup = rb_struct_define_under(mEtc, "Group", "name",
-#ifdef HAVE_STRUCT_GROUP_GR_PASSWD
- "passwd",
-#endif
- "gid", "mem", NULL);
-
-#if 0
- /* Define-const: Group
- *
- * Group is a Struct that is only available when compiled with +HAVE_GETGRENT+.
- *
- * The struct contains the following members:
- *
- * name::
- * contains the name of the group as a String.
- * passwd::
- * contains the encrypted password as a String. An 'x' is
- * returned if password access to the group is not available; an empty
- * string is returned if no password is needed to obtain membership of
- * the group.
- *
- * Must be compiled with +HAVE_STRUCT_GROUP_GR_PASSWD+.
- * gid::
- * contains the group's numeric ID as an integer.
- * mem::
- * is an Array of Strings containing the short login names of the
- * members of the group.
- */
- rb_define_const(mEtc, "Group", sGroup);
-#endif
- rb_define_const(rb_cStruct, "Group", sGroup); /* deprecated name */
- rb_extend_object(sGroup, rb_mEnumerable);
- rb_define_singleton_method(sGroup, "each", etc_each_group, 0);
-#endif
-}