rzward has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I have a monolithic Perl CGI script that is distributed to a wide variety of web servers. The script has a new feature that requires the use of the function sysopen. The flags I want to pass to sysopen (O_CREAT, O_EXCL and O_WRONLY) in turn require the Fcntl module.

I would like to not require that web servers have the Fcntl module installed to use my script unless the new feature is used.

Here is a small program that uses sysopen and Fcntl:

use strict; print &openit; sub openit1 { use Fcntl qw(O_CREAT O_EXCL O_WRONLY); my $fp = "c:\\temp\\test.csv.lck.tmp"; die "Cannot open $fp" if !sysopen (my $fh,$fp,O_WRONLY|O_CREAT|O_EXC +L); close $fh; unlink $fp; return $fp; }

This program works fine when Fcntl is installed. When Fcntl is not installed, the program fails to compile. So, I have tried the following:

use strict; print &openit; sub openit { eval "use Fcntl qw(O_CREAT O_EXCL O_WRONLY);"; my $fp = "c:\\temp\\test.csv.lck.tmp"; die "Cannot open $fp" if !sysopen (my $fh,$fp,O_WRONLY|O_CREAT|O_EXC +L); close $fh; unlink $fp; return $fp; }
This program does not compile because of use strict; and the barewords O_CREAT, O_EXCL and O_WRONLY. When I remove use strict;, the script compiles but sysopen does not work properly. I don't really understand why but I'm thinking this is because O_CREAT, O_EXCL and O_WRONLY are not set correctly when use Fcntl is evaluated inside a string.

I would like those who use the feature to install Fcntl but those who do not to not have to install Fcntl. Is there a way for me to use sysopen in my script, requiring Fcntl only when the code is about to be run?

Thank you in advance for your help.

Richard

  • Comment on Can I include O_CREAT, O_EXCEL and O_WRONLY in my script without always requiring Fcntl?
  • Select or Download Code

Replies are listed 'Best First'.
Re: Can I include O_CREAT, O_EXCEL and O_WRONLY in my script without always requiring Fcntl?
by Roy Johnson (Monsignor) on Apr 13, 2006 at 17:58 UTC
    use, as the docs say, is just require and import called at BEGIN time. If you don't want it done then, make the calls yourself:
    use strict; use warnings; sub not_really_needed { require SomethingStupid; import SomethingStupid qw(O_CREAT O_EXCL O_WRONLY); }
    This program compiles fine, but fails with a runtime error if you add a call to not_really_needed. Replace SomethingStupid with Fcntl and you'll have what you want.

    Caution: Contents may have been coded under pressure.
      Thank you for your help.

      I did read that but I guess I somehow convinced myself require and import are evaluated at compile-time.

      I will experiment with this and the other method.

      Richard

Re: Can I include O_CREAT, O_EXCEL and O_WRONLY in my script without always requiring Fcntl?
by sgifford (Prior) on Apr 13, 2006 at 18:48 UTC
    Fcntl has been part of the core Perl distribution for a very long time, so really nobody should have to install it even if you require it all the time; they will almost certainly already have it.
      Thank you for your help.

      I agree with what you said but I found that on 2 of my own MS Windows web servers, where I had recently reinstalled the operating system and then installed ActiveState Perl 5.8, I noticed that although Fcntl has been installed and I can see the module in the lib folder, the @INC variable was not set up properly for IIS.

      I realize this is easy to fix but it made me realize that even though Fcntl may be installed on many or all of my customers' web servers, it is likely that for some Fcntl will not be available through the web server without making a configuration change. The problem is many of my customers do not have the ability to change the configuration of their web servers. Many of them can only copy files. To accommodate these folks, it's important to be able to make Fcntl optional.

      Thanks again.

      Richard

        If you go that far, you might not be able to rely on strict. At some point, you have to assume that your customers have non-broken systems. For me, that point is being able to use at least the core modules.

Re: Can I include O_CREAT, O_EXCEL and O_WRONLY in my script without always requiring Fcntl?
by salva (Canon) on Apr 13, 2006 at 17:40 UTC
    add an empty pair of parens after the constant names when using them: O_CREAT().
      Thank you! That appears to work. My test program would then look like this:
      use strict; print &openit; sub openit { eval "use Fcntl qw(O_CREAT O_EXCL O_WRONLY);"; die $@ if ($@); my $fp = "c:\\temp\\test.csv.lck.tmp"; die "Unable to open $fp" if !sysopen (my $fh, $fp, O_WRONLY() | O_CR +EAT() | O_EXCL()); close $fh; unlink $fp; return $fp; }

      Thanks again.

      Richard

        you can also eliminate the eval/use statement replacing it by a require one and then call the constant subs prefixed with the package name:
        sub openit { require Fcntl; my $fp = "c:\\temp\\test.csv.lck.tmp"; die "Unable to open $fp" if !sysopen (my $fh, $fp, Fcntl::O_WRONLY() + | Fcntl::O_CREAT() | Fcntl::O_EXCL()); close $fh; unlink $fp; return $fp; }