[comp.lang.perl] problem: open

mwette@csi.jpl.nasa.gov (Matt Wette) (06/12/91)

After receiving a couple of replies that open(OUT, "| more") works
and still not being able to get my code to work I've decided to post
my code.  The command (`whom') just dumps the NIS password file, in
formatted form, to the screen.  The option "-m" attempts to pipe
through more.  But the program just dies at the first --more-- prompt.

If someone is willing to check it out and tell me what's wrong, I'd
appreciate it.  (also, anyone is certainly welcomed to use the code)

perl: 4.003
mach: SunOS 4.1.1 on sun3

#!/usr/local/bin/perl
#
# whom - print out the NIS password file, formatted
#
# usage -
#	whom [-m] [-s (last | login)] [-v]
#		-m	Pipe output through more.
#		-s opt	Sort by last name (last) or by login name (login)
#			Default is last.
#		-v	Show version and quit.
#
# history -
#	04Jun91	M.Wette: created.
#	05Jun91	M.Wette: added sortby
# version -
#	$Id: whom,v 1.3 1991/06/05 23:21:39 mwette Exp $
$Version="1.01";
$Dated="04Jun91";

$sortby = "last";
$out = STDOUT;

while ($arg = shift(@ARGV)) {
  if ($arg eq "-v") {
    print("whom Version $Version Dated $Dated\n");
    exit(0);
  } elsif ($arg eq "-s") {
    $arg = shift(@ARGV);
    if ($arg eq "login") { $sortby = "login"; }
  } elsif ($arg eq "-m") {
    open(MOREOUT, "| more");
    $out = MOREOUT;
  }
}

if ($sortby eq "last") {
  select((select($out), $^='LASTTOP', $~='LASTOUT', $|=1)[0]);
} elsif ($sortby eq "login") {
  select((select($out), $^='LOGINTOP', $~='LOGINOUT', $|=1)[0]);
}

if (system("ypcat passwd > /tmp/passwd.$$")/256) {
  die "whom: ypcat failed\n";
}
if (!open(PASSWD, "/tmp/passwd.$$")) {
  die "whom: can't open temporary password file\n";
}

while (<PASSWD>) {
  chop;
  ($login,$passwd,$uid,$gid,$gcos,$home,$shell) = split(/:/);
  ($name,$office,$phone) = split(/,/,$gcos);
  if ($uid < 30) { next; }
  if (length($phone)>0) { $phone = "4-$phone"; }
  $pos = rindex($name,' ');
  if ($pos < 0) { $pos = 0; }
  $last = substr($name,$pos);
  $last =~ tr/A-Z/a-z/;
  if (length($last) == 0) { $last = "zzz$i"; $i++; }
  if ($sortby eq "login") {
    $entries{$login} .= "$name:$login:$office:$phone:";
  } else {
    $entries{$last} .= "$name:$login:$office:$phone:";
  }
}

@sortedkeys = sort alphabetically keys(%entries);
while ($key = shift(@sortedkeys)) {
  ($name,$login,$office,$phone) = split(/:/,$entries{$key});
  write($out);
}

system("rm -f /tmp/passwd.$$");



sub alphabetically { $a gt $b; }


format LASTTOP =
Name                  Login      Office    Phone 
-------------------------------------------------
.
format LASTOUT =
@<<<<<<<<<<<<<<<<<<<  @<<<<<<<<  @<<<<<<<  @<<<<<<
$name,                $login,    $office,  $phone
.

format LOGINTOP =
Login      Name                  Office    Phone 
-------------------------------------------------
.
format LOGINOUT =
@<<<<<<<<  @<<<<<<<<<<<<<<<<<<<  @<<<<<<<  @<<<<<<
$login,    $name,                $office,  $phone
.

# --- last line of whom ---


-- 
 _________________________________________________________________
 Matthew R. Wette           | Jet Propulsion Laboratory, 198-326
 mwette@csi.jpl.nasa.gov    | 4800 Oak Grove Dr, Pasadena,CA 91109
 -----------------------------------------------------------------

stuart@amc.com (Stuart Poulin) (06/13/91)

Hey I know this one, (because I asked basically the same question a few
weeks back).  It's in the man page under close(FILEHANDLE). "... Close
will wait for the process executing the pipe to complete ...".  You
just need to add close($out) after your write loop.  At least that's
what I did to get your script to work for me.

The -m to pipe the output to more is a nice feature, but how about
looking in the users environment for the variable PAGER and if it's is
set then use this for the pager, if is not set then default to more.


"Who's Perl?!" - My wife to me as I was waking up one morning.

Stuart Poulin                             DNS: stuart@amc.com
Applied Microsystems Corporation         UUCP: amc-gw!stuart
Redmond, Washington  98073               Dial: 800-ASK-4AMC,206-882-2000 

tchrist@convex.COM (Tom Christiansen) (06/16/91)

From the keyboard of stuart@tfatf.amc.com (Stuart Poulin):
:The -m to pipe the output to more is a nice feature, but how about
:looking in the users environment for the variable PAGER and if it's is
:set then use this for the pager, if is not set then default to more.

Better to let the user type the pipe himself than build it in
to every command, don't you think?

It's not as though you're even really saving any characters: if 'm' is
aliased to your pager, then a postfix "|m" is still only two characters,
the same as an infix "-m".

--tom