[19217] in Perl-Users-Digest

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

Perl-Users Digest, Issue: 1412 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Mon Jul 30 21:10:30 2001

Date: Mon, 30 Jul 2001 18:10:12 -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: <996541812-v10-i1412@ruby.oce.orst.edu>
Content-Type: text

Perl-Users Digest           Mon, 30 Jul 2001     Volume: 10 Number: 1412

Today's topics:
    Re: PERL compiler...... <bart.lateur@skynet.be>
    Re: question about CGI.PM~~~ help (David Efflandt)
    Re: Regexp question (Craig Berry)
    Re: scope for recursive sub (Joe McMahon)
    Re: SHEBANG ? <paul.johnston@dsvr.co.uk>
    Re: Striping out the string <paul.johnston@dsvr.co.uk>
    Re: Telnet/MUD server <goldbb2@earthlink.net>
    Re: User Authentication in Unix <paul.johnston@dsvr.co.uk>
    Re: Verify upload is completed <bcaligari@fireforged.com>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

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

Date: Tue, 31 Jul 2001 00:02:44 GMT
From: Bart Lateur <bart.lateur@skynet.be>
Subject: Re: PERL compiler......
Message-Id: <18tbmtcptmrpvrglhh3re3sfdvu0uo4n5b@4ax.com>

Kolorove Nebo wrote:

>Is there any PERL compiler to build exe files from perl files on win32
>platforms?

Yes. No. It depends on what you want.

There is perl2exe from Indigostar (<www.indigostar.com>), and Perlapp
from Activestate (<www.activestate.com>). Both work on the same
principle: they build an executable which contains the script (stored in
encrypted form), the perl interpreter, and any used modules (including
DLL's). So they do give you the ease of just one executable (needs no
installation, just run it!), but give no speed advantages whatsoever.
Nor disadvantages.

Don't be discouraged by the large starting size for the executable. If
you double the size of your script, it most certainly won't double the
size of the executable.

-- 
	Bart.


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

Date: Tue, 31 Jul 2001 00:09:02 +0000 (UTC)
From: see-sig@from.invalid (David Efflandt)
Subject: Re: question about CGI.PM~~~ help
Message-Id: <slrn9mbtou.an6.see-sig@typhoon.xnet.com>

On Mon, 30 Jul 2001 16:55:32 +0800, swansun <swansun@kali.com.cn> wrote:
> i'm using the CGI.PM to write a perl script
> to upload files now,and it work!
> but i want to know how can i know the size of the uploaded file?
> who can help me? thanks.

Either keep a running total of each line if read as a text file or 
$bytesread if saving it as binary (slightly modified from perldoc CGI):

# Copy a binary file to somewhere safe
if (open (OUTFILE,">>/usr/local/web/users/feedback")) {
    while ($bytesread=read($filename,$buffer,1024)) {
        $totalbytes += $bytesread;
        # do something else if $totalbytes gets too big
        print OUTFILE $buffer;
    }
} else {
   # print error that file would not open including reason $!
}

Or if you simply want to know the size after it is saved, use the -s file 
test operator ($size = -s $savedfile).

-- 
David Efflandt  (Reply-To is valid)  http://www.de-srv.com/
http://www.autox.chicago.il.us/  http://www.berniesfloral.net/
http://cgi-help.virtualave.net/  http://hammer.prohosting.com/~cgi-wiz/


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

Date: Mon, 30 Jul 2001 23:02:44 -0000
From: cberry@cinenet.net (Craig Berry)
Subject: Re: Regexp question
Message-Id: <tmbpskag5t7pfd@corp.supernews.com>

Svein Erling Seldal (Svein.Seldal@q-free.com) wrote:
: I want to match the following text:
: 
: persist=<some_argument>   or
: per=<some_argument>
: 
: For this I use /^(persist|per)=(.*)/i

  /^(per(?:sist)?)=(.*)/i

is more idiomatic and efficient.

: I want to put an asterisk(*) after the command, and thus match 'persist*='
: or 'persist=', but not 'persistsomething=' nor 'persist*something='. How can
: I do this? I.e. I want to match \* or nothing. Is there a quantifier which
: matches nothing?

? is what you need; it quantifies 0 or 1 match, as in my use of it above.
For your asterisk, the syntax would be \*? .

-- 
   |   Craig Berry - http://www.cinenet.net/~cberry/
 --*--  "Brute force done fast enough looks slick."
   |             - William Purves


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

Date: 30 Jul 2001 18:42:19 -0400
From: mcmahon@tribal.metalab.unc.edu (Joe McMahon)
Subject: Re: scope for recursive sub
Message-Id: <9k4nsb$34g$1@tribal.metalab.unc.edu>

In article <3B5CCA8D.C410D0DC@yahoo.com>,
Jason LaPenta  <lapenta_jm@yahoo.com> wrote:
>I have a recursive sub. and I want a local var that is not global, so
>each call in the recursion has it's own copy. How do I do this. I've
>tried delcaring it local.

After reading all the other entries here, I think you are trying to 
create a closure.

sub counter {
   my $start = shift;
   return sub { $start++ };
}

my $first = counter(10);
my $second = counter(20);
&$first; &$first; print &$first,"\n";  # prints 12
&$second; print &$second,"\n";         # prints 21
print &$first,"\n";                    # prints 13

Note that the $start variable is "enclosed" in the code reference (that's the
return sub) that counter returns. Even though the enclosing scope (the call to
counter) has terminated, the returned sub has a reference to it, so it stays
around as long as the subroutine reference does. 

This means that the two different subs returned by the two calls to counter()
are completely independent, each with its own copy of $start; as you can see,
one counts from 10, the other from 20.

So in the case you specify, you might be able to do saomething like this:

sub windup {
  my $particular = shift;
  return sub {
           my ($backref,@params) = shift;
           # do stuff here ...
           if ($keep_recursing) {
              $backref->($backref,@new_params);
           }
           else {
              return ($something)
           }
   };
}

$do_it = windup(47);
&$do_it($do_it,$other,$stuff);

Note that since the closure is anonymous (that is, it only exists as a 
reference, without any entry in the symbol table), you have to pass it a 
reference to itself to make it possible for it to call itself recursively.

Perhaps this is what you're really trying to do? Note that the second example
is incomplete; $keep_recursing has to be replaced with the condition you'd use
to determine whether or not to keep recursing, and the return logic currently
only allows you to return a scalar. Further enhancements are up to you.

Check out Chapter 8, "Closures" in 3rd edition "Programming Perl", or 
Chapter 4 in the 2nd edition. If you have the first edition (the pink one),
none of this is in there, and you need a new book ASAP. :)

 --- Joe M.
--
perl -w
print((split //,"\nechle etn sJutaohrPr akr")
[map{splice @_,@_/$^F,$^W}(@_=$%..$^F*$=/5)])



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

Date: Mon, 30 Jul 2001 12:42:00 +0100
From: Paul Johnston <paul.johnston@dsvr.co.uk>
Subject: Re: SHEBANG ?
Message-Id: <3B654808.9FE0E32C@dsvr.co.uk>

Hi,

> I've got #!/usr/bin/perl and #!/usr/local/bin/perl

Covers most Unix. A common twist though is when an ISP starts with say
Perl 5.004, and doesn't want to change this in case some dumbass
customers are taking advantage of undocumented behaviour that has
changed. They install new versions of perl in something like
/usr/bin/perl5.6
 
> Presumably there are others?

C:/Perl/bin/perl.exe
C:/Program\ Files/Perl/bin/perl.exe

Paul


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

Date: Mon, 30 Jul 2001 12:54:25 +0100
From: Paul Johnston <paul.johnston@dsvr.co.uk>
Subject: Re: Striping out the string
Message-Id: <3B654AF1.48593E87@dsvr.co.uk>

Hi,

>  I'm tying to strip out everything but a file extension of a variable "$file
> = c:\files\file.exe" and I what to end up with a variable of "$file = .exe"
> I try $file =~ s/\.[^.]+$//; and that will strip out the ".exe" So shouldn't
> $file =~ s/\.[$.]+$//; strip out the "c:\files\file"

That second regex won't do what you want. 

There are two approaches you can take here:

1) Use your first regex and grab what it finds instead of stipping it
off:
   $file =~ /(\.[^.]*$)/;
   $extension = $1;

2) Use a different regex to cut off the beginning:
   $file =~ s/^.*\././;

I'd prefer approach (1) because it doesn't rely on the * operator being
greedy, and you don't have the messiness of finding all the stuff up to
the last period, and replacing it with a period.

Paul


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

Date: Mon, 30 Jul 2001 20:26:11 -0400
From: Benjamin Goldberg <goldbb2@earthlink.net>
Subject: Re: Telnet/MUD server
Message-Id: <3B65FB22.723941FD@earthlink.net>

Philip Taylor wrote:
> 
>   I'm making a text-based FPS-style Internet game (well, actually it's
> an SPS, but that's not important), which functions in a fairly similar
> way to a MUD. The server runs a Perl program, and users can connect to
> it using whatever Telnet client they want.
> 
>   Firstly, is there a module which can be used for this? I've looked
> at Net::Telnet but from its readme file, "Net::Telnet allows you to
> make client connections to a TCP port" -- I need the server rather
> than the client.

Unless you *need* to do TELNET protocol (all caps because the protocol
name is an acronym) specific actions, then you can use simple tcp
sockets, and not worry about the protocol.

>   Currently I'm using a modified version of an example I found
> somewhere on the internet (although I've forgotten where), which uses
> the Socket routines.

You will probably have an easier time of it if you use IO::Socket module
instead of Socket.

>   "Programming Perl" mentions using 'fork' to allow multiple users,
> but this opens a lot of processes, which is presumably not good if
> there are lots of simultaneous users.

Using fork is especially good when the users don't need to interact with
each other in any way... at it's simplest you accept, then fork, and
handle each user in their own process, with the seperate processes not
talking with each other, and them exiting when their done with that
particular user's needs.

For a game, a MUD, you really want all the interaction in a single
process, so everyone can talk to each other.

> The system which I'm using does it all inside the main loop -- it
> waits until one of the users has some data (with 'vec'),

It's not vec that does the waiting, it's select.  vec just puts it into
a format which select is able to use.  You would be better off using the
IO::Select module instead of vec/select.

> then receives it (with 'sysread'), then repeats.
> 
>   However, I'm not sure exactly how this works. Is all the data passed
> to the server before vec detects anything, then sysread copies the
> data immediately from memory?

vec detects nothing.  It's select that detects whether data is
available.  Anyway, when someone sends a line from their telnet program
to your server, the machine it's on (or I should say, the machine's "tcp
stack", the details of which I won't go into) recieves it and process
the tcp headers, and then makes it available to your program.  Calling
select in your program will tell if the tcp stack has some data buffered
for that particular tcp connection.  Select doesn't read anything, just
checks whether or not there's anything in the tcp buffers.  When you
call sysread, it copied the data from the tcp buffer into your program's
memory, then removed from the tcp buffer.

>   Or does vec merely know that the user has some data waiting, then
> sysread has to wait a few fractions of a second while downloading the
> information?

select tells whether or not some data is waiting.  sysread does not have
to wait in such a case -- it only blocks if you try to read when no data
is there.

> I need to avoid anything in which one user could freeze the
> server for every other user...
> 
>   The main server-related sections of the code are shown below (there
> might be a few minor bits which I accidentally removed while cutting
> out the unnecessary code, but it shows the main sections of how it
> ought to work):
> 
> use Socket;
> # Set up main server socket (S)
> $port = 1979;
> $proto = getprotobyname('tcp');
> socket(S,AF_INET,SOCK_STREAM,$proto) or die "socket: $!";
> bind(S, pack('S n a4 x8', AF_INET, $port, "\0\0\0\0")) or die "bind:$!";
> listen(S, 10) or die "listen: $!";
> 
> while (1) { # this loop repeats after each byte of input
> 
>   # Set the list of sockets to be read from
>     $rin = '';
>     # The filehandle S refers to the main 'server' socket
>     vec($rin, fileno(S), 1) = 1;
> 
>     # @sockets is a list of the socket numbers.
>     # $socket[1]=1, $socket[5]=5, etc, EXCEPT when the user has
>     # left -- in that case, $socket[_]=0

If you plan on keeping the code like this (I would suggest a major
rewrite, instead), why not do @sockets = grep $_, @sockets, each time
you assign 0 to one of the items?

>     foreach $socket (@sockets) {
>       next if ($socket == 0); # don't look at closed sockets
> 
>       # Each socket needs a unique filehandle, but these can't be just
>       # numbers, so they're 'NS' followed by the socket number
>       vec($rin, fileno('NS'.$socket), 1) = 1;
>     }
> 
>   # wait for one of the inputs to be ready
>   select($rout=$rin, undef, undef, undef);

This is ok for something like a chat client, but for a MUD, there are
things happening even when the users aren't typing... for example,
monsters attacking/moving around, people healing (if they were injured
and are resting), etc.  The third argument for select() is a timeout. 
Putting in undef means wait forever.  Puting in a numeric value means to
wait that many seconds.

> 
>   if (vec($rout, fileno(S), 1)) {
>     # A new user has connected, so set up the socket
> 
>     ++$con;
>     $sockets[$con] = $con;
>     $addr = accept('NS'.$sockets[$con], S) or die $!;
> 
>   } else {
> 
>     # Get input from each user who's got some data
>     foreach $socket (@sockets) {
>       next if $socket == 0;
>       if (vec($rout, fileno('NS'.$socket), 1)) {
>         &readInput($socket);
>       }
>     }
>   }
> }

This part is sortof ok, depending on what readInput does.

> sub readInput {
>   # Reads a byte of input from the user specified by the parameter
> 
>   my $socket = 'NS'.$_[0];
>   if ((sysread($socket, $c, 1) <= 0) or ($c eq "\n")) {
>     # end of input -- process commands
>   } else {
>     # add character to input buffer
>   }
> }

If sysread returns <= 0, then the user has closed his connection... told
telnet to exit (killed the window or whatever).  That should be handled
as a seperate case from the input being "\n".

You would be better off doing something like
	if( my $len = sysread($socket, $c, 1024) ) {
		$buffer .= $c;
	} elsif( defined( $len ) ) {
		# client closed his connection.
		# treat it similar to him typing exit.
		# Close the socket, and clean up the user's data.
	} else {
		# we got an error reading from the socket.
		# this shouldn't happen.  Print $!
		# to STDERR and to a logfile.
		# Also, we should close the socket, and
		# clean up the user's data.
	}
	while( $buffer =~ s/^([\x00-\xFF]*?)[\015\012]+// ) {
		$line = $1;
		# process $line.
	}

Don't worry about the 1024 ... sysread will only read as many bytes as
are available.  The while loop will process all complete lines, trimming
off the newlines.

>   I've had it running with about 4 users, and it seemed to work
> successfully (although there were some major bugs which I didn't
> notice, such as the server freezing between when a Microsoft Telnet
> user started and finished typing, so I might have missed some smaller
> ones too), but I want something that's I know will be reliable with
> lots of users.

A bug like that indicates that once a user starts typing, you keep
reading from him until you get a newline.  That's a bad thing to do, but
I'll admit that I don't see where in your code you're doing it.

>   I can always try things and see if they work (in fact, I'll probably
> make some computer-controlled AI bots to play against when there
> aren't many human players, and could just add a load of them in order
> to test the system), but I'd like to know if anyone has past
> experience with things like this.

Depending on what kind of MUD you want, you might make it so that
players can *only* attack the bots, not each other.  If you do this, and
if you make most monsters non-aggressive (ie, they only attack you if
you attack them), then your mud will be one where it's more or less safe
for someone to walk away from the keyboard without worrying about
getting killed.  Whether players can kill players is a design decision.
Also, how smart your bots are is another design decision (it's also
limited by your ability to code<gg>)

I would suggest that instead of coding your MUD from scratch, you go
find the FAQs for reg.games.mud.*, and see if there is already a MUD
written in perl (or in any other language you know and can code in).  If
you don't see one in the faqs, ask in the .admin or on .misc groups in
that heirarchy.  You may also be interested in rec.games.frp.* (frp
means fantasy-role-playing).  I used to play a number of muds years ago,
but I stopped when I saw how much they were eating up my time.

-- 
I need more taglines. This one is getting old.


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

Date: Mon, 30 Jul 2001 12:35:38 +0100
From: Paul Johnston <paul.johnston@dsvr.co.uk>
Subject: Re: User Authentication in Unix
Message-Id: <3B65468A.27B9E9A5@dsvr.co.uk>

Hi,

> Well, first you have to look up the crypted version of the password,

Usually:
  $passwd = (getpwnam $uname)[1];

This requires you to be root if shadow passwords are used. It will
generally still work if some more advanced password scheme is used, but
there are probably some exceptions.

> Once you have it, you use the crypt() function to encrypt the
> supposedly-correct version and then compare the crypted string you
> generated with the crypted version stored in the password file.

The salt is usually the first two characters of the encrypted password,
but there are several password encryption schemes. In most cases this
will work:

  print (crypt($entered_passwd, $encrypted_passwd) eq $encrypted_passwd)
? "ok" : "f**k off hacker";

I'm not totally convinced by the apache documentation's arguments
against doing this. You definitily should log something and do a random
sleep on an incorrect password. If your script runs as root you could
log to utmp/wtmp just as login/sshd/ftpd do. It's not hard to use a
tie()'d hash to keep track of what IP addresses were giving duff
passwords, and have a limit. The criticism that the password is
transmitted in clear text is also true of telnet, pop3 and ftp. You can
avoid it using SSL. Of course if you were really concerned about
security you'd forget all about passwords and use crypto cards instead.

Paul


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

Date: Tue, 31 Jul 2001 00:03:36 -0000
From: "B. Caligari" <bcaligari@fireforged.com>
Subject: Re: Verify upload is completed
Message-Id: <9k4lao01bks@enews3.newsguy.com>

"YMK" <gbeymk@sgh.com.sg> wrote in message
news:3B651517.CA841516@sgh.com.sg...
> Hi !
>
> I am doing the following:
> 1. upload or copy a file to a "raw_file" folder in Linux
> 2. a script to 1st verify the file size every 5 seconds
> if there is no change in file size, assume the upload is completed
> process the file and remove it from "raw_file" folder

<snip snip>

>
> Is there anyway to verify whether upload or copy is completed ?

<snip snip>

You are right in observing that NT shows the 'full size'
of the file even though it has not been fully copied over.

Assuming that if the file doesn't change in size
is also assuming that there were no network errors,
etc.  How about uploading the file to a temporary
filename, and renaming it to the original filename
from the uploading side once the transfer is complete?

B




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

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
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.  

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 V10 Issue 1412
***************************************


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