Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /************************************************ 00002 00003 etc.c - 00004 00005 $Author: nagachika $ 00006 created at: Tue Mar 22 18:39:19 JST 1994 00007 00008 ************************************************/ 00009 00010 #include "ruby.h" 00011 #include "ruby/encoding.h" 00012 00013 #include <sys/types.h> 00014 #ifdef HAVE_UNISTD_H 00015 #include <unistd.h> 00016 #endif 00017 00018 #ifdef HAVE_GETPWENT 00019 #include <pwd.h> 00020 #endif 00021 00022 #ifdef HAVE_GETGRENT 00023 #include <grp.h> 00024 #endif 00025 00026 static VALUE sPasswd; 00027 #ifdef HAVE_GETGRENT 00028 static VALUE sGroup; 00029 #endif 00030 00031 #ifdef _WIN32 00032 #include <shlobj.h> 00033 #ifndef CSIDL_COMMON_APPDATA 00034 #define CSIDL_COMMON_APPDATA 35 00035 #endif 00036 #endif 00037 00038 #ifndef _WIN32 00039 char *getenv(); 00040 #endif 00041 char *getlogin(); 00042 00043 /* call-seq: 00044 * getlogin -> String 00045 * 00046 * Returns the short user name of the currently logged in user. 00047 * Unfortunately, it is often rather easy to fool ::getlogin. 00048 * 00049 * Avoid ::getlogin for security-related purposes. 00050 * 00051 * If ::getlogin fails, try ::getpwuid. 00052 * 00053 * See the unix manpage for <code>getpwuid(3)</code> for more detail. 00054 * 00055 * e.g. 00056 * Etc.getlogin -> 'guest' 00057 */ 00058 static VALUE 00059 etc_getlogin(VALUE obj) 00060 { 00061 char *login; 00062 00063 rb_secure(4); 00064 #ifdef HAVE_GETLOGIN 00065 login = getlogin(); 00066 if (!login) login = getenv("USER"); 00067 #else 00068 login = getenv("USER"); 00069 #endif 00070 00071 if (login) 00072 return rb_tainted_str_new2(login); 00073 return Qnil; 00074 } 00075 00076 #if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT) 00077 static VALUE 00078 safe_setup_str(const char *str) 00079 { 00080 if (str == 0) str = ""; 00081 return rb_tainted_str_new2(str); 00082 } 00083 #endif 00084 00085 #ifdef HAVE_GETPWENT 00086 static VALUE 00087 setup_passwd(struct passwd *pwd) 00088 { 00089 if (pwd == 0) rb_sys_fail("/etc/passwd"); 00090 return rb_struct_new(sPasswd, 00091 safe_setup_str(pwd->pw_name), 00092 #ifdef HAVE_ST_PW_PASSWD 00093 safe_setup_str(pwd->pw_passwd), 00094 #endif 00095 UIDT2NUM(pwd->pw_uid), 00096 GIDT2NUM(pwd->pw_gid), 00097 #ifdef HAVE_ST_PW_GECOS 00098 safe_setup_str(pwd->pw_gecos), 00099 #endif 00100 safe_setup_str(pwd->pw_dir), 00101 safe_setup_str(pwd->pw_shell), 00102 #ifdef HAVE_ST_PW_CHANGE 00103 INT2NUM(pwd->pw_change), 00104 #endif 00105 #ifdef HAVE_ST_PW_QUOTA 00106 INT2NUM(pwd->pw_quota), 00107 #endif 00108 #ifdef HAVE_ST_PW_AGE 00109 PW_AGE2VAL(pwd->pw_age), 00110 #endif 00111 #ifdef HAVE_ST_PW_CLASS 00112 safe_setup_str(pwd->pw_class), 00113 #endif 00114 #ifdef HAVE_ST_PW_COMMENT 00115 safe_setup_str(pwd->pw_comment), 00116 #endif 00117 #ifdef HAVE_ST_PW_EXPIRE 00118 INT2NUM(pwd->pw_expire), 00119 #endif 00120 0 /*dummy*/ 00121 ); 00122 } 00123 #endif 00124 00125 /* call-seq: 00126 * getpwuid(uid) -> Passwd 00127 * 00128 * Returns the /etc/passwd information for the user with the given integer +uid+. 00129 * 00130 * The information is returned as a Passwd struct. 00131 * 00132 * If +uid+ is omitted, the value from <code>Passwd[:uid]</code> is returned 00133 * instead. 00134 * 00135 * See the unix manpage for <code>getpwuid(3)</code> for more detail. 00136 * 00137 * === Example: 00138 * 00139 * Etc.getpwuid(0) 00140 * #=> #<struct Struct::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash"> 00141 */ 00142 static VALUE 00143 etc_getpwuid(int argc, VALUE *argv, VALUE obj) 00144 { 00145 #if defined(HAVE_GETPWENT) 00146 VALUE id; 00147 rb_uid_t uid; 00148 struct passwd *pwd; 00149 00150 rb_secure(4); 00151 if (rb_scan_args(argc, argv, "01", &id) == 1) { 00152 uid = NUM2UIDT(id); 00153 } 00154 else { 00155 uid = getuid(); 00156 } 00157 pwd = getpwuid(uid); 00158 if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", (int)uid); 00159 return setup_passwd(pwd); 00160 #else 00161 return Qnil; 00162 #endif 00163 } 00164 00165 /* call-seq: 00166 * getpwnam(name) -> Passwd 00167 * 00168 * Returns the /etc/passwd information for the user with specified login 00169 * +name+. 00170 * 00171 * The information is returned as a Passwd struct. 00172 * 00173 * See the unix manpage for <code>getpwnam(3)</code> for more detail. 00174 * 00175 * === Example: 00176 * 00177 * Etc.getpwnam('root') 00178 * #=> #<struct Struct::Passwd name="root", passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash"> 00179 */ 00180 static VALUE 00181 etc_getpwnam(VALUE obj, VALUE nam) 00182 { 00183 #ifdef HAVE_GETPWENT 00184 struct passwd *pwd; 00185 00186 SafeStringValue(nam); 00187 pwd = getpwnam(RSTRING_PTR(nam)); 00188 if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, nam); 00189 return setup_passwd(pwd); 00190 #else 00191 return Qnil; 00192 #endif 00193 } 00194 00195 #ifdef HAVE_GETPWENT 00196 static int passwd_blocking = 0; 00197 static VALUE 00198 passwd_ensure(void) 00199 { 00200 endpwent(); 00201 passwd_blocking = (int)Qfalse; 00202 return Qnil; 00203 } 00204 00205 static VALUE 00206 passwd_iterate(void) 00207 { 00208 struct passwd *pw; 00209 00210 setpwent(); 00211 while (pw = getpwent()) { 00212 rb_yield(setup_passwd(pw)); 00213 } 00214 return Qnil; 00215 } 00216 00217 static void 00218 each_passwd(void) 00219 { 00220 if (passwd_blocking) { 00221 rb_raise(rb_eRuntimeError, "parallel passwd iteration"); 00222 } 00223 passwd_blocking = (int)Qtrue; 00224 rb_ensure(passwd_iterate, 0, passwd_ensure, 0); 00225 } 00226 #endif 00227 00228 /* call-seq: 00229 * Etc.passwd { |struct| block } -> Passwd 00230 * Etc.passwd -> Passwd 00231 * 00232 * Provides a convenient Ruby iterator which executes a block for each entry 00233 * in the /etc/passwd file. 00234 * 00235 * The code block is passed an Passwd struct. 00236 * 00237 * See ::getpwent above for details. 00238 * 00239 * Example: 00240 * 00241 * require 'etc' 00242 * 00243 * Etc.passwd {|u| 00244 * puts u.name + " = " + u.gecos 00245 * } 00246 * 00247 */ 00248 static VALUE 00249 etc_passwd(VALUE obj) 00250 { 00251 #ifdef HAVE_GETPWENT 00252 struct passwd *pw; 00253 00254 rb_secure(4); 00255 if (rb_block_given_p()) { 00256 each_passwd(); 00257 } 00258 else if (pw = getpwent()) { 00259 return setup_passwd(pw); 00260 } 00261 #endif 00262 return Qnil; 00263 } 00264 00265 /* call-seq: 00266 * Etc::Passwd.each { |struct| block } -> Passwd 00267 * Etc::Passwd.each -> Enumerator 00268 * 00269 * Iterates for each entry in the /etc/passwd file if a block is given. 00270 * 00271 * If no block is given, returns the Enumerator. 00272 * 00273 * The code block is passed an Passwd struct. 00274 * 00275 * See ::getpwent above for details. 00276 * 00277 * Example: 00278 * 00279 * require 'etc' 00280 * 00281 * Etc::Passwd.each {|u| 00282 * puts u.name + " = " + u.gecos 00283 * } 00284 * 00285 * Etc::Passwd.collect {|u| u.gecos} 00286 * Etc::Passwd.collect {|u| u.gecos} 00287 * 00288 */ 00289 static VALUE 00290 etc_each_passwd(VALUE obj) 00291 { 00292 #ifdef HAVE_GETPWENT 00293 RETURN_ENUMERATOR(obj, 0, 0); 00294 each_passwd(); 00295 #endif 00296 return obj; 00297 } 00298 00299 /* Resets the process of reading the /etc/passwd file, so that the next call 00300 * to ::getpwent will return the first entry again. 00301 */ 00302 static VALUE 00303 etc_setpwent(VALUE obj) 00304 { 00305 #ifdef HAVE_GETPWENT 00306 setpwent(); 00307 #endif 00308 return Qnil; 00309 } 00310 00311 /* Ends the process of scanning through the /etc/passwd file begun with 00312 * ::getpwent, and closes the file. 00313 */ 00314 static VALUE 00315 etc_endpwent(VALUE obj) 00316 { 00317 #ifdef HAVE_GETPWENT 00318 endpwent(); 00319 #endif 00320 return Qnil; 00321 } 00322 00323 /* Returns an entry from the /etc/passwd file. 00324 * 00325 * The first time it is called it opens the file and returns the first entry; 00326 * each successive call returns the next entry, or +nil+ if the end of the file 00327 * has been reached. 00328 * 00329 * To close the file when processing is complete, call ::endpwent. 00330 * 00331 * Each entry is returned as a Passwd struct. 00332 * 00333 */ 00334 static VALUE 00335 etc_getpwent(VALUE obj) 00336 { 00337 #ifdef HAVE_GETPWENT 00338 struct passwd *pw; 00339 00340 if (pw = getpwent()) { 00341 return setup_passwd(pw); 00342 } 00343 #endif 00344 return Qnil; 00345 } 00346 00347 #ifdef HAVE_GETGRENT 00348 static VALUE 00349 setup_group(struct group *grp) 00350 { 00351 VALUE mem; 00352 char **tbl; 00353 00354 mem = rb_ary_new(); 00355 tbl = grp->gr_mem; 00356 while (*tbl) { 00357 rb_ary_push(mem, safe_setup_str(*tbl)); 00358 tbl++; 00359 } 00360 return rb_struct_new(sGroup, 00361 safe_setup_str(grp->gr_name), 00362 #ifdef HAVE_ST_GR_PASSWD 00363 safe_setup_str(grp->gr_passwd), 00364 #endif 00365 GIDT2NUM(grp->gr_gid), 00366 mem); 00367 } 00368 #endif 00369 00370 /* call-seq: 00371 * getgrgid(group_id) -> Group 00372 * 00373 * Returns information about the group with specified integer +group_id+, 00374 * as found in /etc/group. 00375 * 00376 * The information is returned as a Group struct. 00377 * 00378 * See the unix manpage for <code>getgrgid(3)</code> for more detail. 00379 * 00380 * === Example: 00381 * 00382 * Etc.getgrgid(100) 00383 * #=> #<struct Struct::Group name="users", passwd="x", gid=100, mem=["meta", "root"]> 00384 * 00385 */ 00386 static VALUE 00387 etc_getgrgid(int argc, VALUE *argv, VALUE obj) 00388 { 00389 #ifdef HAVE_GETGRENT 00390 VALUE id; 00391 gid_t gid; 00392 struct group *grp; 00393 00394 rb_secure(4); 00395 if (rb_scan_args(argc, argv, "01", &id) == 1) { 00396 gid = NUM2GIDT(id); 00397 } 00398 else { 00399 gid = getgid(); 00400 } 00401 grp = getgrgid(gid); 00402 if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", (int)gid); 00403 return setup_group(grp); 00404 #else 00405 return Qnil; 00406 #endif 00407 } 00408 00409 /* call-seq: 00410 * getgrnam(name) -> Group 00411 * 00412 * Returns information about the group with specified +name+, as found in 00413 * /etc/group. 00414 * 00415 * The information is returned as a Group struct. 00416 * 00417 * See the unix manpage for <code>getgrnam(3)</code> for more detail. 00418 * 00419 * === Example: 00420 * 00421 * Etc.getgrnam('users') 00422 * #=> #<struct Struct::Group name="users", passwd="x", gid=100, mem=["meta", "root"]> 00423 * 00424 */ 00425 static VALUE 00426 etc_getgrnam(VALUE obj, VALUE nam) 00427 { 00428 #ifdef HAVE_GETGRENT 00429 struct group *grp; 00430 00431 rb_secure(4); 00432 SafeStringValue(nam); 00433 grp = getgrnam(RSTRING_PTR(nam)); 00434 if (grp == 0) rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, nam); 00435 return setup_group(grp); 00436 #else 00437 return Qnil; 00438 #endif 00439 } 00440 00441 #ifdef HAVE_GETGRENT 00442 static int group_blocking = 0; 00443 static VALUE 00444 group_ensure(void) 00445 { 00446 endgrent(); 00447 group_blocking = (int)Qfalse; 00448 return Qnil; 00449 } 00450 00451 00452 static VALUE 00453 group_iterate(void) 00454 { 00455 struct group *pw; 00456 00457 setgrent(); 00458 while (pw = getgrent()) { 00459 rb_yield(setup_group(pw)); 00460 } 00461 return Qnil; 00462 } 00463 00464 static void 00465 each_group(void) 00466 { 00467 if (group_blocking) { 00468 rb_raise(rb_eRuntimeError, "parallel group iteration"); 00469 } 00470 group_blocking = (int)Qtrue; 00471 rb_ensure(group_iterate, 0, group_ensure, 0); 00472 } 00473 #endif 00474 00475 /* Provides a convenient Ruby iterator which executes a block for each entry 00476 * in the /etc/group file. 00477 * 00478 * The code block is passed an Group struct. 00479 * 00480 * See ::getgrent above for details. 00481 * 00482 * Example: 00483 * 00484 * require 'etc' 00485 * 00486 * Etc.group {|g| 00487 * puts g.name + ": " + g.mem.join(', ') 00488 * } 00489 * 00490 */ 00491 static VALUE 00492 etc_group(VALUE obj) 00493 { 00494 #ifdef HAVE_GETGRENT 00495 struct group *grp; 00496 00497 rb_secure(4); 00498 if (rb_block_given_p()) { 00499 each_group(); 00500 } 00501 else if (grp = getgrent()) { 00502 return setup_group(grp); 00503 } 00504 #endif 00505 return Qnil; 00506 } 00507 00508 #ifdef HAVE_GETGRENT 00509 /* call-seq: 00510 * Etc::Group.each { |group| block } -> obj 00511 * Etc::Group.each -> Enumerator 00512 * 00513 * Iterates for each entry in the /etc/group file if a block is given. 00514 * 00515 * If no block is given, returns the Enumerator. 00516 * 00517 * The code block is passed a Group struct. 00518 * 00519 * Example: 00520 * 00521 * require 'etc' 00522 * 00523 * Etc::Group.each {|g| 00524 * puts g.name + ": " + g.mem.join(', ') 00525 * } 00526 * 00527 * Etc::Group.collect {|g| g.name} 00528 * Etc::Group.select {|g| !g.mem.empty?} 00529 * 00530 */ 00531 static VALUE 00532 etc_each_group(VALUE obj) 00533 { 00534 RETURN_ENUMERATOR(obj, 0, 0); 00535 each_group(); 00536 return obj; 00537 } 00538 #endif 00539 00540 /* Resets the process of reading the /etc/group file, so that the next call 00541 * to ::getgrent will return the first entry again. 00542 */ 00543 static VALUE 00544 etc_setgrent(VALUE obj) 00545 { 00546 #ifdef HAVE_GETGRENT 00547 setgrent(); 00548 #endif 00549 return Qnil; 00550 } 00551 00552 /* Ends the process of scanning through the /etc/group file begun by 00553 * ::getgrent, and closes the file. 00554 */ 00555 static VALUE 00556 etc_endgrent(VALUE obj) 00557 { 00558 #ifdef HAVE_GETGRENT 00559 endgrent(); 00560 #endif 00561 return Qnil; 00562 } 00563 00564 /* Returns an entry from the /etc/group file. 00565 * 00566 * The first time it is called it opens the file and returns the first entry; 00567 * each successive call returns the next entry, or +nil+ if the end of the file 00568 * has been reached. 00569 * 00570 * To close the file when processing is complete, call ::endgrent. 00571 * 00572 * Each entry is returned as a Group struct 00573 */ 00574 static VALUE 00575 etc_getgrent(VALUE obj) 00576 { 00577 #ifdef HAVE_GETGRENT 00578 struct group *gr; 00579 00580 if (gr = getgrent()) { 00581 return setup_group(gr); 00582 } 00583 #endif 00584 return Qnil; 00585 } 00586 00587 #define numberof(array) (sizeof(array) / sizeof(*(array))) 00588 00589 #ifdef _WIN32 00590 VALUE rb_w32_special_folder(int type); 00591 UINT rb_w32_system_tmpdir(WCHAR *path, UINT len); 00592 VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc); 00593 #endif 00594 00595 /* 00596 * Returns system configuration directory. 00597 * 00598 * This is typically "/etc", but is modified by the prefix used when Ruby was 00599 * compiled. For example, if Ruby is built and installed in /usr/local, returns 00600 * "/usr/local/etc". 00601 */ 00602 static VALUE 00603 etc_sysconfdir(VALUE obj) 00604 { 00605 #ifdef _WIN32 00606 return rb_w32_special_folder(CSIDL_COMMON_APPDATA); 00607 #else 00608 return rb_filesystem_str_new_cstr(SYSCONFDIR); 00609 #endif 00610 } 00611 00612 /* 00613 * Returns system temporary directory; typically "/tmp". 00614 */ 00615 static VALUE 00616 etc_systmpdir(void) 00617 { 00618 VALUE tmpdir; 00619 #ifdef _WIN32 00620 WCHAR path[_MAX_PATH]; 00621 UINT len = rb_w32_system_tmpdir(path, numberof(path)); 00622 if (!len) return Qnil; 00623 tmpdir = rb_w32_conv_from_wchar(path, rb_filesystem_encoding()); 00624 #else 00625 tmpdir = rb_filesystem_str_new_cstr("/tmp"); 00626 #endif 00627 FL_UNSET(tmpdir, FL_TAINT|FL_UNTRUSTED); 00628 return tmpdir; 00629 } 00630 00631 /* 00632 * The Etc module provides access to information typically stored in 00633 * files in the /etc directory on Unix systems. 00634 * 00635 * The information accessible consists of the information found in the 00636 * /etc/passwd and /etc/group files, plus information about the system's 00637 * temporary directory (/tmp) and configuration directory (/etc). 00638 * 00639 * The Etc module provides a more reliable way to access information about 00640 * the logged in user than environment variables such as +$USER+. 00641 * 00642 * == Example: 00643 * 00644 * require 'etc' 00645 * 00646 * login = Etc.getlogin 00647 * info = Etc.getpwnam(login) 00648 * username = info.gecos.split(/,/).first 00649 * puts "Hello #{username}, I see your login name is #{login}" 00650 * 00651 * Note that the methods provided by this module are not always secure. 00652 * It should be used for informational purposes, and not for security. 00653 * 00654 * All operations defined in this module are class methods, so that you can 00655 * include the Etc module into your class. 00656 */ 00657 void 00658 Init_etc(void) 00659 { 00660 VALUE mEtc; 00661 00662 mEtc = rb_define_module("Etc"); 00663 rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0); 00664 00665 rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1); 00666 rb_define_module_function(mEtc, "getpwnam", etc_getpwnam, 1); 00667 rb_define_module_function(mEtc, "setpwent", etc_setpwent, 0); 00668 rb_define_module_function(mEtc, "endpwent", etc_endpwent, 0); 00669 rb_define_module_function(mEtc, "getpwent", etc_getpwent, 0); 00670 rb_define_module_function(mEtc, "passwd", etc_passwd, 0); 00671 00672 rb_define_module_function(mEtc, "getgrgid", etc_getgrgid, -1); 00673 rb_define_module_function(mEtc, "getgrnam", etc_getgrnam, 1); 00674 rb_define_module_function(mEtc, "group", etc_group, 0); 00675 rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0); 00676 rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0); 00677 rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0); 00678 rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0); 00679 rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0); 00680 00681 sPasswd = rb_struct_define("Passwd", 00682 "name", "passwd", "uid", "gid", 00683 #ifdef HAVE_ST_PW_GECOS 00684 "gecos", 00685 #endif 00686 "dir", "shell", 00687 #ifdef HAVE_ST_PW_CHANGE 00688 "change", 00689 #endif 00690 #ifdef HAVE_ST_PW_QUOTA 00691 "quota", 00692 #endif 00693 #ifdef HAVE_ST_PW_AGE 00694 "age", 00695 #endif 00696 #ifdef HAVE_ST_PW_CLASS 00697 "uclass", 00698 #endif 00699 #ifdef HAVE_ST_PW_COMMENT 00700 "comment", 00701 #endif 00702 #ifdef HAVE_ST_PW_EXPIRE 00703 "expire", 00704 #endif 00705 NULL); 00706 /* Define-const: Passwd 00707 * 00708 * Passwd is a Struct that contains the following members: 00709 * 00710 * name:: 00711 * contains the short login name of the user as a String. 00712 * passwd:: 00713 * contains the encrypted password of the user as a String. 00714 * an 'x' is returned if shadow passwords are in use. An '*' is returned 00715 * if the user cannot log in using a password. 00716 * uid:: 00717 * contains the integer user ID (uid) of the user. 00718 * gid:: 00719 * contains the integer group ID (gid) of the user's primary group. 00720 * dir:: 00721 * contains the path to the home directory of the user as a String. 00722 * shell:: 00723 * contains the path to the login shell of the user as a String. 00724 * 00725 * === The following members below are optional, and must be compiled with special flags: 00726 * 00727 * gecos:: 00728 * contains a longer String description of the user, such as 00729 * a full name. Some Unix systems provide structured information in the 00730 * gecos field, but this is system-dependent. 00731 * must be compiled with +HAVE_ST_PW_GECOS+ 00732 * change:: 00733 * password change time(integer) must be compiled with +HAVE_ST_PW_CHANGE+ 00734 * quota:: 00735 * quota value(integer) must be compiled with +HAVE_ST_PW_QUOTA+ 00736 * age:: 00737 * password age(integer) must be compiled with +HAVE_ST_PW_AGE+ 00738 * class:: 00739 * user access class(string) must be compiled with +HAVE_ST_PW_CLASS+ 00740 * comment:: 00741 * comment(string) must be compiled with +HAVE_ST_PW_COMMENT+ 00742 * expire:: 00743 * account expiration time(integer) must be compiled with +HAVE_ST_PW_EXPIRE+ 00744 */ 00745 rb_define_const(mEtc, "Passwd", sPasswd); 00746 rb_extend_object(sPasswd, rb_mEnumerable); 00747 rb_define_singleton_method(sPasswd, "each", etc_each_passwd, 0); 00748 00749 #ifdef HAVE_GETGRENT 00750 sGroup = rb_struct_define("Group", "name", 00751 #ifdef HAVE_ST_GR_PASSWD 00752 "passwd", 00753 #endif 00754 "gid", "mem", NULL); 00755 00756 /* Define-const: Group 00757 * 00758 * Group is a Struct that is only available when compiled with +HAVE_GETGRENT+. 00759 * 00760 * The struct contains the following members: 00761 * 00762 * name:: 00763 * contains the name of the group as a String. 00764 * passwd:: 00765 * contains the encrypted password as a String. An 'x' is 00766 * returned if password access to the group is not available; an empty 00767 * string is returned if no password is needed to obtain membership of 00768 * the group. 00769 * 00770 * Must be compiled with +HAVE_ST_GR_PASSWD+. 00771 * gid:: 00772 * contains the group's numeric ID as an integer. 00773 * mem:: 00774 * is an Array of Strings containing the short login names of the 00775 * members of the group. 00776 */ 00777 rb_define_const(mEtc, "Group", sGroup); 00778 rb_extend_object(sGroup, rb_mEnumerable); 00779 rb_define_singleton_method(sGroup, "each", etc_each_group, 0); 00780 #endif 00781 } 00782