[Feature:1.9] Etc.each_passwd, each_group

e$B$J$+$@$G$9!#e(B

Etc.each_passwde$B$de(BEtc.each_groupe$B$H$$$&$b$N$r;W$$$D$-$^$7$?!#e(B
e$B$^$?!"JLL>$H$7$Fe(BEtc::Passwd.eache$B$de(BEtc.::Group.eache$B$b!#e(B

e$B%Q%9%o!<%I$r@_Dj$7$F$$$J$$%f!<%6L>$N%j%9%He(B

Etc::Passwd.find_all {|u| u.passwd == “”}.map(&:name)

e$B$H$+!#e(B

Index: ext/etc/etc.c

— ext/etc/etc.c (revision 22104)
+++ ext/etc/etc.c (working copy)
@@ -187,4 +187,14 @@ passwd_iterate(void)
return Qnil;
}
+
+static void
+each_passwd(void)
+{

  • if (passwd_blocking) {
  • rb_raise(rb_eRuntimeError, “parallel passwd iteration”);
  • }
  • passwd_blocking = Qtrue;
  • rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
    +}
    #endif

@@ -212,11 +222,7 @@ etc_passwd(VALUE obj)
rb_secure(4);
if (rb_block_given_p()) {

  • if (passwd_blocking) {
  •  rb_raise(rb_eRuntimeError, "parallel passwd iteration");
    
  • }
  • passwd_blocking = Qtrue;
  • rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
  • each_passwd();
    }
  • if (pw = getpwent()) {
  • else if (pw = getpwent()) {
    return setup_passwd(pw);
    }
    @@ -225,4 +231,32 @@ etc_passwd(VALUE obj)
    }

+/* 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 Struct::Passwd struct; see getpwent
      above for
    • details.
    • Example:
    • require 'etc'
      
    • Etc.each_passwd {|u|
      
    •   puts u.name + " = " + u.gecos
      
    • }
      
    • Etc.each_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.
    @@ -391,4 +425,14 @@ group_iterate(void)
    return Qnil;
    }

+static void
+each_group(void)
+{

  • if (group_blocking) {
  • rb_raise(rb_eRuntimeError, “parallel group iteration”);
  • }
  • group_blocking = Qtrue;
  • rb_ensure(group_iterate, 0, group_ensure, 0);
    +}
    #endif

@@ -416,11 +460,7 @@ etc_group(VALUE obj)
rb_secure(4);
if (rb_block_given_p()) {

  • if (group_blocking) {
  •  rb_raise(rb_eRuntimeError, "parallel group iteration");
    
  • }
  • group_blocking = Qtrue;
  • rb_ensure(group_iterate, 0, group_ensure, 0);
  • each_group();
    }
  • if (grp = getgrent()) {
  • else if (grp = getgrent()) {
    return setup_group(grp);
    }
    @@ -429,4 +469,32 @@ etc_group(VALUE obj)
    }

+/* 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 an Struct::Group struct; see getpwent above
      for
    • details.
    • Example:
    • require 'etc'
      
    • Etc.each_group {|g|
      
    •   puts g.name + ": " + g.mem.join(', ')
      
    • }
      
    • Etc.each_group.collect {|g| g.name}
      
    • Etc::Group.select {|g| !g.mem.empty?}
      
  • */
    +static VALUE
    +etc_each_group(VALUE obj)
    +{
    +#ifdef HAVE_GETPWENT
  • RETURN_ENUMERATOR(obj, 0, 0);
  • each_group();
    +#endif
  • return obj;
    +}

/* Resets the process of reading the /etc/group file, so that the next
call

  • to getgrent will return the first entry again.
    @@ -505,8 +573,10 @@ Init_etc(void)
    rb_define_module_function(mEtc, “getpwent”, etc_getpwent, 0);
    rb_define_module_function(mEtc, “passwd”, etc_passwd, 0);
  • rb_define_module_function(mEtc, “each_passwd”, etc_each_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, “each_group”, etc_each_group, 0);
    rb_define_module_function(mEtc, “setgrent”, etc_setgrent, 0);
    rb_define_module_function(mEtc, “endgrent”, etc_endgrent, 0);
    @@ -539,4 +609,6 @@ Init_etc(void)
    NULL);
    rb_define_const(mEtc, “Passwd”, sPasswd);

  • rb_extend_object(sPasswd, rb_mEnumerable);

  • rb_define_singleton_method(sPasswd, “each”, etc_each_passwd, 0);

#ifdef HAVE_GETGRENT
@@ -548,4 +620,6 @@ Init_etc(void)

 rb_define_const(mEtc, "Group", sGroup);
  • rb_extend_object(sGroup, rb_mEnumerable);
  • rb_define_singleton_method(sGroup, “each”, etc_each_group, 0);
    #endif
    }

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:37999] [Feature:1.9] Etc.each_passwd,
each_group”
on Fri, 13 Feb 2009 22:30:01 +0900, Nobuyoshi N.
[email protected] writes:

|Etc.each_passwde$B$de(BEtc.each_groupe$B$H$$$&$b$N$r;W$$$D$-$^$7$?!#e(B

e$B8_49@-$r5$$K$7$J$1$l$P!"e(BEtc.passwde$B$,e(Beach_passwde$B$H$7$FF0:n$9e(B
e$B$Y$-$G$O$J$$$+$H46$8$^$7$?!#e(B

|e$B$^$?!"JLL>$H$7$Fe(BEtc::Passwd.eache$B$de(BEtc.::Group.eache$B$b!#e(B
|
| # e$B%Q%9%o!<%I$r@_Dj$7$F$$$J$$%f!<%6L>$N%j%9%He(B
| Etc::Passwd.find_all {|u| u.passwd == “”}.map(&:name)
|
|e$B$H$+!#e(B

e$B$3$C$A$O;?@.$7$^$9!#e(B

e$B%A%1%C%He(B #1155 e$B$,99?7$5$l$^$7$?!#e(B (by Nobuyoshi N.)

e$B%9%F!<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

Applied in changeset r22377.

http://redmine.ruby-lang.org/issues/show/1155