~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to ext/etc/etc.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2010-07-31 17:08:39 UTC
  • mfrom: (1.1.4 upstream) (8.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100731170839-j034dmpdqt1cc4p6
Tags: 1.9.2~svn28788-1
* New release based on upstream snapshot from the 1.9.2 branch,
  after 1.9.2 RC2. That branch is (supposed to be) binary-compatible
  with the 1.9.1 branch.
  + Builds fine on i386. Closes: #580852.
* Upgrade to Standards-Version: 3.9.1. No changes needed.
* Updated generated incs.
* Patches that still need work:
  + Unclear status, need more investigation:
   090729_fix_Makefile_deps.dpatch
   090803_exclude_rdoc.dpatch
   203_adjust_base_of_search_path.dpatch
   902_define_YAML_in_yaml_stringio.rb.dpatch
   919_common.mk_tweaks.dpatch
   931_libruby_suffix.dpatch
   940_test_thread_mutex_sync_shorter.dpatch
  + Maybe not needed anymore, keeping but not applying.
   102_skip_test_copy_stream.dpatch (test doesn't block anymore?)
   104_skip_btest_io.dpatch (test doesn't block anymore?)
   201_gem_prelude.dpatch (we don't use that rubygems anyway?)
   202_gem_default_dir.dpatch (we don't use that rubygems anyway?)
   940_test_file_exhaustive_fails_as_root.dpatch
   940_test_priority_fails.dpatch
   100518_load_libc_libm.dpatch
* Add disable-tests.diff: disable some tests that cause failures on FreeBSD.
  Closes: #590002, #543805, #542927.
* However, many new failures on FreeBSD. Since that version is still an
  improvement, add the check that makes test suite failures non-fatal on
  FreeBSD again. That still needs to be investigated.
* Re-add 903_skip_base_ruby_check.dpatch
* Add build-dependency on ruby1.8 and drop all pre-generated files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
  etc.c -
4
4
 
5
 
  $Author: nobu $
 
5
  $Author: naruse $
6
6
  created at: Tue Mar 22 18:39:19 JST 1994
7
7
 
8
8
************************************************/
9
9
 
10
10
#include "ruby.h"
 
11
#include "ruby/encoding.h"
11
12
 
12
13
#include <sys/types.h>
13
14
#ifdef HAVE_UNISTD_H
22
23
#include <grp.h>
23
24
#endif
24
25
 
25
 
#ifndef HAVE_TYPE_UID_T
26
 
#define uid_t int
27
 
#endif
28
 
 
29
26
static VALUE sPasswd;
30
27
#ifdef HAVE_GETGRENT
31
28
static VALUE sGroup;
32
29
#endif
33
30
 
 
31
#ifdef _WIN32
 
32
#include <shlobj.h>
 
33
#ifndef CSIDL_COMMON_APPDATA
 
34
#define CSIDL_COMMON_APPDATA 35
 
35
#endif
 
36
#endif
 
37
 
34
38
#ifndef _WIN32
35
39
char *getenv();
36
40
#endif
124
128
{
125
129
#if defined(HAVE_GETPWENT)
126
130
    VALUE id;
127
 
    uid_t uid;
 
131
    rb_uid_t uid;
128
132
    struct passwd *pwd;
129
133
 
130
134
    rb_secure(4);
137
141
    pwd = getpwuid(uid);
138
142
    if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", (int)uid);
139
143
    return setup_passwd(pwd);
140
 
#else 
 
144
#else
141
145
    return Qnil;
142
146
#endif
143
147
}
160
164
    pwd = getpwnam(RSTRING_PTR(nam));
161
165
    if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %s", RSTRING_PTR(nam));
162
166
    return setup_passwd(pwd);
163
 
#else 
 
167
#else
164
168
    return Qnil;
165
169
#endif
166
170
}
170
174
static VALUE
171
175
passwd_ensure(void)
172
176
{
173
 
    passwd_blocking = Qfalse;
 
177
    passwd_blocking = (int)Qfalse;
174
178
    return Qnil;
175
179
}
176
180
 
186
190
    endpwent();
187
191
    return Qnil;
188
192
}
 
193
 
 
194
static void
 
195
each_passwd(void)
 
196
{
 
197
    if (passwd_blocking) {
 
198
        rb_raise(rb_eRuntimeError, "parallel passwd iteration");
 
199
    }
 
200
    passwd_blocking = (int)Qtrue;
 
201
    rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
 
202
}
189
203
#endif
190
204
 
191
 
/* Provides a convenient Ruby iterator which executes a block for each entry 
 
205
/* Provides a convenient Ruby iterator which executes a block for each entry
192
206
 * in the /etc/passwd file.
193
207
 *
194
 
 * The code block is passed an Struct::Passwd struct; see getpwent above for 
 
208
 * The code block is passed an Struct::Passwd struct; see getpwent above for
195
209
 * details.
196
210
 *
197
211
 * Example:
211
225
 
212
226
    rb_secure(4);
213
227
    if (rb_block_given_p()) {
214
 
        if (passwd_blocking) {
215
 
            rb_raise(rb_eRuntimeError, "parallel passwd iteration");
216
 
        }
217
 
        passwd_blocking = Qtrue;
218
 
        rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
 
228
        each_passwd();
219
229
    }
220
 
    if (pw = getpwent()) {
 
230
    else if (pw = getpwent()) {
221
231
        return setup_passwd(pw);
222
232
    }
223
233
#endif
224
234
    return Qnil;
225
235
}
226
236
 
 
237
/* Iterates for each entry in the /etc/passwd file if a block is given.
 
238
 * If no block is given, returns the enumerator.
 
239
 *
 
240
 * The code block is passed an Struct::Passwd struct; see getpwent above for
 
241
 * details.
 
242
 *
 
243
 * Example:
 
244
 *
 
245
 *     require 'etc'
 
246
 *
 
247
 *     Etc::Passwd.each {|u|
 
248
 *       puts u.name + " = " + u.gecos
 
249
 *     }
 
250
 *
 
251
 *     Etc::Passwd.collect {|u| u.gecos}
 
252
 *     Etc::Passwd.collect {|u| u.gecos}
 
253
 *
 
254
 */
 
255
static VALUE
 
256
etc_each_passwd(VALUE obj)
 
257
{
 
258
#ifdef HAVE_GETPWENT
 
259
    RETURN_ENUMERATOR(obj, 0, 0);
 
260
    each_passwd();
 
261
#endif
 
262
    return obj;
 
263
}
 
264
 
227
265
/* Resets the process of reading the /etc/passwd file, so that the next call
228
266
 * to getpwent will return the first entry again.
229
267
 */
249
287
}
250
288
 
251
289
/* Returns an entry from the /etc/passwd file. The first time it is called it
252
 
 * opens the file and returns the first entry; each successive call returns 
 
290
 * opens the file and returns the first entry; each successive call returns
253
291
 * the next entry, or nil if the end of the file has been reached.
254
292
 *
255
293
 * To close the file when processing is complete, call endpwent.
266
304
 *
267
305
 * - Passwd#gid contains the integer group ID (gid) of the user's primary group.
268
306
 *
269
 
 * - Passwd#gecos contains a longer String description of the user, such as 
270
 
 *   a full name. Some Unix systems provide structured information in the 
 
307
 * - Passwd#gecos contains a longer String description of the user, such as
 
308
 *   a full name. Some Unix systems provide structured information in the
271
309
 *   gecos field, but this is system-dependent.
272
310
 *
273
311
 * - Passwd#dir contains the path to the home directory of the user as a String.
310
348
}
311
349
#endif
312
350
 
313
 
/* Returns information about the group with specified integer group id (gid), 
 
351
/* Returns information about the group with specified integer group id (gid),
314
352
 * as found in /etc/group.
315
353
 *
316
354
 * The information is returned as a Struct::Group; see getgrent above for
343
381
#endif
344
382
}
345
383
 
346
 
/* Returns information about the group with specified String name, as found 
 
384
/* Returns information about the group with specified String name, as found
347
385
 * in /etc/group.
348
386
 *
349
387
 * The information is returned as a Struct::Group; see getgrent above for
374
412
static VALUE
375
413
group_ensure(void)
376
414
{
377
 
    group_blocking = Qfalse;
 
415
    group_blocking = (int)Qfalse;
378
416
    return Qnil;
379
417
}
380
418
 
390
428
    endgrent();
391
429
    return Qnil;
392
430
}
 
431
 
 
432
static void
 
433
each_group(void)
 
434
{
 
435
    if (group_blocking) {
 
436
        rb_raise(rb_eRuntimeError, "parallel group iteration");
 
437
    }
 
438
    group_blocking = (int)Qtrue;
 
439
    rb_ensure(group_iterate, 0, group_ensure, 0);
 
440
}
393
441
#endif
394
442
 
395
 
/* Provides a convenient Ruby iterator which executes a block for each entry 
 
443
/* Provides a convenient Ruby iterator which executes a block for each entry
396
444
 * in the /etc/group file.
397
445
 *
398
 
 * The code block is passed an Struct::Group struct; see getgrent above for 
 
446
 * The code block is passed an Struct::Group struct; see getgrent above for
399
447
 * details.
400
448
 *
401
449
 * Example:
415
463
 
416
464
    rb_secure(4);
417
465
    if (rb_block_given_p()) {
418
 
        if (group_blocking) {
419
 
            rb_raise(rb_eRuntimeError, "parallel group iteration");
420
 
        }
421
 
        group_blocking = Qtrue;
422
 
        rb_ensure(group_iterate, 0, group_ensure, 0);
 
466
        each_group();
423
467
    }
424
 
    if (grp = getgrent()) {
 
468
    else if (grp = getgrent()) {
425
469
        return setup_group(grp);
426
470
    }
427
471
#endif
428
472
    return Qnil;
429
473
}
430
474
 
 
475
#ifdef HAVE_GETGRENT
 
476
/* Iterates for each entry in the /etc/group file if a block is given.
 
477
 * If no block is given, returns the enumerator.
 
478
 *
 
479
 * The code block is passed an Struct::Group struct; see getpwent above for
 
480
 * details.
 
481
 *
 
482
 * Example:
 
483
 *
 
484
 *     require 'etc'
 
485
 *
 
486
 *     Etc::Group.each {|g|
 
487
 *       puts g.name + ": " + g.mem.join(', ')
 
488
 *     }
 
489
 *
 
490
 *     Etc::Group.collect {|g| g.name}
 
491
 *     Etc::Group.select {|g| !g.mem.empty?}
 
492
 *
 
493
 */
 
494
static VALUE
 
495
etc_each_group(VALUE obj)
 
496
{
 
497
    RETURN_ENUMERATOR(obj, 0, 0);
 
498
    each_group();
 
499
    return obj;
 
500
}
 
501
#endif
 
502
 
431
503
/* Resets the process of reading the /etc/group file, so that the next call
432
504
 * to getgrent will return the first entry again.
433
505
 */
440
512
    return Qnil;
441
513
}
442
514
 
443
 
/* Ends the process of scanning through the /etc/group file begun by 
 
515
/* Ends the process of scanning through the /etc/group file begun by
444
516
 * getgrent, and closes the file.
445
517
 */
446
518
static VALUE
453
525
}
454
526
 
455
527
/* Returns an entry from the /etc/group file. The first time it is called it
456
 
 * opens the file and returns the first entry; each successive call returns 
 
528
 * opens the file and returns the first entry; each successive call returns
457
529
 * the next entry, or nil if the end of the file has been reached.
458
530
 *
459
531
 * To close the file when processing is complete, call endgrent.
463
535
 * - Group#name contains the name of the group as a String.
464
536
 *
465
537
 * - Group#passwd contains the encrypted password as a String. An 'x' is
466
 
 *   returned if password access to the group is not available; an empty 
467
 
 *   string is returned if no password is needed to obtain membership of 
 
538
 *   returned if password access to the group is not available; an empty
 
539
 *   string is returned if no password is needed to obtain membership of
468
540
 *   the group.
469
541
 *
470
542
 * - Group#gid contains the group's numeric ID as an integer.
471
543
 *
472
 
 * - Group#mem is an Array of Strings containing the short login names of the 
 
544
 * - Group#mem is an Array of Strings containing the short login names of the
473
545
 *   members of the group.
474
546
 */
475
547
static VALUE
485
557
    return Qnil;
486
558
}
487
559
 
488
 
/* The etc module provides access to information from the /etc/passwd and
489
 
 * /etc/group files on Linux and Unix systems.
 
560
#define numberof(array) (sizeof(array) / sizeof(*array))
 
561
 
 
562
#ifdef _WIN32
 
563
VALUE rb_w32_special_folder(int type);
 
564
UINT rb_w32_system_tmpdir(WCHAR *path, UINT len);
 
565
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
 
566
#endif
 
567
 
 
568
/*
 
569
 * Returns system configuration directory.
 
570
 */
 
571
static VALUE
 
572
etc_sysconfdir(VALUE obj)
 
573
{
 
574
#ifdef _WIN32
 
575
    return rb_w32_special_folder(CSIDL_COMMON_APPDATA);
 
576
#else
 
577
    return rb_filesystem_str_new_cstr(SYSCONFDIR);
 
578
#endif
 
579
}
 
580
 
 
581
/*
 
582
 * Returns system temporary directory.
 
583
 */
 
584
static VALUE
 
585
etc_systmpdir(void)
 
586
{
 
587
#ifdef _WIN32
 
588
    WCHAR path[_MAX_PATH];
 
589
    UINT len = rb_w32_system_tmpdir(path, numberof(path));
 
590
    if (!len) return Qnil;
 
591
    return rb_w32_conv_from_wchar(path, rb_filesystem_encoding());
 
592
#else
 
593
    return rb_filesystem_str_new_cstr("/tmp");
 
594
#endif
 
595
}
 
596
 
 
597
/*
 
598
 * The etc module provides access to information from the running OS.
490
599
 *
491
600
 * Documented by mathew <meta@pobox.com>.
492
601
 */
511
620
    rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0);
512
621
    rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
513
622
    rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
 
623
    rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
 
624
    rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
514
625
 
515
626
    sPasswd =  rb_struct_define("Passwd",
516
627
                                "name", "passwd", "uid", "gid",
538
649
#endif
539
650
                                NULL);
540
651
    rb_define_const(mEtc, "Passwd", sPasswd);
 
652
    rb_extend_object(sPasswd, rb_mEnumerable);
 
653
    rb_define_singleton_method(sPasswd, "each", etc_each_passwd, 0);
541
654
 
542
655
#ifdef HAVE_GETGRENT
543
656
    sGroup = rb_struct_define("Group", "name",
547
660
                              "gid", "mem", NULL);
548
661
 
549
662
    rb_define_const(mEtc, "Group", sGroup);
 
663
    rb_extend_object(sGroup, rb_mEnumerable);
 
664
    rb_define_singleton_method(sGroup, "each", etc_each_group, 0);
550
665
#endif
551
666
}