ext/etc/etc.c

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

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7