1 /************************************************
6 $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
7 created at: Tue Mar 22 18:39:19 JST 1994
9 ************************************************/
13 #include <sys/types.h>
26 #ifndef HAVE_TYPE_UID_T
30 static VALUE sPasswd
, sGroup
;
37 /* Returns the short user name of the currently logged in user.
40 * Etc.getlogin -> 'guest'
51 if (!login
) login
= getenv("USER");
53 login
= getenv("USER");
57 return rb_tainted_str_new2(login
);
61 #if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
66 if (str
== 0) str
= "";
67 return rb_tainted_str_new2(str
);
76 if (pwd
== 0) rb_sys_fail("/etc/passwd");
77 return rb_struct_new(sPasswd
,
78 safe_setup_str(pwd
->pw_name
),
79 #ifdef HAVE_ST_PW_PASSWD
80 safe_setup_str(pwd
->pw_passwd
),
82 PW_UID2VAL(pwd
->pw_uid
),
83 PW_GID2VAL(pwd
->pw_gid
),
84 #ifdef HAVE_ST_PW_GECOS
85 safe_setup_str(pwd
->pw_gecos
),
87 safe_setup_str(pwd
->pw_dir
),
88 safe_setup_str(pwd
->pw_shell
),
89 #ifdef HAVE_ST_PW_CHANGE
90 INT2NUM(pwd
->pw_change
),
92 #ifdef HAVE_ST_PW_QUOTA
93 INT2NUM(pwd
->pw_quota
),
96 PW_AGE2VAL(pwd
->pw_age
),
98 #ifdef HAVE_ST_PW_CLASS
99 safe_setup_str(pwd
->pw_class
),
101 #ifdef HAVE_ST_PW_COMMENT
102 safe_setup_str(pwd
->pw_comment
),
104 #ifdef HAVE_ST_PW_EXPIRE
105 INT2NUM(pwd
->pw_expire
),
112 /* Returns the /etc/passwd information for the user with specified integer
115 * The information is returned as a Struct::Passwd; see getpwent above for
118 * e.g. * Etc.getpwuid(0) -> #<struct Struct::Passwd name="root",
119 * passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
122 etc_getpwuid(argc
, argv
, obj
)
127 #if defined(HAVE_GETPWENT)
133 if (rb_scan_args(argc
, argv
, "01", &id
) == 1) {
134 uid
= PW_VAL2UID(id
);
140 if (pwd
== 0) rb_raise(rb_eArgError
, "can't find user for %d", uid
);
141 return setup_passwd(pwd
);
147 /* Returns the /etc/passwd information for the user with specified login name.
149 * The information is returned as a Struct::Passwd; see getpwent above for
152 * e.g. * Etc.getpwnam('root') -> #<struct Struct::Passwd name="root",
153 * passwd="x", uid=0, gid=0, gecos="root",dir="/root", shell="/bin/bash">
156 etc_getpwnam(obj
, nam
)
162 SafeStringValue(nam
);
163 pwd
= getpwnam(RSTRING(nam
)->ptr
);
164 if (pwd
== 0) rb_raise(rb_eArgError
, "can't find user for %s", RSTRING(nam
)->ptr
);
165 return setup_passwd(pwd
);
172 static int passwd_blocking
= 0;
176 passwd_blocking
= Qfalse
;
186 while (pw
= getpwent()) {
187 rb_yield(setup_passwd(pw
));
194 /* Provides a convenient Ruby iterator which executes a block for each entry
195 * in the /etc/passwd file.
197 * The code block is passed an Etc::Passwd struct; see getpwent above for
205 * puts u.name + " = " + u.gecos
217 if (rb_block_given_p()) {
218 if (passwd_blocking
) {
219 rb_raise(rb_eRuntimeError
, "parallel passwd iteration");
221 passwd_blocking
= Qtrue
;
222 rb_ensure(passwd_iterate
, 0, passwd_ensure
, 0);
224 if (pw
= getpwent()) {
225 return setup_passwd(pw
);
231 /* Resets the process of reading the /etc/passwd file, so that the next call
232 * to getpwent will return the first entry again.
244 /* Ends the process of scanning through the /etc/passwd file begun with
245 * getpwent, and closes the file.
257 /* Returns an entry from the /etc/passwd file. The first time it is called it
258 * opens the file and returns the first entry; each successive call returns
259 * the next entry, or nil if the end of the file has been reached.
261 * To close the file when processing is complete, call endpwent.
263 * Each entry is returned as a Struct::Passwd:
265 * - Passwd#name contains the short login name of the user as a String.
267 * - Passwd#passwd contains the encrypted password of the user as a String.
268 * an 'x' is returned if shadow passwords are in use. An '*' is returned
269 * if the user cannot log in using a password.
271 * - Passwd#uid contains the integer user ID (uid) of the user.
273 * - Passwd#gid contains the integer group ID (gid) of the user's primary group.
275 * - Passwd#gecos contains a longer String description of the user, such as
276 * a full name. Some Unix systems provide structured information in the
277 * gecos field, but this is system-dependent.
279 * - Passwd#dir contains the path to the home directory of the user as a String.
281 * - Passwd#shell contains the path to the login shell of the user as a String.
290 if (pw
= getpwent()) {
291 return setup_passwd(pw
);
308 rb_ary_push(mem
, safe_setup_str(*tbl
));
311 return rb_struct_new(sGroup
,
312 safe_setup_str(grp
->gr_name
),
313 #ifdef HAVE_ST_GR_PASSWD
314 safe_setup_str(grp
->gr_passwd
),
316 PW_GID2VAL(grp
->gr_gid
),
321 /* Returns information about the group with specified integer group id (gid),
322 * as found in /etc/group.
324 * The information is returned as a Struct::Group; see getgrent above for
327 * e.g. Etc.getgrgid(100) -> #<struct Struct::Group name="users", passwd="x",
328 * gid=100, mem=["meta", "root"]>
332 etc_getgrgid(obj
, id
)
342 if (grp
== 0) rb_raise(rb_eArgError
, "can't find group for %d", gid
);
343 return setup_group(grp
);
349 /* Returns information about the group with specified String name, as found
352 * The information is returned as a Struct::Group; see getgrent above for
355 * e.g. Etc.getgrnam('users') -> #<struct Struct::Group name="users",
356 * passwd="x", gid=100, mem=["meta", "root"]>
360 etc_getgrnam(obj
, nam
)
367 SafeStringValue(nam
);
368 grp
= getgrnam(RSTRING(nam
)->ptr
);
369 if (grp
== 0) rb_raise(rb_eArgError
, "can't find group for %s", RSTRING(nam
)->ptr
);
370 return setup_group(grp
);
377 static int group_blocking
= 0;
381 group_blocking
= Qfalse
;
391 while (pw
= getgrent()) {
392 rb_yield(setup_group(pw
));
399 /* Provides a convenient Ruby iterator which executes a block for each entry
400 * in the /etc/group file.
402 * The code block is passed an Etc::Group struct; see getgrent above for
410 * puts g.name + ": " + g.mem.join(', ')
422 if (rb_block_given_p()) {
423 if (group_blocking
) {
424 rb_raise(rb_eRuntimeError
, "parallel group iteration");
426 group_blocking
= Qtrue
;
427 rb_ensure(group_iterate
, 0, group_ensure
, 0);
429 if (grp
= getgrent()) {
430 return setup_group(grp
);
436 /* Resets the process of reading the /etc/group file, so that the next call
437 * to getgrent will return the first entry again.
449 /* Ends the process of scanning through the /etc/group file begun by
450 * getgrent, and closes the file.
462 /* Returns an entry from the /etc/group file. The first time it is called it
463 * opens the file and returns the first entry; each successive call returns
464 * the next entry, or nil if the end of the file has been reached.
466 * To close the file when processing is complete, call endgrent.
468 * Each entry is returned as a Struct::Group:
470 * - Group#name contains the name of the group as a String.
472 * - Group#passwd contains the encrypted password as a String. An 'x' is
473 * returned if password access to the group is not available; an empty
474 * string is returned if no password is needed to obtain membership of
477 * - Group#gid contains the group's numeric ID as an integer.
479 * - Group#mem is an Array of Strings containing the short login names of the
480 * members of the group.
489 if (gr
= getgrent()) {
490 return setup_group(gr
);
498 /* The etc module provides access to information from the /etc/passwd and
499 * /etc/group files on Linux and Unix systems.
501 * Documented by mathew <meta@pobox.com>.
506 mEtc
= rb_define_module("Etc");
508 rb_define_module_function(mEtc
, "getlogin", etc_getlogin
, 0);
510 rb_define_module_function(mEtc
, "getpwuid", etc_getpwuid
, -1);
511 rb_define_module_function(mEtc
, "getpwnam", etc_getpwnam
, 1);
512 rb_define_module_function(mEtc
, "setpwent", etc_setpwent
, 0);
513 rb_define_module_function(mEtc
, "endpwent", etc_endpwent
, 0);
514 rb_define_module_function(mEtc
, "getpwent", etc_getpwent
, 0);
515 rb_define_module_function(mEtc
, "passwd", etc_passwd
, 0);
517 rb_define_module_function(mEtc
, "getgrgid", etc_getgrgid
, 1);
518 rb_define_module_function(mEtc
, "getgrnam", etc_getgrnam
, 1);
519 rb_define_module_function(mEtc
, "group", etc_group
, 0);
520 rb_define_module_function(mEtc
, "setgrent", etc_setgrent
, 0);
521 rb_define_module_function(mEtc
, "endgrent", etc_endgrent
, 0);
522 rb_define_module_function(mEtc
, "getgrent", etc_getgrent
, 0);
524 rb_global_variable(&sPasswd
);
525 sPasswd
= rb_struct_define("Passwd",
526 "name", "passwd", "uid", "gid",
527 #ifdef HAVE_ST_PW_GECOS
531 #ifdef HAVE_ST_PW_CHANGE
534 #ifdef HAVE_ST_PW_QUOTA
537 #ifdef HAVE_ST_PW_AGE
540 #ifdef HAVE_ST_PW_CLASS
543 #ifdef HAVE_ST_PW_COMMENT
546 #ifdef HAVE_ST_PW_EXPIRE
552 rb_global_variable(&sGroup
);
553 sGroup
= rb_struct_define("Group", "name",
554 #ifdef HAVE_ST_GR_PASSWD