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