diff options
author | Tom Wyant <unknown> | 2008-05-11 07:40:04 -0700 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2008-05-18 08:00:24 +0000 |
commit | 0d7a9d9f455e176eb389f4d5d28bec38cd9fb15d (patch) | |
tree | a717e445abfae361a49fc5f8196ed6a684050e0a /t/op/pwent.t | |
parent | b0fdf69ec50f40b936b80fb258d82bfc8e867346 (diff) | |
download | perl-0d7a9d9f455e176eb389f4d5d28bec38cd9fb15d.tar.gz |
[perl #53500] op/pwent.t should use the DirectoryService on OS X
From: "Tom Wyant via RT" <perlbug-followup@perl.org>
Message-ID: <rt-3.6.HEAD-20841-1210542001-412.53500-15-0@perl.org>
p4raw-id: //depot/perl@33850
Diffstat (limited to 't/op/pwent.t')
-rwxr-xr-x | t/op/pwent.t | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/t/op/pwent.t b/t/op/pwent.t index 3303f3e41e..9653c6baec 100755 --- a/t/op/pwent.t +++ b/t/op/pwent.t @@ -41,6 +41,71 @@ BEGIN { } } + if (not defined $where && # Try dscl + $Config{useperlio} eq 'define') { # need perlio + + # Map dscl items to passwd fields, and provide support for + # mucking with the dscl output if we need to (and we do). + my %want = do { + my $inx = 0; + map {$_ => {inx => $inx++, mung => sub {$_[0]}}} + qw{RecordName Password UniqueID PrimaryGroupID + RealName NFSHomeDirectory UserShell}; + }; + + # The RecordName for a /User record is the username. In some + # cases there are synonyms (e.g. _www and www), in which case we + # get a blank-delimited list. We prefer the first entry in the + # list because getpwnam() does. + $want{RecordName}{mung} = sub {(split '\s+', $_[0], 2)[0]}; + + # The UniqueID and PrimaryGroupID for a /User record are the + # user ID and the primary group ID respectively. In cases where + # the high bit is set, 'dscl' returns a negative number, whereas + # getpwnam() returns its twos complement. This mungs the dscl + # output to agree with what getpwnam() produces. Interestingly + # enough, getpwuid(-2) returns the right record ('nobody'), even + # though it returns the uid as 4294967294. If you track uid_t + # on an i386, you find it is an unsigned int, which makes the + # unsigned version the right one; but both /etc/passwd and + # /etc/master.passwd contain negative numbers. + $want{UniqueID}{mung} = $want{PrimaryGroupID}{mung} = sub { + unpack 'L', pack 'l', $_[0]}; + + foreach my $dscl (qw(/usr/bin/dscl)) { + -x $dscl or next; + open (my $fh, '-|', join (' ', $dscl, qw{. -readall /Users}, + keys %want, '2>/dev/null')) or next; + my $data; + my @rec; + while (<$fh>) { + chomp; + if ($_ eq '-') { + @rec and $data .= join (':', @rec) . "\n"; + @rec = (); + next; + } + my ($name, $value) = split ':\s+', $_, 2; + unless (defined $value) { + s/:$//; + $name = $_; + $value = <$fh>; + chomp $value; + $value =~ s/^\s+//; + } + if (defined (my $info = $want{$name})) { + $rec[$info->{inx}] = $info->{mung}->($value); + } + } + @rec and $data .= join (':', @rec) . "\n"; + if (open (PW, '<', \$data)) { + $where = "dscl . -readall /Users"; + undef $reason; + last; + } + } + } + if (not defined $where) { # Try local. my $PW = "/etc/passwd"; if (-f $PW && open(PW, $PW) && defined(<PW>)) { |