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
00051
00052
00053
00054
00055
00056
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
00134 );
00135 }
00136 #endif
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
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
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
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
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
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
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
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
00311
00312
00313 static VALUE
00314 etc_setpwent(VALUE obj)
00315 {
00316 #ifdef HAVE_GETPWENT
00317 setpwent();
00318 #endif
00319 return Qnil;
00320 }
00321
00322
00323
00324
00325 static VALUE
00326 etc_endpwent(VALUE obj)
00327 {
00328 #ifdef HAVE_GETPWENT
00329 endpwent();
00330 #endif
00331 return Qnil;
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
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
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
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
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
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
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
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
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
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
00549
00550
00551 static VALUE
00552 etc_setgrent(VALUE obj)
00553 {
00554 #ifdef HAVE_GETGRENT
00555 setgrent();
00556 #endif
00557 return Qnil;
00558 }
00559
00560
00561
00562
00563 static VALUE
00564 etc_endgrent(VALUE obj)
00565 {
00566 #ifdef HAVE_GETGRENT
00567 endgrent();
00568 #endif
00569 return Qnil;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
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
00605
00606
00607
00608
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
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
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
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
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 rb_define_const(mEtc, "Passwd", sPasswd);
00761 #endif
00762 rb_define_const(rb_cStruct, "Passwd", sPasswd);
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
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 rb_define_const(mEtc, "Group", sGroup);
00796 #endif
00797 rb_define_const(rb_cStruct, "Group", sGroup);
00798 rb_extend_object(sGroup, rb_mEnumerable);
00799 rb_define_singleton_method(sGroup, "each", etc_each_group, 0);
00800 #endif
00801 }
00802