diff options
author | Andy Dougherty <doughera.lafayette.edu> | 1995-12-21 00:01:16 +0000 |
---|---|---|
committer | Andy Dougherty <doughera.lafayette.edu> | 1995-12-21 00:01:16 +0000 |
commit | cb1a09d0194fed9b905df7b04a4bc031d354609d (patch) | |
tree | f0c890a5a8f5274873421ac573dfc719188e5eec /ext | |
parent | 3712091946b37b5feabcc1f630b32639406ad717 (diff) | |
download | perl-cb1a09d0194fed9b905df7b04a4bc031d354609d.tar.gz |
This is patch.2b1g to perl5.002beta1.
cd to your perl source directory, and type
patch -p1 -N < patch.2b1g
This patch is just my packaging of Tom's documentation patches
he released as patch.2b1g.
Patch and enjoy,
Andy Dougherty doughera@lafcol.lafayette.edu
Dept. of Physics
Lafayette College, Easton PA 18042
Diffstat (limited to 'ext')
-rw-r--r-- | ext/DB_File/DB_File.pm | 79 | ||||
-rw-r--r-- | ext/POSIX/POSIX.pm | 12 | ||||
-rw-r--r-- | ext/POSIX/POSIX.pod | 351 | ||||
-rw-r--r-- | ext/Safe/Makefile.PL | 2 | ||||
-rw-r--r-- | ext/Safe/Safe.pm | 387 | ||||
-rw-r--r-- | ext/Safe/Safe.xs | 113 | ||||
-rw-r--r-- | ext/Socket/Socket.pm | 3 |
7 files changed, 915 insertions, 32 deletions
diff --git a/ext/DB_File/DB_File.pm b/ext/DB_File/DB_File.pm index 55e5e9fe7a..08463dfabc 100644 --- a/ext/DB_File/DB_File.pm +++ b/ext/DB_File/DB_File.pm @@ -528,25 +528,84 @@ Here is the output from the code above. untie @h ; +=head2 Locking Databases -=head1 CHANGES +Concurrent access of a read-write database by several parties requires +them all to use some kind of locking. Here's an example of Tom's that +uses the I<fd> method to get the file descriptor, and then a careful +open() to give something Perl will flock() for you. Run this repeatedly +in the background to watch the locks granted in proper order. -=head2 0.1 + use Fcntl; + use DB_File; + + use strict; + + sub LOCK_SH { 1 } + sub LOCK_EX { 2 } + sub LOCK_NB { 4 } + sub LOCK_UN { 8 } + + my($oldval, $fd, $db, %db, $value, $key); + + $key = shift || 'default'; + $value = shift || 'magic'; + + $value .= " $$"; + + $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0644) + || die "dbcreat /tmp/foo.db $!"; + $fd = $db->fd; + print "$$: db fd is $fd\n"; + open(DB_FH, "+<&=$fd") || die "dup $!"; + + + unless (flock (DB_FH, LOCK_SH | LOCK_NB)) { + print "$$: CONTENTION; can't read during write update! + Waiting for read lock ($!) ...."; + unless (flock (DB_FH, LOCK_SH)) { die "flock: $!" } + } + print "$$: Read lock granted\n"; + + $oldval = $db{$key}; + print "$$: Old value was $oldval\n"; + flock(DB_FH, LOCK_UN); + + unless (flock (DB_FH, LOCK_EX | LOCK_NB)) { + print "$$: CONTENTION; must have exclusive lock! + Waiting for write lock ($!) ...."; + unless (flock (DB_FH, LOCK_EX)) { die "flock: $!" } + } + + print "$$: Write lock granted\n"; + $db{$key} = $value; + sleep 10; + + flock(DB_FH, LOCK_UN); + untie %db; + close(DB_FH); + print "$$: Updated db to $key=$value\n"; + +=head1 HISTORY + +=over + +=item 0.1 First Release. -=head2 0.2 +=item 0.2 When B<DB_File> is opening a database file it no longer terminates the process if I<dbopen> returned an error. This allows file protection errors to be caught at run time. Thanks to Judith Grass -<grass@cybercash.com> for spotting the bug. +E<lt>grass@cybercash.comE<gt> for spotting the bug. -=head2 0.3 +=item 0.3 Added prototype support for multiple btree compare callbacks. -=head2 1.0 +=item 1.0 B<DB_File> has been in use for over a year. To reflect that, the version number has been incremented to 1.0. @@ -556,7 +615,7 @@ Added complete support for multiple concurrent callbacks. Using the I<push> method on an empty list didn't work properly. This has been fixed. -=head2 1.01 +=item 1.01 Fixed a core dump problem with SunOS. @@ -583,8 +642,10 @@ suggest any enhancements, I would welcome your comments. =head1 AVAILABILITY -Berkeley DB is available via the hold C<ftp.cs.berkeley.edu> in the -directory C</ucb/4bsd/db.tar.gz>. It is I<not> under the GPL. +Berkeley DB is available at your nearest CPAN archive (see +L<perlmod/"CPAN"> for a list) in F<src/misc/db.1.85.tar.gz>, or via the +host F<ftp.cs.berkeley.edu> in F</ucb/4bsd/db.tar.gz>. It is I<not> under +the GPL. =head1 SEE ALSO diff --git a/ext/POSIX/POSIX.pm b/ext/POSIX/POSIX.pm index 2c397bb5ab..ee35ea20fb 100644 --- a/ext/POSIX/POSIX.pm +++ b/ext/POSIX/POSIX.pm @@ -830,17 +830,13 @@ sub umask { } sub wait { - usage "wait(statusvariable)" if @_ != 1; - local $result = wait(); - $_[0] = $?; - $result; + usage "wait()" if @_ != 0; + wait(); } sub waitpid { - usage "waitpid(pid, statusvariable, options)" if @_ != 3; - local $result = waitpid($_[0], $_[2]); - $_[1] = $?; - $result; + usage "waitpid(pid, options)" if @_ != 2; + waitpid($_[0], $_[1]); } sub gmtime { diff --git a/ext/POSIX/POSIX.pod b/ext/POSIX/POSIX.pod index 654028e2dd..2549a613ac 100644 --- a/ext/POSIX/POSIX.pod +++ b/ext/POSIX/POSIX.pod @@ -2,6 +2,19 @@ POSIX - Perl interface to IEEE Std 1003.1 +=head1 SYNOPSIS + + use POSIX; + use POSIX qw(setsid); + use POSIX qw(:errno_h :fcntl_h); + + printf "EINTR is %d\n", EINTR; + + $sess_id = POSIX::setsid(); + + $fd = POSIX::open($path, O_CREAT|O_EXCL|O_WRONLY, 0644); + # note: that's a filedescriptor, *NOT* a filehandle + =head1 DESCRIPTION The POSIX module permits you to access all (or nearly all) the standard @@ -22,15 +35,6 @@ and other miscellaneous objects. The remaining sections list various constants and macros in an organization which roughly follows IEEE Std 1003.1b-1993. -=head1 EXAMPLES - - printf "EINTR is %d\n", EINTR; - - $sess_id = POSIX::setsid(); - - $fd = POSIX::open($path, O_CREAT|O_EXCL|O_WRONLY, 0644); - # note: that's a filedescriptor, *NOT* a filehandle - =head1 NOTE The POSIX module is probably the most complex Perl module supplied with @@ -99,6 +103,7 @@ This is identical to the C function C<asin()>. =item assert +Unimplemented. =item atan @@ -158,6 +163,11 @@ This is identical to the C function C<clock()>. =item close +Close the file. This uses file descriptors such as those obtained by calling +C<POSIX::open>. + + $fd = POSIX::open( "foo", &POSIX::O_RDONLY ); + POSIX::close( $fd ); Returns C<undef> on failure. @@ -175,10 +185,15 @@ This is identical to the C function C<cosh()>. =item creat +Create a new file. This returns a file descriptor like the ones returned by +C<POSIX::open>. Use C<POSIX::close> to close the file. + + $fd = POSIX::creat( "foo", 0611 ); + POSIX::close( $fd ); =item ctermid -Generates the path name for controlling terminal. +Generates the path name for the controlling terminal. $path = POSIX::ctermid(); @@ -202,11 +217,19 @@ div() is C-specific. =item dup +This is similar to the C function C<dup()>. + +This uses file descriptors such as those obtained by calling +C<POSIX::open>. Returns C<undef> on failure. =item dup2 +This is similar to the C function C<dup2()>. + +This uses file descriptors such as those obtained by calling +C<POSIX::open>. Returns C<undef> on failure. @@ -310,6 +333,14 @@ This is identical to Perl's builtin C<fork()> function. =item fpathconf +Retrieves the value of a configurable limit on a file or directory. This +uses file descriptors such as those obtained by calling C<POSIX::open>. + +The following will determine the maximum length of the longest allowable +pathname on the filesystem which holds C</tmp/foo>. + + $fd = POSIX::open( "/tmp/foo", &POSIX::O_RDONLY ); + $path_max = POSIX::fpathconf( $fd, &POSIX::_PC_PATH_MAX ); Returns C<undef> on failure. @@ -339,6 +370,9 @@ freopen() is C-specific--use open instead. =item frexp +Return the mantissa and exponent of a floating-point number. + + ($mantissa, $exponent) = POSIX::frexp( 3.14 ); =item fscanf @@ -354,6 +388,12 @@ Use method C<FileHandle::setpos()> instead. =item fstat +Get file status. This uses file descriptors such as those obtained by +calling C<POSIX::open>. The data returned is identical to the data from +Perl's builtin C<stat> function. + + $fd = POSIX::open( "foo", &POSIX::O_RDONLY ); + @stats = POSIX::fstat( $fd ); =item ftell @@ -441,9 +481,13 @@ This is identical to Perl's builtin C<gmtime()> function. =item isalnum +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item isalpha +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item isatty @@ -452,30 +496,48 @@ to a tty. =item iscntrl +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item isdigit +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item isgraph +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item islower +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item isprint +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item ispunct +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item isspace +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item isupper +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item isxdigit +This is identical to the C function, except that it can apply to a single +character or to a whole string. =item kill @@ -499,6 +561,32 @@ This is identical to Perl's builtin C<link()> function. =item localeconv +Get numeric formatting information. Returns a reference to a hash +containing the current locale formatting values. + +The database for the B<de> (Deutsch or German) locale. + + $loc = POSIX::setlocale( &POSIX::LC_ALL, "de" ); + print "Locale = $loc\n"; + $lconv = POSIX::localeconv(); + print "decimal_point = ", $lconv->{decimal_point}, "\n"; + print "thousands_sep = ", $lconv->{thousands_sep}, "\n"; + print "grouping = ", $lconv->{grouping}, "\n"; + print "int_curr_symbol = ", $lconv->{int_curr_symbol}, "\n"; + print "currency_symbol = ", $lconv->{currency_symbol}, "\n"; + print "mon_decimal_point = ", $lconv->{mon_decimal_point}, "\n"; + print "mon_thousands_sep = ", $lconv->{mon_thousands_sep}, "\n"; + print "mon_grouping = ", $lconv->{mon_grouping}, "\n"; + print "positive_sign = ", $lconv->{positive_sign}, "\n"; + print "negative_sign = ", $lconv->{negative_sign}, "\n"; + print "int_frac_digits = ", $lconv->{int_frac_digits}, "\n"; + print "frac_digits = ", $lconv->{frac_digits}, "\n"; + print "p_cs_precedes = ", $lconv->{p_cs_precedes}, "\n"; + print "p_sep_by_space = ", $lconv->{p_sep_by_space}, "\n"; + print "n_cs_precedes = ", $lconv->{n_cs_precedes}, "\n"; + print "n_sep_by_space = ", $lconv->{n_sep_by_space}, "\n"; + print "p_sign_posn = ", $lconv->{p_sign_posn}, "\n"; + print "n_sign_posn = ", $lconv->{n_sign_posn}, "\n"; =item localtime @@ -518,6 +606,11 @@ longjmp() is C-specific: use die instead. =item lseek +Move the read/write file pointer. This uses file descriptors such as +those obtained by calling C<POSIX::open>. + + $fd = POSIX::open( "foo", &POSIX::O_RDONLY ); + $off_t = POSIX::lseek( $fd, 0, &POSIX::SEEK_SET ); Returns C<undef> on failure. @@ -527,12 +620,15 @@ malloc() is C-specific. =item mblen +This is identical to the C function C<mblen()>. =item mbstowcs +This is identical to the C function C<mbstowcs()>. =item mbtowc +This is identical to the C function C<mbtowc()>. =item memchr @@ -560,19 +656,40 @@ This is identical to Perl's builtin C<mkdir()> function. =item mkfifo +This is similar to the C function C<mkfifo()>. Returns C<undef> on failure. =item mktime +Convert date/time info to a calendar time. + +Synopsis: + + mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0) + +The month (C<mon>), weekday (C<wday>), and yearday (C<yday>) begin at zero. +I.e. January is 0, not 1; Sunday is 0, not 1; January 1st is 0, not 1. The +year (C<year>) is given in years since 1900. I.e. The year 1995 is 95; the +year 2001 is 101. Consult your system's C<mktime()> manpage for details +about these and the other arguments. + +Calendar time for December 12, 1995, at 10:30 am. + + $time_t = POSIX::mktime( 0, 30, 10, 12, 11, 95 ); + print "Date = ", POSIX::ctime($time_t); Returns C<undef> on failure. =item modf +Return the integral and fractional parts of a floating-point number. + + ($fractional, $integral) = POSIX::modf( 3.14 ); =item nice +This is similar to the C function C<nice()>. Returns C<undef> on failure. @@ -582,11 +699,36 @@ offsetof() is C-specific. =item open +Open a file for reading for writing. This returns file descriptors, not +Perl filehandles. Use C<POSIX::close> to close the file. + +Open a file read-only with mode 0666. + + $fd = POSIX::open( "foo" ); + +Open a file for read and write. + + $fd = POSIX::open( "foo", &POSIX::O_RDWR ); + +Open a file for write, with truncation. + + $fd = POSIX::open( "foo", &POSIX::O_WRONLY | &POSIX::O_TRUNC ); + +Create a new file with mode 0640. Set up the file for writing. + + $fd = POSIX::open( "foo", &POSIX::O_CREAT | &POSIX::O_WRONLY, 0640 ); Returns C<undef> on failure. =item opendir +Open a directory for reading. + + $dir = POSIX::opendir( "/tmp" ); + @files = POSIX::readdir( $dir ); + POSIX::closedir( $dir ); + +Returns C<undef> on failure. =item pathconf @@ -611,6 +753,12 @@ This is identical to the C function C<perror()>. =item pipe +Create an interprocess channel. This returns file descriptors like those +returned by C<POSIX::open>. + + ($fd0, $fd1) = POSIX::pipe(); + POSIX::write( $fd0, "hello", 5 ); + POSIX::read( $fd1, $buf, 5 ); =item pow @@ -648,6 +796,12 @@ rand() is non-portable, use Perl's rand instead. =item read +Read from a file. This uses file descriptors such as those obtained by +calling C<POSIX::open>. If the buffer C<$buf> is not large enough for the +read then Perl will extend it to make room for the request. + + $fd = POSIX::open( "foo", &POSIX::O_RDONLY ); + $bytes = POSIX::read( $fd, $buf, 3 ); Returns C<undef> on failure. @@ -701,6 +855,7 @@ The following will set the traditional UNIX system locale behavior. =item setpgid +This is similar to the C function C<setpgid()>. Returns C<undef> on failure. @@ -714,6 +869,13 @@ Sets the real user id for this process. =item sigaction +Detailed signal management. This uses C<POSIX::SigAction> objects for the +C<action> and C<oldaction> arguments. Consult your system's C<sigaction> +manpage for details. + +Synopsis: + + sigaction(sig, action, oldaction = 0) Returns C<undef> on failure. @@ -723,11 +885,25 @@ siglongjmp() is C-specific: use die instead. =item sigpending +Examine signals that are blocked and pending. This uses C<POSIX::SigSet> +objects for the C<sigset> argument. Consult your system's C<sigpending> +manpage for details. + +Synopsis: + + sigpending(sigset) Returns C<undef> on failure. =item sigprocmask +Change and/or examine calling process's signal mask. This uses +C<POSIX::SigSet> objects for the C<sigset> and C<oldsigset> arguments. +Consult your system's C<sigprocmask> manpage for details. + +Synopsis: + + sigprocmask(how, sigset, oldsigset = 0) Returns C<undef> on failure. @@ -737,6 +913,13 @@ sigsetjmp() is C-specific: use eval {} instead. =item sigsuspend +Install a signal mask and suspend process until signal arrives. This uses +C<POSIX::SigSet> objects for the C<signal_mask> argument. Consult your +system's C<sigsuspend> manpage for details. + +Synopsis: + + sigsuspend(signal_mask) Returns C<undef> on failure. @@ -754,6 +937,7 @@ This is identical to Perl's builtin C<sleep()> function. =item sprintf +This is identical to Perl's builtin C<sprintf()> function. =item sqrt @@ -801,6 +985,22 @@ Returns the error string for the specified errno. =item strftime +Convert date and time information to string. Returns the string. + +Synopsis: + + strftime(fmt, sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0) + +The month (C<mon>), weekday (C<wday>), and yearday (C<yday>) begin at zero. +I.e. January is 0, not 1; Sunday is 0, not 1; January 1st is 0, not 1. The +year (C<year>) is given in years since 1900. I.e. The year 1995 is 95; the +year 2001 is 101. Consult your system's C<strftime()> manpage for details +about these and the other arguments. + +The string for Tuesday, December 12, 1995. + + $str = POSIX::strftime( "%A, %B %d, %Y", 0, 0, 0, 12, 11, 95, 2 ); + print "$str\n"; =item strlen @@ -852,6 +1052,9 @@ strtol() is C-specific. =item strxfrm +String transformation. Returns the transformed string. + + $dst = POSIX::strxfrm( $src ); =item sysconf @@ -877,16 +1080,19 @@ This is identical to the C function C<tanh()>. =item tcdrain +This is similar to the C function C<tcdrain()>. Returns C<undef> on failure. =item tcflow +This is similar to the C function C<tcflow()>. Returns C<undef> on failure. =item tcflush +This is similar to the C function C<tcflush()>. Returns C<undef> on failure. @@ -896,11 +1102,13 @@ This is identical to the C function C<tcgetpgrp()>. =item tcsendbreak +This is similar to the C function C<tcsendbreak()>. Returns C<undef> on failure. =item tcsetpgrp +This is similar to the C function C<tcsetpgrp()>. Returns C<undef> on failure. @@ -940,9 +1148,14 @@ This is identical to Perl's builtin C<uc()> function. =item ttyname +This is identical to the C function C<ttyname()>. =item tzname +Retrieves the time conversion information from the C<tzname> variable. + + POSIX::tzset(); + ($std, $dst) = POSIX::tzname(); =item tzset @@ -954,6 +1167,9 @@ This is identical to Perl's builtin C<umask()> function. =item uname +Get name of current operating system. + + ($sysname, $nodename, $release, $version, $machine ) = POSIX::uname(); =item ungetc @@ -981,18 +1197,32 @@ vsprintf() is C-specific. =item wait +This is identical to Perl's builtin C<wait()> function. =item waitpid +Wait for a child process to change state. This is identical to Perl's +builtin C<waitpid()> function. + + $pid = POSIX::waitpid( -1, &POSIX::WNOHANG ); + print "status = ", ($? / 256), "\n"; =item wcstombs +This is identical to the C function C<wcstombs()>. =item wctomb +This is identical to the C function C<wctomb()>. =item write +Write to a file. This uses file descriptors such as those obtained by +calling C<POSIX::open>. + + $fd = POSIX::open( "foo", &POSIX::O_WRONLY ); + $buf = "hello"; + $bytes = POSIX::write( $b, $buf, 5 ); Returns C<undef> on failure. @@ -1006,50 +1236,119 @@ Returns C<undef> on failure. =item new +Open a file and return a Perl filehandle. The first parameter is the +filename and the second parameter is the mode. The mode should be specified +as C<a> for append, C<w> for write, and E<lt> or C<""> for read. + +Open a file for reading. + + $fh = FileHandle->new( "foo", "" ); + die "Unable to open foo for reading" unless $fh; + +Open a file for writing. + + $fh = FileHandle->new( "foo", "w" ); + die "Unable to open foo for writing" unless $fh; + +Use C<FileHandle::close()> to close the file or let the FileHandle object's +destructor perform the close. =item clearerr +Resets the error indicator and EOF indicator to zero. + + $fh->clearerr; =item close +Close the file. + + $fh->close; =item eof +Tests for end of file. + + if( $fh->eof ){ + print "end of file\n"; + } =item error +Returns non-zero if there has been an error while reading or writing a file. + + if( $fh->error ){ + print "error\n"; + } =item fileno +Returns the integer file descriptor associated with the file. + + $fileno = $fh->fileno; =item flush +Flush the stream. + + $fh->flush; Returns C<undef> on failure. =item getc +Get a character from the stream. + + $ch = $fh->getc; =item getpos +Retrieve the file pointer position. The returned value can be used as an +argument to C<setpos()>. + + $pos = $fh->getpos; =item gets +Retrieve a line from the open file. + + $line = $fh->gets; =item new_from_fd +Open a file using a file descriptor. Return a Perl filehandle. The first +parameter should be a file descriptor, which can come from C<POSIX::open()>. +The second parameter, the mode, should be C<a> for append, C<w> for write, +and E<lt> or C<""> for read. The mode should match the mode which was used +when the file descriptor was created. + + $fd = POSIX::open( "typemap" ); + $fh = FileHandle->new_from_fd( $fd, "<" ); + die "FileHandle failed" unless $fh; =item new_tmpfile +Creates a temporary file, opens it for writing, and returns a Perl +filehandle. Consult your system's C<tmpfile()> manpage for details. + + $fh = FileHandle->new_tmpfile; + die "FileHandle failed" unless $fh; =item seek +Reposition file pointer. + + $fh->seek( 2, &POSIX::SEEK_SET ); =item setbuf =item setpos +Set the file pointer position. + + $pos = $fh->getpos; + $fh->setpos( $pos ); Returns C<undef> on failure. @@ -1060,6 +1359,9 @@ Returns C<undef> on failure. =item tell +Returns the current file position, in bytes. + + $pos = $fh->tell; =item ungetc @@ -1072,8 +1374,17 @@ Returns C<undef> on failure. =item new -Creates a new SigAction object. This object will be destroyed automatically -when it is no longer needed. +Creates a new C<POSIX::SigAction> object which corresponds to the C +C<struct sigaction>. This object will be destroyed automatically when it is +no longer needed. The first parameter is the fully-qualified name of a sub +which is a signal-handler. The second parameter is a C<POSIX::SigSet> +object. The third parameter contains the C<sa_flags>. + + $sigset = POSIX::SigSet->new; + $sigaction = POSIX::SigAction->new( 'main::handler', $sigset, &POSIX::SA_NOCLDSTOP ); + +This C<POSIX::SigAction> object should be used with the C<POSIX::sigaction()> +function. =back @@ -1150,6 +1461,15 @@ when it is no longer needed. =item getattr +Get terminal control attributes. + +Obtain the attributes for stdin. + + $termios->getattr() + +Obtain the attributes for stdout. + + $termios->getattr( 1 ) Returns C<undef> on failure. @@ -1198,6 +1518,11 @@ Retrieve the output baud rate. =item setattr +Set terminal control attributes. + +Set attributes immediately for stdout. + + $termios->setattr( 1, &POSIX::TCSANOW ); Returns C<undef> on failure. @@ -1448,5 +1773,5 @@ WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG WIFSTOPPED WSTOPSIG =head1 CREATION -This document generated by mkposixman.PL version 951129. +This document generated by ./mkposixman.PL version 19951212. diff --git a/ext/Safe/Makefile.PL b/ext/Safe/Makefile.PL new file mode 100644 index 0000000000..414df14f22 --- /dev/null +++ b/ext/Safe/Makefile.PL @@ -0,0 +1,2 @@ +use ExtUtils::MakeMaker; +WriteMakefile(); diff --git a/ext/Safe/Safe.pm b/ext/Safe/Safe.pm new file mode 100644 index 0000000000..dc2f9e9f9b --- /dev/null +++ b/ext/Safe/Safe.pm @@ -0,0 +1,387 @@ +package Safe; +require Exporter; +require DynaLoader; +use Carp; +@ISA = qw(Exporter DynaLoader); +@EXPORT_OK = qw(op_mask ops_to_mask mask_to_ops opcode opname + MAXO emptymask fullmask); + +=head1 NAME + +Safe - Safe extension module for Perl + +=head1 DESCRIPTION + +The Safe extension module allows the creation of compartments +in which perl code can be evaluated. Each compartment has + +=over 8 + +=item a new namespace + +The "root" of the namespace (i.e. "main::") is changed to a +different package and code evaluated in the compartment cannot +refer to variables outside this namespace, even with run-time +glob lookups and other tricks. Code which is compiled outside +the compartment can choose to place variables into (or share +variables with) the compartment's namespace and only that +data will be visible to code evaluated in the compartment. + +By default, the only variables shared with compartments are the +"underscore" variables $_ and @_ (and, technically, the much less +frequently used %_, the _ filehandle and so on). This is because +otherwise perl operators which default to $_ will not work and neither +will the assignment of arguments to @_ on subroutine entry. + +=item an operator mask + +Each compartment has an associated "operator mask". Recall that +perl code is compiled into an internal format before execution. +Evaluating perl code (e.g. via "eval" or "do 'file'") causes +the code to be compiled into an internal format and then, +provided there was no error in the compilation, executed. +Code evaulated in a compartment compiles subject to the +compartment's operator mask. Attempting to evaulate code in a +compartment which contains a masked operator will cause the +compilation to fail with an error. The code will not be executed. + +By default, the operator mask for a newly created compartment masks +out all operations which give "access to the system" in some sense. +This includes masking off operators such as I<system>, I<open>, +I<chown>, and I<shmget> but does not mask off operators such as +I<print>, I<sysread> and I<E<lt>HANDLE<gt>>. Those file operators +are allowed since for the code in the compartment to have access +to a filehandle, the code outside the compartment must have explicitly +placed the filehandle variable inside the compartment. + +Since it is only at the compilation stage that the operator mask +applies, controlled access to potentially unsafe operations can +be achieved by having a handle to a wrapper subroutine (written +outside the compartment) placed into the compartment. For example, + + $cpt = new Safe; + sub wrapper { + # vet arguments and perform potentially unsafe operations + } + $cpt->share('&wrapper'); + +=back + +=head2 Operator masks + +An operator mask exists at user-level as a string of bytes of length +MAXO, each of which is either 0x00 or 0x01. Here, MAXO is the number +of operators in the current version of perl. The subroutine MAXO() +(available for export by package Safe) returns the number of operators +in the current version of perl. Note that, unlike the beta versions of +the Safe extension, this is a reliable count of the number of +operators in the currently running perl executable. The presence of a +0x01 byte at offset B<n> of the string indicates that operator number +B<n> should be masked (i.e. disallowed). The Safe extension makes +available routines for converting from operator names to operator +numbers (and I<vice versa>) and for converting from a list of operator +names to the corresponding mask (and I<vice versa>). + +=head2 Methods in class Safe + +To create a new compartment, use + + $cpt = new Safe; + +Optional arguments are (NAMESPACE, MASK), where + +=over 8 + +=item NAMESPACE + +is the root namespace to use for the compartment (defaults to +"Safe::Root000000000", auto-incremented for each new compartment); and + +=item MASK + +is the operator mask to use (defaults to a fairly restrictive set). + +=back + +The following methods can then be used on the compartment +object returned by the above constructor. The object argument +is implicit in each case. + +=over 8 + +=item root (NAMESPACE) + +This is a get-or-set method for the compartment's namespace. With the +NAMESPACE argument present, it sets the root namespace for the +compartment. With no NAMESPACE argument present, it returns the +current root namespace of the compartment. + +=item mask (MASK) + +This is a get-or-set method for the compartment's operator mask. +With the MASK argument present, it sets the operator mask for the +compartment. With no MASK argument present, it returns the +current operator mask of the compartment. + +=item trap (OP, ...) + +This sets bits in the compartment's operator mask corresponding +to each operator named in the list of arguments. Each OP can be +either the name of an operation or its number. See opcode.h or +opcode.pl in the main perl distribution for a canonical list of +operator names. + +=item untrap (OP, ...) + +This resets bits in the compartment's operator mask corresponding +to each operator named in the list of arguments. Each OP can be +either the name of an operation or its number. See opcode.h or +opcode.pl in the main perl distribution for a canonical list of +operator names. + +=item share (VARNAME, ...) + +This shares the variable(s) in the argument list with the compartment. +Each VARNAME must be the B<name> of a variable with a leading type +identifier included. Examples of legal variable names are '$foo' for +a scalar, '@foo' for an array, '%foo' for a hash, '&foo' for a +subroutine and '*foo' for a glob (i.e. all symbol table entries +associated with "foo", including scalar, array, hash, sub and filehandle). + +=item varglob (VARNAME) + +This returns a glob for the symbol table entry of VARNAME in the package +of the compartment. VARNAME must be the B<name> of a variable without +any leading type marker. For example, + + $cpt = new Safe 'Root'; + $Root::foo = "Hello world"; + # Equivalent version which doesn't need to know $cpt's package name: + ${$cpt->varglob('foo')} = "Hello world"; + + +=item reval (STRING) + +This evaluates STRING as perl code inside the compartment. The code +can only see the compartment's namespace (as returned by the B<root> +method). Any attempt by code in STRING to use an operator which is +in the compartment's mask will cause an error (at run-time of the +main program but at compile-time for the code in STRING). The error +is of the form "%s trapped by operation mask operation...". If an +operation is trapped in this way, then the code in STRING will not +be executed. If such a trapped operation occurs or any other +compile-time or return error, then $@ is set to the error message, +just as with an eval(). If there is no error, then the method returns +the value of the last expression evaluated, or a return statement may +be used, just as with subroutines and B<eval()>. Note that this +behaviour differs from the beta distribution of the Safe extension +where earlier versions of perl made it hard to mimic the return +behaviour of the eval() command. + +=item rdo (FILENAME) + +This evaluates the contents of file FILENAME inside the compartment. +See above documentation on the B<reval> method for further details. + +=back + +=head2 Subroutines in package Safe + +The Safe package contains subroutines for manipulating operator +names and operator masks. All are available for export by the package. +The canonical list of operator names is the contents of the array +op_name defined and initialised in file F<opcode.h> of the Perl +source distribution. + +=over 8 + +=item ops_to_mask (OP, ...) + +This takes a list of operator names and returns an operator mask +with precisely those operators masked. + +=item mask_to_ops (MASK) + +This takes an operator mask and returns a list of operator names +corresponding to those operators which are masked in MASK. + +=item opcode (OP, ...) + +This takes a list of operator names and returns the corresponding +list of opcodes (which can then be used as byte offsets into a mask). + +=item opname (OP, ...) + +This takes a list of opcodes and returns the corresponding list of +operator names. + +=item fullmask + +This just returns a mask which has all operators masked. +It returns the string "\1" x MAXO(). + +=item emptymask + +This just returns a mask which has all operators unmasked. +It returns the string "\0" x MAXO(). This is useful if you +want a compartment to make use of the namespace protection +features but do not want the default restrictive mask. + +=item MAXO + +This returns the number of operators (and hence the length of an +operator mask). Note that, unlike the beta distributions of the +Safe extension, this is derived from a genuine integer variable +in the perl executable and not from a preprocessor constant. +This means that the Safe extension is more robust in the presence +of mismatched versions of the perl executable and the Safe extension. + +=item op_mask + +This returns the operator mask which is actually in effect at the +time the invocation to the subroutine is compiled. In general, +this is probably not terribly useful. + +=back + +=head2 AUTHOR + +Malcolm Beattie, mbeattie@sable.ox.ac.uk. + +=cut + +my $safes = "1111111111111111111111101111111111111111111111111111111111111111" + . "1111111111111111111111111111111111111111111111111111111111111111" + . "1111110011111111111011111111111111111111111111111111111101001010" + . "0110111111111111111111110011111111100001000000000000000000000100" + . "0000000000000111110000001111111110100000000000001111111111111111" + . "11111111111111111110"; + +my $default_root = 'Safe::Root000000000'; + +sub new { + my($class, $root, $mask) = @_; + my $obj = {}; + bless $obj, $class; + $obj->root(defined($root) ? $root : $default_root++); + $obj->mask(defined($mask) ? $mask : $default_mask); + # We must share $_ and @_ with the compartment or else ops such + # as split, length and so on won't default to $_ properly, nor + # will passing argument to subroutines work (via @_). In fact, + # for reasons I don't completely understand, we need to share + # the whole glob *_ rather than $_ and @_ separately, otherwise + # @_ in non default packages within the compartment don't work. + *{$obj->root . "::_"} = *_; + return $obj; +} + +sub root { + my $obj = shift; + if (@_) { + $obj->{Root} = $_[0]; + } else { + return $obj->{Root}; + } +} + +sub mask { + my $obj = shift; + if (@_) { + $obj->{Mask} = verify_mask($_[0]); + } else { + return $obj->{Mask}; + } +} + +sub verify_mask { + my($mask) = @_; + if (length($mask) != MAXO() || $mask !~ /^[\0\1]+$/) { + croak("argument is not a mask"); + } + return $mask; +} + +sub trap { + my $obj = shift; + $obj->setmaskel("\1", @_); +} + +sub untrap { + my $obj = shift; + $obj->setmaskel("\0", @_); +} + +sub emptymask { "\0" x MAXO() } +sub fullmask { "\1" x MAXO() } + +sub setmaskel { + my $obj = shift; + my $val = shift; + croak("bad value for mask element") unless $val eq "\0" || $val eq "\1"; + my $maskref = \$obj->{Mask}; + my ($op, $opcode); + foreach $op (@_) { + $opcode = ($op =~ /^\d/) ? $op : opcode($op); + substr($$maskref, $opcode, 1) = $val; + } +} + +sub share { + my $obj = shift; + my $root = $obj->root(); + my ($arg); + foreach $arg (@_) { + my $var; + ($var = $arg) =~ s/^(.)//; + my $caller = caller; + *{$root."::$var"} = ($1 eq '$') ? \${$caller."::$var"} + : ($1 eq '@') ? \@{$caller."::$var"} + : ($1 eq '%') ? \%{$caller."::$var"} + : ($1 eq '*') ? *{$caller."::$var"} + : ($1 eq '&') ? \&{$caller."::$var"} + : croak(qq(No such variable type for "$1$var")); + } +} + +sub varglob { + my ($obj, $var) = @_; + return *{$obj->root()."::$var"}; +} + +sub reval { + my ($obj, $expr) = @_; + my $root = $obj->{Root}; + my $mask = $obj->{Mask}; + verify_mask($mask); + + my $evalsub = eval sprintf(<<'EOT', $root); + package %s; + sub { + eval $expr; + } +EOT + return safe_call_sv($root, $mask, $evalsub); +} + +sub rdo { + my ($obj, $file) = @_; + my $root = $obj->{Root}; + my $mask = $obj->{Mask}; + verify_mask($mask); + + $file =~ s/"/\\"/g; # just in case the filename contains any double quotes + my $evalsub = eval sprintf(<<'EOT', $root, $file); + package %s; + sub { + do "%s"; + } +EOT + return safe_call_sv($root, $mask, $evalsub); +} + +bootstrap Safe; + +$safes .= "0" x (MAXO() - length($safes)); +($default_mask = $safes) =~ tr/01/\1\0/; # invert for mask + +1; diff --git a/ext/Safe/Safe.xs b/ext/Safe/Safe.xs new file mode 100644 index 0000000000..4437284932 --- /dev/null +++ b/ext/Safe/Safe.xs @@ -0,0 +1,113 @@ +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +MODULE = Safe PACKAGE = Safe + +void +safe_call_sv(package, mask, codesv) + char * package + SV * mask + SV * codesv + CODE: + int i; + char *str; + STRLEN len; + + ENTER; + SAVETMPS; + save_hptr(&defstash); + save_aptr(&endav); + SAVEPPTR(op_mask); + Newz(666, op_mask, maxo, char); + SAVEFREEPV(op_mask); + str = SvPV(mask, len); + if (maxo != len) + croak("Bad mask length"); + for (i = 0; i < maxo; i++) + op_mask[i] = str[i]; + defstash = gv_stashpv(package, TRUE); + endav = (AV*)sv_2mortal((SV*)newAV()); /* Ignore END blocks for now */ + GvHV(gv_fetchpv("main::", TRUE, SVt_PVHV)) = defstash; + PUSHMARK(sp); + i = perl_call_sv(codesv, G_SCALAR|G_EVAL|G_KEEPERR); + SPAGAIN; + ST(0) = i ? newSVsv(POPs) : &sv_undef; + PUTBACK; + FREETMPS; + LEAVE; + sv_2mortal(ST(0)); + +void +op_mask() + CODE: + ST(0) = sv_newmortal(); + if (op_mask) + sv_setpvn(ST(0), op_mask, maxo); + +void +mask_to_ops(mask) + SV * mask + PPCODE: + STRLEN len; + char *maskstr = SvPV(mask, len); + int i; + if (maxo != len) + croak("Bad mask length"); + for (i = 0; i < maxo; i++) + if (maskstr[i]) + XPUSHs(sv_2mortal(newSVpv(op_name[i], 0))); + +void +ops_to_mask(...) + CODE: + int i, j; + char *mask, *op; + Newz(666, mask, maxo, char); + for (i = 0; i < items; i++) + { + op = SvPV(ST(i), na); + for (j = 0; j < maxo && strNE(op, op_name[j]); j++) /* nothing */ ; + if (j < maxo) + mask[j] = 1; + else + { + Safefree(mask); + croak("bad op name \"%s\" in mask", op); + } + } + ST(0) = sv_newmortal(); + sv_usepvn(ST(0), mask, maxo); + +void +opname(...) + PPCODE: + int i, opcode; + for (i = 0; i < items; i++) + { + opcode = SvIV(ST(i)); + if (opcode < 0 || opcode >= maxo) + croak("opcode out of range"); + XPUSHs(sv_2mortal(newSVpv(op_name[opcode], 0))); + } + +void +opcode(...) + PPCODE: + int i, j; + char *op; + for (i = 0; i < items; i++) + { + op = SvPV(ST(i), na); + for (j = 0; j < maxo && strNE(op, op_name[j]); j++) /* nothing */ ; + if (j == maxo) + croak("bad op name \"%s\"", op); + XPUSHs(sv_2mortal(newSViv(j))); + } + +int +MAXO() + CODE: + RETVAL = maxo; + OUTPUT: + RETVAL diff --git a/ext/Socket/Socket.pm b/ext/Socket/Socket.pm index 7f0943bc6b..6462713c43 100644 --- a/ext/Socket/Socket.pm +++ b/ext/Socket/Socket.pm @@ -3,8 +3,7 @@ $VERSION = 1.5; =head1 NAME -Socket, sockaddr_in, sockaddr_un, inet_aton, inet_ntoa - load the C - socket.h defines and structure manipulators +Socket, sockaddr_in, sockaddr_un, inet_aton, inet_ntoa - load the C socket.h defines and structure manipulators =head1 SYNOPSIS |