[comp.lang.perl] fun with scoping

tchrist@convex.com (Tom Christiansen) (12/17/90)

Once upon a time I had an annoying problem: I diff the run of a nightly
find to discover changes to setid files and devices.  Now, I happen to have
several accounts, like uucp and notes, that have files of this sort and
with more than one login to each uid, so every time the passwd and group
files hash (YP), I pull out a different id and so get reams of nightly
output.  This annoyed me.  So I wrote the following filter to convert
everything out of 'find -ls' back into numbers so it would stop changing:

    #!/usr/bin/perl
    $fmt = 'a22 A9 A8 a*';
    while (<>) {
	($pre, $login, $group, $post) = unpack($fmt, $_);
	print pack($fmt, $pre, &get(*login), &get(*group), $post);
    }
    sub get {
	local(*id) = @_;
	$id{$id} = $id =~ /^\d+$/ ? $id : &id       unless defined $id{$id};
	$id{$id};

    }
    sub login { (getpwnam($id))[2]; }
    sub group { (getgrnam($id))[2]; }


I would say that this is an interesting program, eh?  :-)   If this isn't
a great demo of Perl's um, unique, scoping behavior, I don't know what is.
If you think that's scary, note that if we s/get/id/g the program still works!

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
"With a kernel dive, all things are possible, but it sure makes it hard
 to look at yourself in the mirror the next morning."  -me

tchrist@convex.COM (Tom Christiansen) (12/17/90)

Crud -- I was using GNU find.  If you use real BSD find (don't ask me
about SysV, Brandon :-), you need a26 as the first format field.

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
"With a kernel dive, all things are possible, but it sure makes it hard
 to look at yourself in the mirror the next morning."  -me

tchrist@convex.COM (Tom Christiansen) (12/19/90)

No one has said anything, except one person through mail.
Here is the slightly touched up code that gets 'find -ls'
output.

    #!/usr/bin/perl
    $fmt = 'a26 A9 A8 a*';
    while (<>) {
	($pre, $login, $group, $post) = unpack($fmt, $_);
	print pack($fmt, $pre, &id(*login), &id(*group), $post);
    } 
    sub id {
	local(*id) = @_;
	$id{$id} = $id =~ /^\d+$/ ? $id : &id	unless defined $id{$id};
	$id{$id};
    } 
    sub login { (getpwnam($id))[2]; } 
    sub group { (getgrnam($id))[2]; } 

Now answer me these questions three:

    1.  Why is this (or isn't this) a recursive program?

    2.  What are the associative arrays in this program, by name?

    3.  What are their favorite colors?


People who already know the answers becasue they've corresponded
with me please hold back until we get some fun tries.

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
"With a kernel dive, all things are possible, but it sure makes it hard
 to look at yourself in the mirror the next morning."  -me

evans@decvax.DEC.COM (Marc Evans) (12/19/90)

In article <111559@convex.convex.com>, tchrist@convex.COM (Tom Christiansen) writes:
|> Crud -- I was using GNU find.  If you use real BSD find (don't ask me
|> about SysV, Brandon :-), you need a26 as the first format field.

Under OSF/1.0 you need a25 (although I thought that this was suppose to be BSD4.4
compatible).

- Marc
-- 
===========================================================================
Marc Evans - WB1GRH - evans@decvax.DEC.COM  | Synergytics     (603)635-8876
      Unix and X Software Contractor        | 21 Hinds Ln, Pelham, NH 03076
===========================================================================

tchrist@convex.COM (Tom Christiansen) (12/21/90)

From the keyboard of tchrist@convex.COM (Tom Christiansen):

:Now answer me these questions three:

(Before I jump on the plane to head for True Cold, here 
 are some answers...)

:    1.  Why is this (or isn't this) a recursive program?

It isn't -- the *id pass-by-name assignment in &id changes 
which &id your talking about.  [Someone was explaining
to me the difference between pass-by-name and pass-by-reference,
and perl's style seems more the former than the latter.]
If you considereed the *id assignment some kind of funky
conditional, I guess you might possibly construe it to be
a potentially recursive program, but that would be stretching
it, and anyway, in this case it doesn't do that.

:    2.  What are the associative arrays in this program, by name?

There are 2 associative arrays used to cache names and values.
These are %group and %login.  However, to the program, they 
are always known as %id, but which one it means varies between
calls, so it would be arguably correct (and certainly a lot
more fun) to say that they are %id and %id.

:    3.  What are their favorite colors?

One respondent said "Red.  No Blue!"  His message trailed off
in an "ARGGGGGGGGGGGGGGGGG!" as he was cast in the Abyss, and 
I have not heard from him since.  You should always answer 
Blue to questions like this, or at the very least be decisive.

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
"With a kernel dive, all things are possible, but it sure makes it hard
 to look at yourself in the mirror the next morning."  -me