This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Permissions in MakeMaker (Was: patch to MM_Unix.pm)
[perl5.git] / lib / ExtUtils / MM_Unix.pm
index 4f7a9e8..daa477c 100644 (file)
@@ -5,11 +5,11 @@ use Config;
 use File::Basename qw(basename dirname fileparse);
 use DirHandle;
 use strict;
-use vars qw($VERSION $Is_Mac $Is_OS2 $Is_VMS $Is_Win32
+use vars qw($VERSION $Is_Mac $Is_OS2 $Is_VMS $Is_Win32 $Is_Dos
            $Verbose %pm %static $Xsubpp_Version);
 
-$VERSION = substr q$Revision: 1.118 $, 10;
-# $Id: MM_Unix.pm,v 1.118 1997/08/01 09:42:52 k Exp $
+$VERSION = substr q$Revision: 1.126 $, 10;
+# $Id: MM_Unix.pm,v 1.126 1998/06/28 21:32:49 k Exp k $
 
 Exporter::import('ExtUtils::MakeMaker',
        qw( $Verbose &neatvalue));
@@ -17,6 +17,7 @@ Exporter::import('ExtUtils::MakeMaker',
 $Is_OS2 = $^O eq 'os2';
 $Is_Mac = $^O eq 'MacOS';
 $Is_Win32 = $^O eq 'MSWin32';
+$Is_Dos = $^O eq 'dos';
 
 if ($Is_VMS = $^O eq 'VMS') {
     require VMS::Filespec;
@@ -77,11 +78,15 @@ path. On UNIX eliminated successive slashes and successive "/.".
 
 sub canonpath {
     my($self,$path) = @_;
+    my $node = '';
+    if ( $^O eq 'qnx' && $path =~ s|^(//\d+)/|/| ) {
+      $node = $1;
+    }
     $path =~ s|/+|/|g ;                            # xx////xx  -> xx/xx
     $path =~ s|(/\.)+/|/|g ;                       # xx/././xx -> xx/xx
     $path =~ s|^(\./)+|| unless $path eq "./";     # ./xx      -> xx
     $path =~ s|/$|| unless $path eq "/";           # xx/       -> xx
-    $path;
+    "$node$path";
 }
 
 =item catdir
@@ -97,17 +102,13 @@ trailing slash :-)
 # ';
 
 sub catdir {
-    shift;
+    my $self = shift @_;
     my @args = @_;
     for (@args) {
        # append a slash to each argument unless it has one there
        $_ .= "/" if $_ eq '' or substr($_,-1) ne "/";
     }
-    my $result = join('', @args);
-    # remove a trailing slash unless we are root
-    substr($result,-1) = ""
-       if length($result) > 1 && substr($result,-1) eq "/";
-    $result;
+    $self->canonpath(join('', @args));
 }
 
 =item catfile
@@ -120,12 +121,12 @@ complete path ending with a filename
 sub catfile {
     my $self = shift @_;
     my $file = pop @_;
-    return $file unless @_;
+    return $self->canonpath($file) unless @_;
     my $dir = $self->catdir(@_);
     for ($dir) {
        $_ .= "/" unless substr($_,length($_)-1,1) eq "/";
     }
-    return $dir.$file;
+    return $self->canonpath($dir.$file);
 }
 
 =item curdir
@@ -266,7 +267,7 @@ sub c_o {
     push @m, '
 .C$(OBJ_EXT):
        $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.C
-' if $^O ne 'os2' and $^O ne 'MSWin32';                # Case-specific
+' if $^O ne 'os2' and $^O ne 'MSWin32' and $^O ne 'dos'; #Case-specific
     push @m, '
 .cpp$(OBJ_EXT):
        $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.cpp
@@ -370,6 +371,15 @@ sub cflags {
        $self->{uc $_} ||= $cflags{$_}
     }
 
+    if ($self->{CAPI}) {
+        $self->{CCFLAGS} =~ s/-DPERL_OBJECT(\s|$)//;
+        $self->{CCFLAGS} .= '-DPERL_CAPI';
+        if ($Is_Win32 && $Config{'cc'} =~ /^cl.exe/i) {
+            # Turn off C++ mode of the MSC compiler
+            $self->{CCFLAGS} =~ s/-TP(\s|$)//;
+            $self->{OPTIMIZE} =~ s/-TP(\s|$)//;
+        }
+    }
     return $self->{CFLAGS} = qq{
 CCFLAGS = $self->{CCFLAGS}
 OPTIMIZE = $self->{OPTIMIZE}
@@ -557,6 +567,15 @@ MAN3PODS = ".join(" \\\n\t", sort keys %{$self->{MAN3PODS}})."
        push @m, "$tmp = $self->{$tmp}\n";
     }
 
+    for $tmp (qw(
+               PERM_RW PERM_RWX
+               )
+            ) {
+        my $method = lc($tmp);
+       # warn "self[$self] method[$method]";
+        push @m, "$tmp = ", $self->$method(), "\n";
+    }
+
     push @m, q{
 .NO_CONFIG_REC: Makefile
 } if $ENV{CLEARCASE_ROOT};
@@ -681,8 +700,8 @@ $targ :: $src
        $self->{NOECHO}\$(MKPATH) $targdir
        $self->{NOECHO}\$(EQUALIZE_TIMESTAMP) $src $targ
 };
-       push(@m,qq{
-       -$self->{NOECHO}\$(CHMOD) 755 $targdir
+       push(@m, qq{
+       -$self->{NOECHO}\$(CHMOD) \$(PERM_RWX) $targdir
 }) unless $Is_VMS;
     }
     join "", @m;
@@ -958,12 +977,12 @@ $(BOOTSTRAP): '."$self->{MAKEFILE} $self->{BOOTDEP}".' $(INST_ARCHAUTODIR)/.exis
                -MExtUtils::Mkbootstrap \
                -e "Mkbootstrap(\'$(BASEEXT)\',\'$(BSLOADLIBS)\');"
        '.$self->{NOECHO}.'$(TOUCH) $(BOOTSTRAP)
-       $(CHMOD) 644 $@
+       $(CHMOD) $(PERM_RW) $@
 
 $(INST_BOOT): $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists
        '."$self->{NOECHO}$self->{RM_RF}".' $(INST_BOOT)
        -'.$self->{CP}.' $(BOOTSTRAP) $(INST_BOOT)
-       $(CHMOD) 644 $@
+       $(CHMOD) $(PERM_RW) $@
 ';
 }
 
@@ -1007,10 +1026,14 @@ $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists
     $ldrun = join ' ', map "-R$_", split /:/, $self->{LD_RUN_PATH}
        if ($^O eq 'solaris');
 
+    # The IRIX linker also doesn't use LD_RUN_PATH
+    $ldrun = qq{-rpath "$self->{LD_RUN_PATH}"}
+       if ($^O eq 'irix' && $self->{LD_RUN_PATH});
+
     push(@m,'  LD_RUN_PATH="$(LD_RUN_PATH)" $(LD) -o $@ '.$ldrun.' $(LDDLFLAGS) '.$ldfrom.
                ' $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(EXPORT_LIST)');
     push @m, '
-       $(CHMOD) 755 $@
+       $(CHMOD) $(PERM_RWX) $@
 ';
 
     push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
@@ -1049,7 +1072,12 @@ Takes as argument a path and returns true, if it is an absolute path.
 
 sub file_name_is_absolute {
     my($self,$file) = @_;
-    $file =~ m:^/: ;
+    if ($Is_Dos){
+        $file =~ m{^([a-z]:)?[\\/]}i ;
+    }
+    else {
+        $file =~ m:^/: ;
+    }
 }
 
 =item find_perl
@@ -1149,6 +1177,7 @@ sub fixin { # stolen from the pink Camel book, more or less
        my($shb) = "";
        if ($interpreter) {
            print STDOUT "Changing sharpbang in $file to $interpreter" if $Verbose;
+           # this is probably value-free on DOSISH platforms
            if ($does_shbang) {
                $shb .= "$Config{'sharpbang'}$interpreter";
                $shb .= ' ' . $arg if defined $arg;
@@ -1157,23 +1186,22 @@ sub fixin { # stolen from the pink Camel book, more or less
            $shb .= qq{
 eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}'
     if 0; # not running under some shell
-};
+} unless $Is_Win32; # this won't work on win32, so don't
        } else {
            warn "Can't find $cmd in PATH, $file unchanged"
                if $Verbose;
            next;
        }
 
-       unless ( rename($file, "$file.bak") ) { 
-           warn "Can't modify $file";
-           next;
-       }
-       unless ( open(FIXOUT,">$file") ) {
+       unless ( open(FIXOUT,">$file.new") ) {
            warn "Can't create new $file: $!\n";
            next;
        }
        my($dev,$ino,$mode) = stat FIXIN;
-       $mode = 0755 unless $dev;
+       # If they override perm_rwx, we won't notice it during fixin,
+       # because fixin is run through a new instance of MakeMaker.
+       # That is why we must run another CHMOD later.
+       $mode = oct($self->perm_rwx) unless $dev;
        chmod $mode, $file;
        
        # Print out the new #! line (or equivalent).
@@ -1182,9 +1210,23 @@ eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}'
        print FIXOUT $shb, <FIXIN>;
        close FIXIN;
        close FIXOUT;
+       # can't rename open files on some DOSISH platforms
+       unless ( rename($file, "$file.bak") ) { 
+           warn "Can't rename $file to $file.bak: $!";
+           next;
+       }
+       unless ( rename("$file.new", $file) ) { 
+           warn "Can't rename $file.new to $file: $!";
+           unless ( rename("$file.bak", $file) ) {
+               warn "Can't rename $file.bak back to $file either: $!";
+               warn "Leaving $file renamed as $file.bak\n";
+           }
+           next;
+       }
        unlink "$file.bak";
     } continue {
-       chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+       chmod oct($self->perm_rwx), $file or
+         die "Can't reset permissions for $file: $!\n";
        system("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';;
     }
 }
@@ -1252,7 +1294,7 @@ sub init_dirscan {        # --- File and Directory Lists (.xs .pm .pod etc)
     my($self) = @_;
     my($name, %dir, %xs, %c, %h, %ignore, %pl_files, %manifypods);
     local(%pm); #the sub in find() has to see this hash
-    $ignore{'test.pl'} = 1;
+    @ignore{qw(Makefile.PL test.pl)} = (1,1);
     $ignore{'makefile.pl'} = 1 if $Is_VMS;
     foreach $name ($self->lsdir($self->curdir)){
        next if $name =~ /\#/;
@@ -1270,13 +1312,16 @@ sub init_dirscan {      # --- File and Directory Lists (.xs .pm .pod etc)
                unless $name =~ m/perlmain\.c/; # See MAP_TARGET
        } elsif ($name =~ /\.h$/i){
            $h{$name} = 1;
+       } elsif ($name =~ /\.PL$/) {
+           ($pl_files{$name} = $name) =~ s/\.PL$// ;
+       } elsif ($Is_VMS && $name =~ /\.pl$/) {  # case-insensitive filesystem
+           local($/); open(PL,$name); my $txt = <PL>; close PL;
+           if ($txt =~ /Extracting \S+ \(with variable substitutions/) {
+               ($pl_files{$name} = $name) =~ s/\.pl$// ;
+           }
+           else { $pm{$name} = $self->catfile('$(INST_LIBDIR)',$name); }
        } elsif ($name =~ /\.(p[ml]|pod)$/){
            $pm{$name} = $self->catfile('$(INST_LIBDIR)',$name);
-       } elsif ($name =~ /\.PL$/ && $name ne "Makefile.PL") {
-           ($pl_files{$name} = $name) =~ s/\.PL$// ;
-       } elsif ($Is_VMS && $name =~ /\.pl$/ && $name ne 'makefile.pl' &&
-                $name ne 'test.pl') {  # case-insensitive filesystem
-           ($pl_files{$name} = $name) =~ s/\.pl$// ;
        }
     }
 
@@ -1480,7 +1525,7 @@ sub init_main {
         $modfname = &DynaLoader::mod2fname(\@modparts);
     }
 
-    ($self->{PARENT_NAME}, $self->{BASEEXT}) = $self->{NAME} =~ m!([\w:]+::)?(\w+)$! ;
+    ($self->{PARENT_NAME}, $self->{BASEEXT}) = $self->{NAME} =~ m!(?:([\w:]+)::)?(\w+)$! ;
 
     if (defined &DynaLoader::mod2fname) {
        # As of 5.001m, dl_os2 appends '_'
@@ -1934,7 +1979,7 @@ pure_site_install ::
                }.$self->catdir('$(PERL_ARCHLIB)','auto','$(FULLEXT)').q{
 
 doc_perl_install ::
-       }.$self->{NOECHO}.q{$(DOC_INSTALL) \
+       -}.$self->{NOECHO}.q{$(DOC_INSTALL) \
                "Module" "$(NAME)" \
                "installed into" "$(INSTALLPRIVLIB)" \
                LINKTYPE "$(LINKTYPE)" \
@@ -1943,7 +1988,7 @@ doc_perl_install ::
                >> }.$self->catfile('$(INSTALLARCHLIB)','perllocal.pod').q{
 
 doc_site_install ::
-       }.$self->{NOECHO}.q{$(DOC_INSTALL) \
+       -}.$self->{NOECHO}.q{$(DOC_INSTALL) \
                "Module" "$(NAME)" \
                "installed into" "$(INSTALLSITELIB)" \
                LINKTYPE "$(LINKTYPE)" \
@@ -1991,9 +2036,12 @@ sub installbin {
     push(@m, qq{
 EXE_FILES = @{$self->{EXE_FILES}}
 
-FIXIN = \$(PERL) -I\$(PERL_ARCHLIB) -I\$(PERL_LIB) -MExtUtils::MakeMaker \\
+} . ($Is_Win32
+  ? q{FIXIN = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \
+    -e "system qq[pl2bat.bat ].shift"
+} : q{FIXIN = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::MakeMaker \
     -e "MY->fixin(shift)"
-
+}).qq{
 all :: @to
        $self->{NOECHO}\$(NOOP)
 
@@ -2009,6 +2057,7 @@ $to: $from $self->{MAKEFILE} " . $self->catdir($todir,'.exists') . "
        $self->{NOECHO}$self->{RM_F} $to
        $self->{CP} $from $to
        \$(FIXIN) $to
+       -$self->{NOECHO}\$(CHMOD) \$(PERM_RWX) $to
 ";
     }
     join "", @m;
@@ -2298,11 +2347,14 @@ $tmp/perlmain.c: $makefilename}, q{
                -e "writemain(grep s#.*/auto/##, qw|$(MAP_STATIC)|)" > $@t && $(MV) $@t $@
 
 };
+    push @m, "\t",$self->{NOECHO}.q{$(PERL) $(INSTALLSCRIPT)/fixpmain
+} if (defined (&Dos::UseLFN) && Dos::UseLFN()==0);
+
 
     push @m, q{
 doc_inst_perl:
        }.$self->{NOECHO}.q{echo Appending installation info to $(INSTALLARCHLIB)/perllocal.pod
-       }.$self->{NOECHO}.q{$(DOC_INSTALL) \
+       -}.$self->{NOECHO}.q{$(DOC_INSTALL) \
                "Perl binary" "$(MAP_TARGET)" \
                MAP_STATIC "$(MAP_STATIC)" \
                MAP_EXTRA "`cat $(INST_ARCHAUTODIR)/extralibs.all`" \
@@ -2394,11 +2446,12 @@ END
     my(@m);
     push @m,
 qq[POD2MAN_EXE = $pod2man_exe\n],
-q[POD2MAN = $(PERL) -we '%m=@ARGV;for (keys %m){' \\
--e 'next if -e $$m{$$_} && -M $$m{$$_} < -M $$_ && -M $$m{$$_} < -M "].$self->{MAKEFILE}.q[";' \\
+qq[POD2MAN = \$(PERL) -we '%m=\@ARGV;for (keys %m){' \\\n],
+q[-e 'next if -e $$m{$$_} && -M $$m{$$_} < -M $$_ && -M $$m{$$_} < -M "],
+ $self->{MAKEFILE}, q[";' \\
 -e 'print "Manifying $$m{$$_}\n";' \\
 -e 'system(qq[$$^X ].q["-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" $(POD2MAN_EXE) ].qq[$$_>$$m{$$_}])==0 or warn "Couldn\\047t install $$m{$$_}\n";' \\
--e 'chmod 0644, $$m{$$_} or warn "chmod 644 $$m{$$_}: $$!\n";}'
+-e 'chmod(oct($(PERM_RW))), $$m{$$_} or warn "chmod $(PERM_RW) $$m{$$_}: $$!\n";}'
 ];
     push @m, "\nmanifypods : ";
     push @m, join " \\\n\t", keys %{$self->{MAN1PODS}}, keys %{$self->{MAN3PODS}};
@@ -2575,7 +2628,7 @@ Takes no argument, returns the environment variable PATH as an array.
 
 sub path {
     my($self) = @_;
-    my $path_sep = $Is_OS2 ? ";" : ":";
+    my $path_sep = ($Is_OS2 || $Is_Dos) ? ";" : ":";
     my $path = $ENV{PATH};
     $path =~ s:\\:/:g if $Is_OS2;
     my @path = split $path_sep, $path;
@@ -2631,7 +2684,7 @@ $(PERL_INC)/config.h       $(PERL_INC)/mg.h           $(PERL_INC)/scope.h    \
 $(PERL_INC)/cop.h          $(PERL_INC)/op.h           $(PERL_INC)/sv.h      \
 $(PERL_INC)/cv.h           $(PERL_INC)/opcode.h       $(PERL_INC)/unixish.h  \
 $(PERL_INC)/dosish.h       $(PERL_INC)/patchlevel.h   $(PERL_INC)/util.h     \
-$(PERL_INC)/embed.h        $(PERL_INC)/perl.h                               \
+$(PERL_INC)/embed.h        $(PERL_INC)/perl.h         $(PERL_INC)/iperlsys.h \
 $(PERL_INC)/form.h         $(PERL_INC)/perly.h
 
 $(OBJECT) : $(PERL_HDRS)
@@ -2642,6 +2695,35 @@ $(OBJECT) : $(PERL_HDRS)
     join "\n", @m;
 }
 
+=item perm_rw (o)
+
+Returns the attribute C<PERM_RW> or the string C<644>.
+Used as the string that is passed
+to the C<chmod> command to set the permissions for read/writeable files.
+MakeMaker chooses C<644> because it has turned out in the past that
+relying on the umask provokes hard-to-track bugreports.
+When the return value is used by the perl function C<chmod>, it is
+interpreted as an octal value.
+
+=cut
+
+sub perm_rw {
+    shift->{PERM_RW} || "644";
+}
+
+=item perm_rwx (o)
+
+Returns the attribute C<PERM_RWX> or the string C<755>,
+i.e. the string that is passed
+to the C<chmod> command to set the permissions for executable files.
+See also perl_rw.
+
+=cut
+
+sub perm_rwx {
+    shift->{PERM_RWX} || "755";
+}
+
 =item pm_to_blib
 
 Defines target that copies all files in the hash PM to their
@@ -2825,7 +2907,7 @@ END
 
     push @m,
 q{     $(AR) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@
-       $(CHMOD) 755 $@
+       $(CHMOD) $(PERM_RWX) $@
        }.$self->{NOECHO}.q{echo "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)/extralibs.ld
 };
     # Old mechanism - still available:
@@ -3139,9 +3221,11 @@ sub tool_xsubpp {
        }
     }
 
+    $xsubpp = $self->{CAPI} ? "xsubpp -object_capi" : "xsubpp";
+
     return qq{
 XSUBPPDIR = $xsdir
-XSUBPP = \$(XSUBPPDIR)/xsubpp
+XSUBPP = \$(XSUBPPDIR)/$xsubpp
 XSPROTOARG = $self->{XSPROTOARG}
 XSUBPPDEPS = @tmdeps
 XSUBPPARGS = @tmargs