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