00001
00002
00003
00004
00005
00006
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
00044
00045
00046
00047
00048
00049
00050 static VALUE
00051 etc_getlogin(VALUE obj)
00052 {
00053 char *login;
00054
00055 rb_secure(4);
00056 #ifdef HAVE_GETLOGIN
00057 login = getlogin();
00058 if (!login) login = getenv("USER");
00059 #else
00060 login = getenv("USER");
00061 #endif
00062
00063 if (login)
00064 return rb_tainted_str_new2(login);
00065 return Qnil;
00066 }
00067
00068 #if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
00069 static VALUE
00070 safe_setup_str(const char *str)
00071 {
00072 if (str == 0) str = "";
00073 return rb_tainted_str_new2(str);
00074 }
00075 #endif
00076
00077 #ifdef HAVE_GETPWENT
00078 static VALUE
00079 setup_passwd(struct passwd *pwd)
00080 {
00081 if (pwd == 0) rb_sys_fail("/etc/passwd");
00082 return rb_struct_new(sPasswd,
00083 safe_setup_str(pwd->pw_name),
00084 #ifdef HAVE_ST_PW_PASSWD
00085 safe_setup_str(pwd->pw_passwd),
00086 #endif
00087 UIDT2NUM(pwd->pw_uid),
00088 GIDT2NUM(pwd->pw_gid),
00089 #ifdef HAVE_ST_PW_GECOS
00090 safe_setup_str(pwd->pw_gecos),
00091 #endif
00092 safe_setup_str(pwd->pw_dir),
00093 safe_setup_str(pwd->pw_shell),
00094 #ifdef HAVE_ST_PW_CHANGE
00095 INT2NUM(pwd->pw_change),
00096 #endif
00097 #ifdef HAVE_ST_PW_QUOTA
00098 INT2NUM(pwd->pw_quota),
00099 #endif
00100 #ifdef HAVE_ST_PW_AGE
00101 PW_AGE2VAL(pwd->pw_age),
00102 #endif
00103 #ifdef HAVE_ST_PW_CLASS
00104 safe_setup_str(pwd->pw_class),
00105 #endif
00106 #ifdef HAVE_ST_PW_COMMENT
00107 safe_setup_str(pwd->pw_comment),
00108 #endif
00109 #ifdef HAVE_ST_PW_EXPIRE
00110 INT2NUM(pwd->pw_expire),
00111 #endif
00112 0
00113 );
00114 }
00115 #endif
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 static VALUE
00127 etc_getpwuid(int argc, VALUE *argv, VALUE obj)
00128 {
00129 #if defined(HAVE_GETPWENT)
00130 VALUE id;
00131 rb_uid_t uid;
00132 struct passwd *pwd;
00133
00134 rb_secure(4);
00135 if (rb_scan_args(argc, argv, "01", &id) == 1) {
00136 uid = NUM2UIDT(id);
00137 }
00138 else {
00139 uid = getuid();
00140 }
00141 pwd = getpwuid(uid);
00142 if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", (int)uid);
00143 return setup_passwd(pwd);
00144 #else
00145 return Qnil;
00146 #endif
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 static VALUE
00158 etc_getpwnam(VALUE obj, VALUE nam)
00159 {
00160 #ifdef HAVE_GETPWENT
00161 struct passwd *pwd;
00162
00163 SafeStringValue(nam);
00164 pwd = getpwnam(RSTRING_PTR(nam));
00165 if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %s", RSTRING_PTR(nam));
00166 return setup_passwd(pwd);
00167 #else
00168 return Qnil;
00169 #endif
00170 }
00171
00172 #ifdef HAVE_GETPWENT
00173 static int passwd_blocking = 0;
00174 static VALUE
00175 passwd_ensure(void)
00176 {
00177 passwd_blocking = (int)Qfalse;
00178 return Qnil;
00179 }
00180
00181 static VALUE
00182 passwd_iterate(void)
00183 {
00184 struct passwd *pw;
00185
00186 setpwent();
00187 while (pw = getpwent()) {
00188 rb_yield(setup_passwd(pw));
00189 }
00190 endpwent();
00191 return Qnil;
00192 }
00193
00194 static void
00195 each_passwd(void)
00196 {
00197 if (passwd_blocking) {
00198 rb_raise(rb_eRuntimeError, "parallel passwd iteration");
00199 }
00200 passwd_blocking = (int)Qtrue;
00201 rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
00202 }
00203 #endif
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 static VALUE
00221 etc_passwd(VALUE obj)
00222 {
00223 #ifdef HAVE_GETPWENT
00224 struct passwd *pw;
00225
00226 rb_secure(4);
00227 if (rb_block_given_p()) {
00228 each_passwd();
00229 }
00230 else if (pw = getpwent()) {
00231 return setup_passwd(pw);
00232 }
00233 #endif
00234 return Qnil;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 static VALUE
00256 etc_each_passwd(VALUE obj)
00257 {
00258 #ifdef HAVE_GETPWENT
00259 RETURN_ENUMERATOR(obj, 0, 0);
00260 each_passwd();
00261 #endif
00262 return obj;
00263 }
00264
00265
00266
00267
00268 static VALUE
00269 etc_setpwent(VALUE obj)
00270 {
00271 #ifdef HAVE_GETPWENT
00272 setpwent();
00273 #endif
00274 return Qnil;
00275 }
00276
00277
00278
00279
00280 static VALUE
00281 etc_endpwent(VALUE obj)
00282 {
00283 #ifdef HAVE_GETPWENT
00284 endpwent();
00285 #endif
00286 return Qnil;
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 static VALUE
00316 etc_getpwent(VALUE obj)
00317 {
00318 #ifdef HAVE_GETPWENT
00319 struct passwd *pw;
00320
00321 if (pw = getpwent()) {
00322 return setup_passwd(pw);
00323 }
00324 #endif
00325 return Qnil;
00326 }
00327
00328 #ifdef HAVE_GETGRENT
00329 static VALUE
00330 setup_group(struct group *grp)
00331 {
00332 VALUE mem;
00333 char **tbl;
00334
00335 mem = rb_ary_new();
00336 tbl = grp->gr_mem;
00337 while (*tbl) {
00338 rb_ary_push(mem, safe_setup_str(*tbl));
00339 tbl++;
00340 }
00341 return rb_struct_new(sGroup,
00342 safe_setup_str(grp->gr_name),
00343 #ifdef HAVE_ST_GR_PASSWD
00344 safe_setup_str(grp->gr_passwd),
00345 #endif
00346 GIDT2NUM(grp->gr_gid),
00347 mem);
00348 }
00349 #endif
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 static VALUE
00362 etc_getgrgid(int argc, VALUE *argv, VALUE obj)
00363 {
00364 #ifdef HAVE_GETGRENT
00365 VALUE id;
00366 gid_t gid;
00367 struct group *grp;
00368
00369 rb_secure(4);
00370 if (rb_scan_args(argc, argv, "01", &id) == 1) {
00371 gid = NUM2GIDT(id);
00372 }
00373 else {
00374 gid = getgid();
00375 }
00376 grp = getgrgid(gid);
00377 if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", (int)gid);
00378 return setup_group(grp);
00379 #else
00380 return Qnil;
00381 #endif
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 static VALUE
00395 etc_getgrnam(VALUE obj, VALUE nam)
00396 {
00397 #ifdef HAVE_GETGRENT
00398 struct group *grp;
00399
00400 rb_secure(4);
00401 SafeStringValue(nam);
00402 grp = getgrnam(RSTRING_PTR(nam));
00403 if (grp == 0) rb_raise(rb_eArgError, "can't find group for %s", RSTRING_PTR(nam));
00404 return setup_group(grp);
00405 #else
00406 return Qnil;
00407 #endif
00408 }
00409
00410 #ifdef HAVE_GETGRENT
00411 static int group_blocking = 0;
00412 static VALUE
00413 group_ensure(void)
00414 {
00415 group_blocking = (int)Qfalse;
00416 return Qnil;
00417 }
00418
00419 static VALUE
00420 group_iterate(void)
00421 {
00422 struct group *pw;
00423
00424 setgrent();
00425 while (pw = getgrent()) {
00426 rb_yield(setup_group(pw));
00427 }
00428 endgrent();
00429 return Qnil;
00430 }
00431
00432 static void
00433 each_group(void)
00434 {
00435 if (group_blocking) {
00436 rb_raise(rb_eRuntimeError, "parallel group iteration");
00437 }
00438 group_blocking = (int)Qtrue;
00439 rb_ensure(group_iterate, 0, group_ensure, 0);
00440 }
00441 #endif
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 static VALUE
00459 etc_group(VALUE obj)
00460 {
00461 #ifdef HAVE_GETGRENT
00462 struct group *grp;
00463
00464 rb_secure(4);
00465 if (rb_block_given_p()) {
00466 each_group();
00467 }
00468 else if (grp = getgrent()) {
00469 return setup_group(grp);
00470 }
00471 #endif
00472 return Qnil;
00473 }
00474
00475 #ifdef HAVE_GETGRENT
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 static VALUE
00495 etc_each_group(VALUE obj)
00496 {
00497 RETURN_ENUMERATOR(obj, 0, 0);
00498 each_group();
00499 return obj;
00500 }
00501 #endif
00502
00503
00504
00505
00506 static VALUE
00507 etc_setgrent(VALUE obj)
00508 {
00509 #ifdef HAVE_GETGRENT
00510 setgrent();
00511 #endif
00512 return Qnil;
00513 }
00514
00515
00516
00517
00518 static VALUE
00519 etc_endgrent(VALUE obj)
00520 {
00521 #ifdef HAVE_GETGRENT
00522 endgrent();
00523 #endif
00524 return Qnil;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 static VALUE
00548 etc_getgrent(VALUE obj)
00549 {
00550 #ifdef HAVE_GETGRENT
00551 struct group *gr;
00552
00553 if (gr = getgrent()) {
00554 return setup_group(gr);
00555 }
00556 #endif
00557 return Qnil;
00558 }
00559
00560 #define numberof(array) (sizeof(array) / sizeof(*array))
00561
00562 #ifdef _WIN32
00563 VALUE rb_w32_special_folder(int type);
00564 UINT rb_w32_system_tmpdir(WCHAR *path, UINT len);
00565 VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
00566 #endif
00567
00568
00569
00570
00571 static VALUE
00572 etc_sysconfdir(VALUE obj)
00573 {
00574 #ifdef _WIN32
00575 return rb_w32_special_folder(CSIDL_COMMON_APPDATA);
00576 #else
00577 return rb_filesystem_str_new_cstr(SYSCONFDIR);
00578 #endif
00579 }
00580
00581
00582
00583
00584 static VALUE
00585 etc_systmpdir(void)
00586 {
00587 #ifdef _WIN32
00588 WCHAR path[_MAX_PATH];
00589 UINT len = rb_w32_system_tmpdir(path, numberof(path));
00590 if (!len) return Qnil;
00591 return rb_w32_conv_from_wchar(path, rb_filesystem_encoding());
00592 #else
00593 return rb_filesystem_str_new_cstr("/tmp");
00594 #endif
00595 }
00596
00597
00598
00599
00600
00601
00602 void
00603 Init_etc(void)
00604 {
00605 VALUE mEtc;
00606
00607 mEtc = rb_define_module("Etc");
00608 rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0);
00609
00610 rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1);
00611 rb_define_module_function(mEtc, "getpwnam", etc_getpwnam, 1);
00612 rb_define_module_function(mEtc, "setpwent", etc_setpwent, 0);
00613 rb_define_module_function(mEtc, "endpwent", etc_endpwent, 0);
00614 rb_define_module_function(mEtc, "getpwent", etc_getpwent, 0);
00615 rb_define_module_function(mEtc, "passwd", etc_passwd, 0);
00616
00617 rb_define_module_function(mEtc, "getgrgid", etc_getgrgid, -1);
00618 rb_define_module_function(mEtc, "getgrnam", etc_getgrnam, 1);
00619 rb_define_module_function(mEtc, "group", etc_group, 0);
00620 rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0);
00621 rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
00622 rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
00623 rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
00624 rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
00625
00626 sPasswd = rb_struct_define("Passwd",
00627 "name", "passwd", "uid", "gid",
00628 #ifdef HAVE_ST_PW_GECOS
00629 "gecos",
00630 #endif
00631 "dir", "shell",
00632 #ifdef HAVE_ST_PW_CHANGE
00633 "change",
00634 #endif
00635 #ifdef HAVE_ST_PW_QUOTA
00636 "quota",
00637 #endif
00638 #ifdef HAVE_ST_PW_AGE
00639 "age",
00640 #endif
00641 #ifdef HAVE_ST_PW_CLASS
00642 "uclass",
00643 #endif
00644 #ifdef HAVE_ST_PW_COMMENT
00645 "comment",
00646 #endif
00647 #ifdef HAVE_ST_PW_EXPIRE
00648 "expire",
00649 #endif
00650 NULL);
00651 rb_define_const(mEtc, "Passwd", sPasswd);
00652 rb_extend_object(sPasswd, rb_mEnumerable);
00653 rb_define_singleton_method(sPasswd, "each", etc_each_passwd, 0);
00654
00655 #ifdef HAVE_GETGRENT
00656 sGroup = rb_struct_define("Group", "name",
00657 #ifdef HAVE_ST_GR_PASSWD
00658 "passwd",
00659 #endif
00660 "gid", "mem", NULL);
00661
00662 rb_define_const(mEtc, "Group", sGroup);
00663 rb_extend_object(sGroup, rb_mEnumerable);
00664 rb_define_singleton_method(sGroup, "each", etc_each_group, 0);
00665 #endif
00666 }
00667