[16681] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 4093 Volume: 9

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Tue Aug 22 11:10:30 2000

Date: Tue, 22 Aug 2000 08:10:16 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Message-Id: <966957016-v9-i4093@ruby.oce.orst.edu>
Content-Type: text

Perl-Users Digest           Tue, 22 Aug 2000     Volume: 9 Number: 4093

Today's topics:
        secure scripting <sp00fD@yahoo.com>
        Sorting <mcnultya@NOSPAMnortelnetworks.com>
        Unexpected behavior of shift in a loop (Jeff HIll)
    Re: Unexpected behavior of shift in a loop (Marcel Grunauer)
    Re: Variable vanishing? (Keith Calvert Ivey)
    Re: Variable vanishing? <lr@hpl.hp.com>
    Re: would you recommend buying a book <lwasilew@tislabs.com>
    Re: write a file in an array <undergronk@my-deja.com>
    Re: write a file in an array <lr@hpl.hp.com>
        Digest Administrivia (Last modified: 16 Sep 99) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Tue, 22 Aug 2000 14:02:00 GMT
From: sp00fD <sp00fD@yahoo.com>
Subject: secure scripting
Message-Id: <8nu14b$e91$1@nnrp1.deja.com>

I just created my first security checking program, and I was wondering
if someone could take a look and tell me if they see any glaring
problems or ways that I can do things better, this runs only as root
with perms of 500.  It's kind of long, so sorry.  Also, this is written
for a Sun Solaris box, it may need some tweaking to run elsewhere, but
feel free to use it.

Code follows:

#!/usr/local/bin/perl -w

#  @(#)cksec	1.23		08/22/00
#
#
#  Program Name:        cksec
#  Creator:             sp00fd
#  Date Created:	08/07/00
#  Usage:               cksec [-i <minutes>] [-f <file>] [-h] [-s] [-u]
#
#  Where:
#  -i <minutes> is the number of minutes in between executions.
#		Note: this doesn't cause the script to sleep, but tells
#		it how far back in the logs to look at stuff.  This is
just
#		so that you can cron it for every half hour or every 5
#		minutes or whatever and not miss log entries in between.
#		Default is 15 minutes.
#  -f <file> is the file which holds (or will hold) the checksums
#	default is /.md5db
#  -h   This help screen
#  -s   Compute and show the md5sums of the binaries and exit
#  -u   Update the "database" with computed checksums
#
use strict;
use POSIX qw(strftime uname);
use Mail::Sendmail;
use Getopt::Std;
use MD5;

use vars qw($opt_s $opt_u $opt_h $opt_i $opt_f);

getopts("suhi:f:");

############################
#
# Config
#
############################
my @UNAME       =	uname();
my $HOST        =	$UNAME[1];
my $RELEASE	=	$UNAME[2];
my $PROGNAME	=	basename($0);

#  File which holds the checksums
my $MD5FILE	=	$opt_f || "/.md5db";

#  Number of minutes between executions
my $INTERVAL	=	$opt_i || 15;	# in minutes

#  Email that should be seen in the /.forward and where to mail alerts
to
my $ADMIN_EMAIL = 	'me@mydomain.com';

#  Users that won't be looked at in the su log
my $ADMIN_STAFF	= 	"someuser another someoneelse";

#  Binaries that we'll sum and diff
my @BIN_LIST	=	qw(ifstatus ifconfig syslogd netstat route
login
				tcpd find date su ps ls du df);

#  Shoddy errno
my $EHRDLINK	=	-1;
my $ENOTPLN	=	-2;
my $EMODE	=	-3;
my $EOWNER	=	-4;
my $ESTAT1	=	-5;
my $ESTAT2	=	-6;
my $ENOMATCH	=	-7;
my $EHASPLUS	=	-8;
my $EEQUIV	=	-9;
my $EENV	=	-10;
my $EFORWARD	=	-11;
my $ENODB	=	-12;

#  We'll append to this if we have any alerts to send
my $msg		=	"";

#  A flag that will be looked at later, if = 1 don't execute ifstatus
my $ckifflag	=	0;

#
#  Files to look at
#
my %FILES = (
	loginlog	=>	"/var/adm/loginlog",
	forward		=>	"/.forward",
	shadow		=>	"/etc/shadow",
	rhosts		=>	"/.rhosts",
	passwd		=>	"/etc/passwd",
	sulog		=>	"/var/adm/sulog",
	md5db		=>	$MD5FILE,
	equiv		=>	"/etc/hosts.equiv",
	utmp		=>	"/var/adm/utmp",
	cron		=>	"/var/spool/cron/crontabs/root",
);

#
#  Binaries to look at
#
my %BINARIES = (
	ifstatus	=>	"/usr/gnu/bin/ifstatus",
	ifconfig	=>	"/usr/sbin/ifconfig",
	syslogd		=>	"/usr/sbin/syslogd",
	netstat		=>	"/usr/bin/netstat",
	route		=>	"/usr/sbin/route",
	login		=>	"/usr/bin/login",
	tcpd		=>	"/usr/sbin/tcpd",
	find		=>	"/usr/bin/find",
	date		=>	"/usr/bin/date",
	su		=>	"/usr/bin/su",
	ps		=>	"/usr/bin/ps",
	ls		=>	"/usr/bin/ls",
	du		=>	"/usr/bin/du",
	df		=>	"/usr/bin/df",
);

#
#  My little perror hash
#
my %PERROR = (
        $EHRDLINK       =>      ": File is a hard link\n",
        $ENOTPLN        =>      ": File isn't a plain file\n",
        $EMODE          =>      ": Incorrect mode for file\n",
        $EOWNER         =>      ": Incorrect ownership for file\n",
        $ESTAT1         =>      ": Couldn't stat file on 1st attempt\n",
        $ESTAT2         =>      ": Couldn't stat file on 2nd attempt\n",
        $ENOMATCH       =>      ": File stats didn't match\n",
        $EHASPLUS       =>      ": $FILES{rhosts} has a + in it\n",
        $EEQUIV         =>      ": $FILES{equiv} exists\n",
        $EENV           =>      ": Root's path is bad $ENV{PATH}\n",
        $EFORWARD       =>      ": Bad entries found\n",
        $ENODB          =>      ": Created database, none existed\n",
);


############################
#
# Main
#
############################
if($opt_h) {
	usage();
	exit;
} elsif($opt_s) {
	showsums();
	exit;
} elsif($opt_u) {
	if(! updatedb()) {
		print "$FILES{md5db} update failure!\n";
	}
	exit;
}

#
#  Compare actual md5sum to stored md5sum, complain if they differ
#
my $sumhash = parsedb();
if(defined($sumhash) && ! $sumhash) {
	$msg .= "Verification failed at parsedb(), unsure of db
integrity\n";
} elsif(defined($sumhash)) {
	foreach (keys(%BINARIES)) {
		my $thishash = twdigest($BINARIES{$_});

		if($thishash ne ${ $sumhash }{$_}) {
			$msg .= "*" x 50;
			$msg .= "\nBad binary -> $BINARIES{$_}\n";
			$msg .= "Stored sum -> ${ $sumhash }{$_}\n";
			$msg .= "Actual sum -> $thishash\n";
			$msg .= "*" x 50;
			$msg .= "\n";

			if($_ eq "ifstatus") {
				$ckifflag = 1;
			}
		}
	}
} else {
	$msg .= "Nothing in the database, please run $PROGNAME -u\n";
}

if($ckifflag == 1) {
	#  Don't want to execute something we're not sure we can trust
	$msg .= "ifstatus hash was off, skipping execution of
binary...";
} else {
	ckifmode();
}

ckpath();
cksulog();
ckloginlog();
ckforward();
ckrhosts();
ckpasswd();
ckshadow();
verifyfile($FILES{cron}, "other", "0400", 1);
verifyfile($FILES{utmp}, "bin", "0644", 1);

#
#  If we appended anything to $msg, we've had a problem, email it
#
if($msg ne "") {
	my %mail = (To		=>	$ADMIN_EMAIL,
		    From	=>	"$PROGNAME\@$HOST",
		    Subject	=>	"Security alert - $HOST
$RELEASE",
		    Message	=>	"\n$msg",
		    Smtp	=>	"mailhost",
	);

	sendmail(%mail);
}

############################
#
# Subroutines
#
############################
sub basename {
	#  Just like the unix command
	my $name = $_[0];
	$name =~ s|^.*/||g;
	return $name;
}

sub usage {
	print "Usage: $PROGNAME [-i <min>] [-f <file>] [-h] [-s] [-u]";
	print "\n\nwhere min is the number of minutes in between\n";
	print "executions of this program\n\n";
	print "-i -- interval between executions\n";
	print "-f -- specify the file to use as the md5 database\n";
	print "      default is /.md5db\n";
	print "-h -- help (this screen)\n";
	print "-s -- display md5 sums of system binaries and exit\n";
	print "-u -- update the md5 database and exit\n\n";
}

sub manipdate {
	#  Return a date string from $INTERVAL minutes ago
	my $current_date = time;
	my $interval = $_[0];
	my $format = $_[1];

	$interval = 60 * $interval;
	my $targ_date = $current_date - $interval;

	return strftime($format, localtime($targ_date));
}

sub convmode {
	#  Convert cryptic stat->mode values to normal octal (i.e. 0600)
	my $mode = shift;
        my @modelist = (($mode & 7000)>>9, ($mode & 0700)>>6,
			($mode & 0070)>>3, ($mode & 0007));
        return join('', @modelist);
}

sub twdigest {
	#  Get the md5 checksum of a file
        my $file = shift;
        my $md5 = new MD5;

        open(FILE, "< $file") || die "Can't open $file: $!\n";
        seek(FILE, 0, 0);
        $md5->reset;
        $md5->addfile(\*FILE);
        close(FILE);

        my $digest = $md5->hexdigest;
        return $digest;
}

sub verifyfile {
	#  Make sure the file permissions/mode are correct
	my ($file, $group, $perm, $create) = @_;
        my $uid = 0;
	#  Should I be passing the gid or the group name?
        my $gid = (getgrnam($group));
	my $rc = 0;

        if(! -f $file) {
                if(-e $file || -l $file) {
			#  File exists but isn't a plain file, uhoh.
                        $msg .= "$file $PERROR{$ENOTPLN}";
			$rc = -1;
                } elsif($create) {
			#  We'll never know why it's not there, just
create it
			open(FILE, "> $file") || die "Can't create
$file: $!";
			close(FILE);
			chown($uid, $gid, $file);
			chmod(oct($perm), $file);
		}
        }

        my @st = lstat($file);
	my $mode = convmode($st[2]);

	if($st[3] != 1) {
		#  File is a hard link, bad news
		$msg .= "$file $PERROR{$EHRDLINK}";
		$rc = -1;
	} elsif($mode != $perm) {
		#  Wrong mode
                $msg .= "$file $PERROR{$EMODE}";
		$rc = -1;
        } elsif($st[4] != 0 || $st[5] != $gid) {
		#  Bad ownership
                $msg .= "$file $PERROR{$EOWNER}";
		$rc = -1;
        }

	return $rc;
}

sub printhash {
	#  Pass in the filehandle, could be STDOUT or anything else
	my $fh = shift;

        foreach (@BIN_LIST) {
                print $fh "$_ = ", twdigest($BINARIES{$_}), "\n";
        }
}

sub updatedb {
	my $rc = verifyfile($FILES{md5db}, "root", "0400", 1);
	if($rc) {
		return 0;
	}

	my @firststat = ();
	my @secondstat = ();

	unless(@firststat = lstat($FILES{md5db})) {
		$msg .= "$FILES{md5db} $PERROR{$ESTAT1}";
		return 0;
	}

	open(MD5DB, "> $FILES{md5db}") || die "Can't open $FILES
{md5db}: $!";

	unless(@secondstat = lstat($FILES{md5db})) {
		$msg .= "$FILES{md5db} $PERROR{$ESTAT2}";
		return 0;
	}

	#  Make sure stats match from before the open, to after the open
	#  We do this because we're writing to the file and we don't
want
	#  anyone modifying where we're writing so that we end up
writing
	#  over the /etc/shadow or something stupid.
	if($firststat[0] != $secondstat[0] ||
	   $firststat[1] != $secondstat[1] ||
	   $firststat[7] != $secondstat[7]) {
		#  Stats don't match, security problem
		$msg .= "$FILES{md5db} $PERROR{$ENOMATCH}";
		return 0;
	}

	printhash(\*MD5DB);
	close(MD5DB);
}

sub parsedb {
        my $rc = verifyfile($FILES{md5db}, "root", "0400", 1);
        if($rc) {
                return 0;
        }

        if(-z $FILES{md5db}) {
                #  Possibly we created it with the verifyfile(),
populate it
                if(! updatedb()) {
			$msg .= "$FILES{md5db} update failure!\n";
		} else {
                	$msg .= "$FILES{md5db} $PERROR{$ENODB}";
		}
        }

        my %MD5HASH = ();

        open(MD5DB, "< $FILES{md5db}") || die "Can't open $FILES
{md5db}: $!";

        while(<MD5DB>) {
                my $filename = "";
                my $sum = "";

                ($filename, $sum) = split(/\s*=\s*/);
                chomp($MD5HASH{$filename} = $sum);
        }

        close(MD5DB);

        return \%MD5HASH;
}

sub showsums {
        #  Just compute and print the checksums and exit
	printhash(\*STDOUT);
}

sub ckpath {
	#  If there's a . in the path that's a no-no
        if($ENV{'PATH'} =~ /:?\.:?(?!$)/g) {
		$msg .= "$EENV\n";
        }
}

sub ckifmode {
	#  Anyone snooping on this machine?
	my $status = `$BINARIES{ifstatus} 2> /dev/null`;

	if($status =~ /^.* INTERFACE (\w+) IS IN PROMISCUOUS .*/) {
		$msg .= "Device found in promiscuous mode -> $1\n";
	}
}

sub cksulog {
	#  Check for su attempts made by people not in the admin list
	verifyfile($FILES{sulog}, "root", "0600", 1);

	my $date_format = "%m/%d %H:%M";
	my @timelist = ();
	my @luserlist = ();

	foreach (0..$INTERVAL) {
		#  Create an array of the hours/minutes to check
		push(@timelist, eval{ manipdate($_, $date_format) });
	}

	open(SULOG, "< $FILES{sulog}") ||
		die "Can't open $FILES{sulog} for read: $!";

	while(<SULOG>) {
		foreach my $time (@timelist) {
			if($_ =~ m|$time (.) pts/[0-9]+ (\w+)-
root\s+$|g) {
				my $status = $1;
				my $luser = $2;

				if($ADMIN_STAFF !~ /\b$luser\b/) {
					if($status eq '+') {
						$status = "SUCCEEDED";
					} else {
						$status = "FAILED";
					}

					$msg .= "$FILES{sulog} : su -
root ";
					$msg .= "attempt for $luser
$status\n";
				}
			}
		}
	}

	close(SULOG);
}

sub ckloginlog {
	#  Any multiple login failures lately?
	verifyfile($FILES{loginlog}, "sys", "0600", 1);

	my $flag = 0;
	my $date_format = "%C";
	my @timelist = ();
	my @failedlogins = ();

	foreach (0..$INTERVAL) {
		#  Create an array of the hours/minutes to check
                push(@timelist, eval{ manipdate($_, $date_format) });
        }

	open(LOGINLOG, "< $FILES{loginlog}") ||
		die "Can't open $FILES{loginlog} for read: $!";

	while(<LOGINLOG>) {
		foreach my $time (@timelist) {
			#  Modify the seconds to \d\d to represent the
regex
			#  of any 2 digits, this way we don't have to
create
			#  a list of times from $INTERVAL to now down
to each
			#  and every second.
			$time =~
			s/(\w+\s\w+\s+\d+\s\d+:\d+:)\d\d EDT( \d+)/$1
\\d\\d$2/g;
			if($_ =~ m|^(.*):/dev/(pts/\d+):$time|g) {
				my $luser = $1;
				my $pty = $2;

				$msg .= "$FILES{loginlog} : Bad Login:
$luser $pty\n";
			}
		}
	}

	close(LOGINLOG);
}

sub ckforward {
	#  We'll make sure that the forward file only has our email in
it
	verifyfile($FILES{forward}, "root", "0600", 1);

	if(-z $FILES{forward}) {
		my @firststat = ();
		my @secondstat = ();

		unless(@firststat = lstat($FILES{forward})) {
			$msg .= "$FILES{forward} $PERROR{$ESTAT1}";
			return 0;
		}

		open(FORWARD, "> $FILES{forward}") ||
			die "Can't open $FILES{forward} for write: $!";

		unless(@secondstat = lstat($FILES{forward})) {
			$msg .= "$FILES{forward} $PERROR{$ESTAT2}";
			return 0;
		}

		#  Make sure stats match from before the open, to after
the
		#  open We do this because we're writing to the file
and we
		#  don't want anyone modifying where we're writing so
that we
		#  end up writing over the /etc/shadow or something
stupid.
		if($firststat[0] != $secondstat[0] ||
		   $firststat[1] != $secondstat[1] ||
		   $firststat[7] != $secondstat[7]) {
			#  Stats don't match, security problem
			$msg .= "$FILES{forward} $PERROR{$ENOMATCH}";
			return 0;
		}

		print FORWARD $ADMIN_EMAIL;
		close(FORWARD);
	}

	open(FORWARD, "< $FILES{forward}") ||
		die "Can't open $FILES{forward} for read: $!";

	while(<FORWARD>) {
		if(! /^$ADMIN_EMAIL$/) {
			#  If there's something besides the email,
complain
			$msg .= "$FILES{forward} $PERROR{$EFORWARD}";
		}
        }

	close(FORWARD);
}

sub ckrhosts {
	#  Make sure the .rhosts doesn't have any pluses and that
	#  there's no hosts.equiv file
	verifyfile($FILES{rhosts}, "other", "0600", 1);

	open(RHOSTS, "< $FILES{rhosts}") ||
		warn "Can't open $FILES{rhosts} for read: $!";

	while(<RHOSTS>) {
		if(/\+/) {
			#  +'s are baaaaddd
			$msg .= "$FILES{rhosts} $PERROR{$EHASPLUS}";
		}
	}

	close(RHOSTS);

	if(-e $FILES{equiv}) {
		$msg .= "$FILES{rhosts} $PERROR{$EEQUIV}";
	}
}

sub ckpasswd {
	verifyfile($FILES{passwd}, "sys", "0444", 0);

	my $rootflag = 0;
	#  Users that have uid of 0
	my @root_users = qw(root rootbob);
	my $standard_shells = "/usr/bin/sh /usr/bin/csh /usr/bin/ksh
			/usr/bin/jsh /usr/bin/false /bin/sh /bin/csh

	/bin/ksh /bin/jsh /bin/false /sbin/sh /sbin/jsh";

	open(PASSWD, "< $FILES{passwd}") || die "Can't open $FILES
{passwd} $!";

	while(<PASSWD>) {
		#  I should probably do a getpwnam() in case the NIS
entry
		#  overrides local files, but....screw it
		chomp(my ($user, $passwd, $uid, $gid, $gecos, $home,
$shell) =
			split(/:/));

		if($user eq "root" && $uid == 0) {
			$rootflag = 1;
		}

		if(! grep(/\b$user\b/, @root_users)) {
			if($uid == 0) {
				$msg .= "$user has uid=0\n";
			}
		}

		if(! -d $home) {
			$msg .= "$user has invalid home directory:
$home\n";
		}
		if($standard_shells !~ /\s$shell\s/) {
			$msg .= "$user has invalid shell: $shell\n";
		}
		if(-u $shell) {
			$msg .= "$user has setuid shell: $shell\n";
		}
		if(-g $shell) {
			$msg .= "$user has setgid shell: $shell\n";
		}
		if(! defined(getgrgid($gid))) {
			$msg .= "$user has invalid gid: $gid\n";
		}
	}

        close(PASSWD);

	if(! $rootflag) {
		$msg .= "didn't see a root entry\n";
	}
}

sub ckshadow {
	verifyfile($FILES{shadow}, "sys", "0400", 0);

	#  Users that should always have NP
	my @nopass_users = qw(daemon bin sys adm lp uucp nobody
			      noaccess nobody4);

	open(SHADOW, "< $FILES{shadow}") || die "Can't open $FILES
{shadow} $!";

	while(<SHADOW>) {
		(my $user = $_) =~ s/^(\w+):.*/$1/g;
		chomp($user);

		foreach my $username (@nopass_users) {
			if($user eq $username) {
				if($_ !~ /^$user:NP:.*/) {
					$msg .= "$user should have NP:
$_\n";
				}
			}
		}

		if($_ =~ /^\w+::.*/) {
			$msg .= "$user has no password: $_\n";
		}

	}

	close(SHADOW);
}


Sent via Deja.com http://www.deja.com/
Before you buy.


------------------------------

Date: 22 Aug 2000 14:18:06 GMT
From: Antony <mcnultya@NOSPAMnortelnetworks.com>
Subject: Sorting
Message-Id: <8nu22u$fl5$1@qnsgh006.europe.nortel.com>

Hi,

I have a hash as follows:

$Hash{id}{key} = value

I need to create a nested sorted array of the id's.
I am terrible at trying to explain this, but I used a command like follows to sort by 
the values of a particular key:

@aryID = sort {$Hash{$a}{$key} cmp $Hash{$b}{$key}} keys %Hash;

But I need to do a nested sort on my hash.
i.e., I need the id's sorted in a way that is first sorted by a particular key, and further 
sorted by another particular key.

Does this make sense ?

Cheers,



------------------------------

Date: Tue, 22 Aug 2000 14:22:07 GMT
From: jeffahill@lucent.com (Jeff HIll)
Subject: Unexpected behavior of shift in a loop
Message-Id: <39a285e1.419558406@nntp.lucent.com>

I have a program where I'm taking some information generated by SAP
and pushing it on to a web page.  I came across a curious behavior of
the shift command and wondered if someone could explain this to me.

Here is the code:

open (FILE, "/prd1/bmp/mfg/parts/total/SIPP") || die "Can't open file
$!";
while (<FILE>) {
  $line = $_;
  $line =~ s/^\s*(.*?)\s*$/$1/g;
  $line =~ s/\s+/ /g;
  @items = split(/ /, $line);
  $list = join ';', $items[0],$items[1],$items[2],$items[3];
  shift @items;
  shift @items;
  shift @items;
  shift @items;
  $list .=";";
#  for ($i=0; $i==3; $i++) {
#    shift @items;
#  }
  $list .= join ' ', @items;
  print $list . "\n";
}

Ouput:

Correct:
f0;f1;f2;f3;f4 f5 f6 f7

Incorrect:
f0;f1;f2;f3;f0 f1 f2 f3 f4 f5 f6 f7

When I run the program using the current configuration, I get the
correct output.  But when I use the commented out for loop, I get the
incorrect output.  Anyone have any ideas?

Jeff Hill


------------------------------

Date: Tue, 22 Aug 2000 14:48:01 GMT
From: marcel@codewerk.com (Marcel Grunauer)
Subject: Re: Unexpected behavior of shift in a loop
Message-Id: <slrn8q54j9.9or.marcel@gandalf.local>

On Tue, 22 Aug 2000 14:22:07 GMT, Jeff HIll <jeffahill@lucent.com> wrote:

>#  for ($i=0; $i==3; $i++) {
>#    shift @items;
>#  }

That loop wouldn't be executed at all, since after assigning 0 to $i,
you then test if it is equal to 3, which it isn't, so the loop terminates
before executing even once.

Also, if I interpret the input correctly (lines consisting of possible
whitespace at the beginning and end, with items separated by whitespace,
and you want the first four items separated by a semicolon, followed by
another semicolon and the rest - a spec would have been nice), then you
could try something like this:

    while (<FILE>) {
	    s/^\s*//;
	    s/\s*$//;
	    s/\s+/ /g;
	    my $list = join ';' => split /\s+/, $_, 5;
	    print $list . "\n";
    }


-- 
Marcel Gr\"unauer - Codewerk plc . . . . . . . . . . . <http://www.codewerk.com>
Perl Consulting, Programming, Training, Code review . . .  <marcel@codewerk.com>
mod_perl, XML solutions - email for consultancy availability
sub AUTOLOAD{($_=$AUTOLOAD)=~s;^.*::;;;y;_; ;;print} Just_Another_Perl_Hacker();


------------------------------

Date: Tue, 22 Aug 2000 13:15:10 GMT
From: kcivey@cpcug.org (Keith Calvert Ivey)
Subject: Re: Variable vanishing?
Message-Id: <39a77bf5.48027992@news.newsguy.com>

darkon@one.net (David Wall) wrote:
>abe@ztreet.demon.nl (Abe Timmerman) wrote in 
><fdi3qsorchuaiterrc9c7gvsl0k6cm4lur@4ax.com>:
>
>>On Mon, 21 Aug 2000 20:32:56 GMT, Steven Merritt
>><smerr612@mailandnews.com> wrote:
>>
>>> my $From_Date = 20000000000000;
>>> my $To_Date = 20000525135144;
>>
>>I would declare those as strings:
>>
>>     my $From_Date = '20000000000000';
>>     my $To_Date   = '20000525135144';
>
>Just out of curiousity, why would you do that?  Why does it matter?

Try adding a few more digits and you'll see why quoting might be
a good habit to get into for long numbers that are really being
treated as strings:

    C:\>perl -le "print 2000052513514412"
    2.00005251351441e+015

-- 
Keith C. Ivey <kcivey@cpcug.org>
Washington, DC


------------------------------

Date: Tue, 22 Aug 2000 06:55:24 -0700
From: Larry Rosler <lr@hpl.hp.com>
Subject: Re: Variable vanishing?
Message-Id: <MPG.140c2620462c1f2a98acb6@nntp.hpl.hp.com>

In article <g8g4qs8mgc50gboak8h8cecirup8691kqu@4ax.com>, 
abe@ztreet.demon.nl says...
> On 22 Aug 2000 00:54:58 -0400, darkon@one.net (David Wall) wrote:
> 
> > abe@ztreet.demon.nl (Abe Timmerman) wrote in 
> > <fdi3qsorchuaiterrc9c7gvsl0k6cm4lur@4ax.com>:
> > 
> > >On Mon, 21 Aug 2000 20:32:56 GMT, Steven Merritt
> > ><smerr612@mailandnews.com> wrote:
> > >
> > >> my $From_Date = 20000000000000;
> > >> my $To_Date = 20000525135144;
> > >
> > >I would declare those as strings:
> > >
> > >     my $From_Date = '20000000000000';
> > >     my $To_Date   = '20000525135144';
> > 
> > Just out of curiousity, why would you do that?  Why does it matter?
> 
> Because they are strings, usually constructed as strings.
> Writing them as numbers gives the impression they're integers, which
> they're not (on 32 bit platforms without the use64bitint config option).

No, they are integers on any platform.  They would be stored as double-
precision floating-point numbers with integral values, because the 
mantissa is 52 (or 53, if you count the hidden bit) bits long.  If one 
were sorting on them, numerical comparison would be faster than 
lexicographic comparison.

-- 
(Just Another Larry) Rosler
Hewlett-Packard Laboratories
http://www.hpl.hp.com/personal/Larry_Rosler/
lr@hpl.hp.com


------------------------------

Date: Tue, 22 Aug 2000 10:20:36 -0400
From: Lori Wasilewski <lwasilew@tislabs.com>
Subject: Re: would you recommend buying a book
Message-Id: <39A28C34.FC37EDCA@tislabs.com>

try this free tutorial :
http://www.netcat.co.uk/rob/perl/win32perltut.html
if that doesn't help you get a book

Jan Heidbrink wrote:

> Hi!
> I'm planning to learn pearl. I'll mainly use it for CGI.
> Would you recommend to buy a book (if yes, where can I find an
> overview about some) or do you think, a free tutorial is enough? I'd
> prefer the last one as I don't have very much money. However, if you
> think that I should buy a good book, I'd do that.
>
> BTW: I'm already familiar with Pascal and C++.



------------------------------

Date: Tue, 22 Aug 2000 13:16:29 GMT
From: Scott Kirk <undergronk@my-deja.com>
Subject: Re: write a file in an array
Message-Id: <8ntuet$aqv$1@nnrp1.deja.com>

In article <39A24AF5.3B7A9862@yahoo.es>,
  Javier Hijas <jhijas@yahoo.es> wrote:

> > Can you tell me a nice way to copy an entire file in an array?
>
> Ok, I already found a fancy way!!:
>
> while (<FILE>) {
>   push @file,$_;
> }

Yes.  But _why_ would you want to do it this way?


--
Scott Kirk
My deja.com mailbox is full of spam. Use this instead:
perl -e '$_ = "znvygb: haqretebax\@lnubb.pbz";
tr/A-Za-z/N-ZA-Mn-za-m/; print;'


Sent via Deja.com http://www.deja.com/
Before you buy.


------------------------------

Date: Tue, 22 Aug 2000 07:02:16 -0700
From: Larry Rosler <lr@hpl.hp.com>
Subject: Re: write a file in an array
Message-Id: <MPG.140c27c4ff4f68198acb7@nntp.hpl.hp.com>

In article <slrn8q4ujp.4ed.tjla@thislove.dyndns.org>, 
tjla@guvfybir.qlaqaf.bet says...
> I was shocked! How could Ralf Heydenreich <heydenreich@delta.de>
> say such a terrible thing:
> >try this (the easiest way):
> >$idx=0;
> >while(<FILE>)
> >{
> >   $file[$idx]=$_;
> >   $idx++;
> >}

That really *is* terrible.  :-)

> *sigh* What's wrong with push?
> 
> push @file while (<FILE>);

  push @file, $_ while <FILE>;
 
> *double sigh* what's wrong with using the diamond operators in a list
> context?
> 
> @file = <FILE>;
> 
> *triple sigh* WHy don;t you read it line by line anyway?
> 
> while (<FILE>)
> {
>     # do something
> }

-- 
(Just Another Larry) Rosler
Hewlett-Packard Laboratories
http://www.hpl.hp.com/personal/Larry_Rosler/
lr@hpl.hp.com


------------------------------

Date: 16 Sep 99 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 16 Sep 99)
Message-Id: <null>


Administrivia:

The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc.  For subscription or unsubscription requests, send
the single line:

	subscribe perl-users
or:
	unsubscribe perl-users

to almanac@ruby.oce.orst.edu.  

| NOTE: The mail to news gateway, and thus the ability to submit articles
| through this service to the newsgroup, has been removed. I do not have
| time to individually vet each article to make sure that someone isn't
| abusing the service, and I no longer have any desire to waste my time
| dealing with the campus admins when some fool complains to them about an
| article that has come through the gateway instead of complaining
| to the source.

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.

For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V9 Issue 4093
**************************************


home help back first fref pref prev next nref lref last post