This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
use Perl_my_mkstemp() where appropriate
[perl5.git] / perl.c
diff --git a/perl.c b/perl.c
index 125afae..e6932b5 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -62,10 +62,6 @@ union control_un {
 #  endif
 #endif
 
-#if !defined(STANDARD_C) && !defined(HAS_GETENV_PROTOTYPE) && !defined(PERL_MICRO)
-char *getenv (char *); /* Usually in <stdlib.h> */
-#endif
-
 static I32 read_e_script(pTHX_ int idx, SV *buf_sv, int maxlen);
 
 #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
@@ -96,6 +92,7 @@ S_init_tls_and_interp(PerlInterpreter *my_perl)
        PERL_SET_THX(my_perl);
        OP_REFCNT_INIT;
        OP_CHECK_MUTEX_INIT;
+        KEYWORD_PLUGIN_MUTEX_INIT;
        HINTS_REFCNT_INIT;
         LOCALE_INIT;
        MUTEX_INIT(&PL_dollarzero_mutex);
@@ -273,6 +270,26 @@ perl_construct(pTHXx)
 
     init_stacks();
 
+/* The PERL_INTERNAL_RAND_SEED set-up must be after init_stacks because it calls
+ * things that may put SVs on the stack.
+ */
+
+#ifdef NO_PERL_INTERNAL_RAND_SEED
+    Perl_drand48_init_r(&PL_internal_random_state, seed());
+#else
+    {
+        UV seed;
+        const char *env_pv;
+        if (PerlProc_getuid() != PerlProc_geteuid() ||
+            PerlProc_getgid() != PerlProc_getegid() ||
+            !(env_pv = PerlEnv_getenv("PERL_INTERNAL_RAND_SEED")) ||
+            grok_number(env_pv, strlen(env_pv), &seed) != IS_NUMBER_IN_UV) {
+            seed = seed();
+        }
+        Perl_drand48_init_r(&PL_internal_random_state, (U32)seed);
+    }
+#endif
+
     init_ids();
 
     S_fixup_platform_bugs();
@@ -286,6 +303,14 @@ perl_construct(pTHXx)
     PL_localpatches = local_patches;   /* For possible -v */
 #endif
 
+#if defined(LIBM_LIB_VERSION)
+    /*
+     * Some BSDs and Cygwin default to POSIX math instead of IEEE.
+     * This switches them over to IEEE.
+     */
+    _LIB_VERSION = _IEEE_;
+#endif
+
 #ifdef HAVE_INTERP_INTERN
     sys_intern_init();
 #endif
@@ -317,13 +342,13 @@ perl_construct(pTHXx)
          * a suitable seed yourself and define PERL_HASH_SEED to a well chosen
          * string. See hv_func.h for details.
          */
-#if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)
+#if defined(USE_HASH_SEED)
         /* get the hash seed from the environment or from an RNG */
         Perl_get_hash_seed(aTHX_ PL_hash_seed);
-#else /*if !(defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT)) */
+#else
         /* they want a hard coded seed, check that it is long enough */
         assert( strlen(PERL_HASH_SEED) >= PERL_HASH_SEED_BYTES );
-#endif /* #if defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) */
+#endif
 
         /* now we use the chosen seed to initialize the state -
          * in some configurations this may be a relatively speaking
@@ -347,15 +372,20 @@ perl_construct(pTHXx)
          * constructing hashes */
         PL_hash_seed_set= TRUE;
     }
-    /* Note that strtab is a rather special HV.  Assumptions are made
-       about not iterating on it, and not adding tie magic to it.
-       It is properly deallocated in perl_destruct() */
-    PL_strtab = newHV();
 
-    /* SHAREKEYS tells us that the hash has its keys shared with PL_strtab,
-     * which is not the case with PL_strtab itself */
-    HvSHAREKEYS_off(PL_strtab);                        /* mandatory */
-    hv_ksplit(PL_strtab, 1 << 11);
+    /* Allow PL_strtab to be pre-initialized before calling perl_construct.
+    * can use a custom optimized PL_strtab hash before calling perl_construct */
+    if (!PL_strtab) {
+        /* Note that strtab is a rather special HV.  Assumptions are made
+           about not iterating on it, and not adding tie magic to it.
+           It is properly deallocated in perl_destruct() */
+        PL_strtab = newHV();
+
+        /* SHAREKEYS tells us that the hash has its keys shared with PL_strtab,
+         * which is not the case with PL_strtab itself */
+        HvSHAREKEYS_off(PL_strtab);                    /* mandatory */
+        hv_ksplit(PL_strtab, 1 << 11);
+    }
 
     Zero(PL_sv_consts, SV_CONSTS_COUNT, SV*);
 
@@ -390,23 +420,14 @@ perl_construct(pTHXx)
        PL_mmap_page_size = sysconf(_SC_MMAP_PAGE_SIZE);
 #   endif
        if ((long) PL_mmap_page_size < 0) {
-         if (errno) {
-           SV * const error = ERRSV;
-           SvUPGRADE(error, SVt_PV);
-           Perl_croak(aTHX_ "panic: sysconf: %s", SvPV_nolen_const(error));
-         }
-         else
-           Perl_croak(aTHX_ "panic: sysconf: pagesize unknown");
+           Perl_croak(aTHX_ "panic: sysconf: %s",
+               errno ? Strerror(errno) : "pagesize unknown");
        }
       }
-#else
-#   ifdef HAS_GETPAGESIZE
+#elif defined(HAS_GETPAGESIZE)
       PL_mmap_page_size = getpagesize();
-#   else
-#       if defined(I_SYS_PARAM) && defined(PAGESIZE)
+#elif defined(I_SYS_PARAM) && defined(PAGESIZE)
       PL_mmap_page_size = PAGESIZE;       /* compiletime, bad */
-#       endif
-#   endif
 #endif
       if (PL_mmap_page_size <= 0)
        Perl_croak(aTHX_ "panic: bad pagesize %" IVdf,
@@ -448,7 +469,7 @@ perl_construct(pTHXx)
     PL_WB_invlist = _new_invlist_C_array(_Perl_WB_invlist);
     PL_LB_invlist = _new_invlist_C_array(_Perl_LB_invlist);
     PL_Assigned_invlist = _new_invlist_C_array(Assigned_invlist);
-#ifdef USE_THREAD_SAFE_LOCALE
+#ifdef HAS_POSIX_2008_LOCALE
     PL_C_locale_obj = newlocale(LC_ALL_MASK, "C", NULL);
 #endif
 
@@ -572,9 +593,33 @@ Perl_dump_sv_child(pTHX_ SV *sv)
 #endif
 
 /*
-=for apidoc perl_destruct
-
-Shuts down a Perl interpreter.  See L<perlembed>.
+=for apidoc Am|int|perl_destruct|PerlInterpreter *my_perl
+
+Shuts down a Perl interpreter.  See L<perlembed> for a tutorial.
+
+C<my_perl> points to the Perl interpreter.  It must have been previously
+created through the use of L</perl_alloc> and L</perl_construct>.  It may
+have been initialised through L</perl_parse>, and may have been used
+through L</perl_run> and other means.  This function should be called for
+any Perl interpreter that has been constructed with L</perl_construct>,
+even if subsequent operations on it failed, for example if L</perl_parse>
+returned a non-zero value.
+
+If the interpreter's C<PL_exit_flags> word has the
+C<PERL_EXIT_DESTRUCT_END> flag set, then this function will execute code
+in C<END> blocks before performing the rest of destruction.  If it is
+desired to make any use of the interpreter between L</perl_parse> and
+L</perl_destruct> other than just calling L</perl_run>, then this flag
+should be set early on.  This matters if L</perl_run> will not be called,
+or if anything else will be done in addition to calling L</perl_run>.
+
+Returns a value be a suitable value to pass to the C library function
+C<exit> (or to return from C<main>), to serve as an exit code indicating
+the nature of the way the interpreter terminated.  This takes into account
+any failure of L</perl_parse> and any early exit from L</perl_run>.
+The exit code is of the type required by the host operating system,
+so because of differing exit code conventions it is not portable to
+interpret specific numeric values as having specific meanings.
 
 =cut
 */
@@ -583,7 +628,7 @@ int
 perl_destruct(pTHXx)
 {
     dVAR;
-    VOL signed char destruct_level;  /* see possible values in intrpvar.h */
+    volatile signed char destruct_level;  /* see possible values in intrpvar.h */
     HV *hv;
 #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
     pid_t child;
@@ -1107,6 +1152,11 @@ perl_destruct(pTHXx)
     PL_numeric_radix_sv = NULL;
 #endif
 
+    if (PL_langinfo_buf) {
+        Safefree(PL_langinfo_buf);
+        PL_langinfo_buf = NULL;
+    }
+
     /* clear character classes  */
     for (i = 0; i < POSIX_SWASH_COUNT; i++) {
         SvREFCNT_dec(PL_utf8_swash_ptrs[i]);
@@ -1287,6 +1337,11 @@ perl_destruct(pTHXx)
     SvANY(&PL_sv_no) = NULL;
     SvFLAGS(&PL_sv_no) = 0;
 
+    SvREFCNT(&PL_sv_zero) = 0;
+    sv_clear(&PL_sv_zero);
+    SvANY(&PL_sv_zero) = NULL;
+    SvFLAGS(&PL_sv_zero) = 0;
+
     {
         int i;
         for (i=0; i<=2; i++) {
@@ -1539,9 +1594,55 @@ Perl_call_atexit(pTHX_ ATEXIT_t fn, void *ptr)
 }
 
 /*
-=for apidoc perl_parse
-
-Tells a Perl interpreter to parse a Perl script.  See L<perlembed>.
+=for apidoc Am|int|perl_parse|PerlInterpreter *my_perl|XSINIT_t xsinit|int argc|char **argv|char **env
+
+Tells a Perl interpreter to parse a Perl script.  This performs most
+of the initialisation of a Perl interpreter.  See L<perlembed> for
+a tutorial.
+
+C<my_perl> points to the Perl interpreter that is to parse the script.
+It must have been previously created through the use of L</perl_alloc>
+and L</perl_construct>.  C<xsinit> points to a callback function that
+will be called to set up the ability for this Perl interpreter to load
+XS extensions, or may be null to perform no such setup.
+
+C<argc> and C<argv> supply a set of command-line arguments to the Perl
+interpreter, as would normally be passed to the C<main> function of
+a C program.  C<argv[argc]> must be null.  These arguments are where
+the script to parse is specified, either by naming a script file or by
+providing a script in a C<-e> option.
+
+C<env> specifies a set of environment variables that will be used by
+this Perl interpreter.  If non-null, it must point to a null-terminated
+array of environment strings.  If null, the Perl interpreter will use
+the environment supplied by the C<environ> global variable.
+
+This function initialises the interpreter, and parses and compiles the
+script specified by the command-line arguments.  This includes executing
+code in C<BEGIN>, C<UNITCHECK>, and C<CHECK> blocks.  It does not execute
+C<INIT> blocks or the main program.
+
+Returns an integer of slightly tricky interpretation.  The correct
+use of the return value is as a truth value indicating whether there
+was a failure in initialisation.  If zero is returned, this indicates
+that initialisation was successful, and it is safe to proceed to call
+L</perl_run> and make other use of it.  If a non-zero value is returned,
+this indicates some problem that means the interpreter wants to terminate.
+The interpreter should not be just abandoned upon such failure; the caller
+should proceed to shut the interpreter down cleanly with L</perl_destruct>
+and free it with L</perl_free>.
+
+For historical reasons, the non-zero return value also attempts to
+be a suitable value to pass to the C library function C<exit> (or to
+return from C<main>), to serve as an exit code indicating the nature
+of the way initialisation terminated.  However, this isn't portable,
+due to differing exit code conventions.  An attempt is made to return
+an exit code of the type required by the host operating system, but
+because it is constrained to be non-zero, it is not necessarily possible
+to indicate every type of exit.  It is only reliable on Unix, where a
+zero exit code can be augmented with a set bit that will be ignored.
+In any case, this function is not the correct place to acquire an exit
+code: one should get that from L</perl_destruct>.
 
 =cut
 */
@@ -1564,7 +1665,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
 #ifndef MULTIPLICITY
     PERL_UNUSED_ARG(my_perl);
 #endif
-#if (defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) || defined(USE_HASH_SEED_DEBUG)) && !defined(NO_PERL_HASH_SEED_DEBUG)
+#if (defined(USE_HASH_SEED) || defined(USE_HASH_SEED_DEBUG)) && !defined(NO_PERL_HASH_SEED_DEBUG)
     {
         const char * const s = PerlEnv_getenv("PERL_HASH_SEED_DEBUG");
 
@@ -1583,7 +1684,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
             PerlIO_printf(Perl_debug_log, "\n");
         }
     }
-#endif /* #if (defined(USE_HASH_SEED) || defined(USE_HASH_SEED_EXPLICIT) ... */
+#endif /* #if (defined(USE_HASH_SEED) ... */
 
 #ifdef __amigaos4__
     {
@@ -1592,6 +1693,13 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
     }
 #endif
 
+    {
+       int i;
+       assert(argc >= 0);
+       for(i = 0; i != argc; i++)
+           assert(argv[i]);
+       assert(!argv[argc]);
+    }
     PL_origargc = argc;
     PL_origargv = argv;
 
@@ -1743,6 +1851,7 @@ perl_parse(pTHXx_ XSINIT_t xsinit, int argc, char **argv, char **env)
            call_list(oldscope, PL_checkav);
        }
        ret = STATUS_EXIT;
+       if (ret == 0) ret = 0x100;
        break;
     case 3:
        PerlIO_printf(Perl_error_log, "panic: top_env\n");
@@ -1869,9 +1978,6 @@ S_Internals_V(pTHX_ CV *cv)
 #  ifdef USE_FAST_STDIO
                             " USE_FAST_STDIO"
 #  endif              
-#  ifdef USE_HASH_SEED_EXPLICIT
-                            " USE_HASH_SEED_EXPLICIT"
-#  endif
 #  ifdef USE_LOCALE
                             " USE_LOCALE"
 #  endif
@@ -2187,6 +2293,21 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
     }
     }
 
+#ifndef NO_PERL_INTERNAL_RAND_SEED
+    /* If we're not set[ug]id, we might have honored
+       PERL_INTERNAL_RAND_SEED in perl_construct().
+       At this point command-line options have been parsed, so if
+       we're now tainting and not set[ug]id re-seed.
+       This could possibly be wasteful if PERL_INTERNAL_RAND_SEED is invalid,
+       but avoids duplicating the logic from perl_construct().
+    */
+    if (PL_tainting &&
+        PerlProc_getuid() == PerlProc_geteuid() &&
+        PerlProc_getgid() == PerlProc_getegid()) {
+        Perl_drand48_init_r(&PL_internal_random_state, seed());
+    }
+#endif
+
     /* Set $^X early so that it can be used for relocatable paths in @INC  */
     /* and for SITELIB_EXP in USE_SITECUSTOMIZE                            */
     assert (!TAINT_get);
@@ -2440,9 +2561,47 @@ S_parse_body(pTHX_ char **env, XSINIT_t xsinit)
 }
 
 /*
-=for apidoc perl_run
-
-Tells a Perl interpreter to run.  See L<perlembed>.
+=for apidoc Am|int|perl_run|PerlInterpreter *my_perl
+
+Tells a Perl interpreter to run its main program.  See L<perlembed>
+for a tutorial.
+
+C<my_perl> points to the Perl interpreter.  It must have been previously
+created through the use of L</perl_alloc> and L</perl_construct>, and
+initialised through L</perl_parse>.  This function should not be called
+if L</perl_parse> returned a non-zero value, indicating a failure in
+initialisation or compilation.
+
+This function executes code in C<INIT> blocks, and then executes the
+main program.  The code to be executed is that established by the prior
+call to L</perl_parse>.  If the interpreter's C<PL_exit_flags> word
+does not have the C<PERL_EXIT_DESTRUCT_END> flag set, then this function
+will also execute code in C<END> blocks.  If it is desired to make any
+further use of the interpreter after calling this function, then C<END>
+blocks should be postponed to L</perl_destruct> time by setting that flag.
+
+Returns an integer of slightly tricky interpretation.  The correct use
+of the return value is as a truth value indicating whether the program
+terminated non-locally.  If zero is returned, this indicates that
+the program ran to completion, and it is safe to make other use of the
+interpreter (provided that the C<PERL_EXIT_DESTRUCT_END> flag was set as
+described above).  If a non-zero value is returned, this indicates that
+the interpreter wants to terminate early.  The interpreter should not be
+just abandoned because of this desire to terminate; the caller should
+proceed to shut the interpreter down cleanly with L</perl_destruct>
+and free it with L</perl_free>.
+
+For historical reasons, the non-zero return value also attempts to
+be a suitable value to pass to the C library function C<exit> (or to
+return from C<main>), to serve as an exit code indicating the nature of
+the way the program terminated.  However, this isn't portable, due to
+differing exit code conventions.  An attempt is made to return an exit
+code of the type required by the host operating system, but because
+it is constrained to be non-zero, it is not necessarily possible to
+indicate every type of exit.  It is only reliable on Unix, where a zero
+exit code can be augmented with a set bit that will be ignored.  In any
+case, this function is not the correct place to acquire an exit code:
+one should get that from L</perl_destruct>.
 
 =cut
 */
@@ -2451,7 +2610,7 @@ int
 perl_run(pTHXx)
 {
     I32 oldscope;
-    int ret = 0;
+    int ret = 0, exit_called = 0;
     dJMPENV;
 
     PERL_ARGS_ASSERT_PERL_RUN;
@@ -2472,8 +2631,10 @@ perl_run(pTHXx)
     case 0:                            /* normal completion */
  redo_body:
        run_body(oldscope);
-       /* FALLTHROUGH */
+       goto handle_exit;
     case 2:                            /* my_exit() */
+       exit_called = 1;
+    handle_exit:
        while (PL_scopestack_ix > oldscope)
            LEAVE;
        FREETMPS;
@@ -2487,7 +2648,12 @@ perl_run(pTHXx)
        if (PerlEnv_getenv("PERL_DEBUG_MSTATS"))
            dump_mstats("after execution:  ");
 #endif
-       ret = STATUS_EXIT;
+       if (exit_called) {
+           ret = STATUS_EXIT;
+           if (ret == 0) ret = 0x100;
+       } else {
+           ret = 0;
+       }
        break;
     case 3:
        if (PL_restartop) {
@@ -2662,6 +2828,9 @@ Perl_get_cvn_flags(pTHX_ const char *name, STRLEN len, I32 flags)
 
     PERL_ARGS_ASSERT_GET_CVN_FLAGS;
 
+    if (gv && UNLIKELY(SvROK(gv)) && SvTYPE(SvRV((SV *)gv)) == SVt_PVCV)
+       return (CV*)SvRV((SV *)gv);
+
     /* XXX this is probably not what they think they're getting.
      * It has the same effect as "sub name;", i.e. just a forward
      * declaration! */
@@ -2788,14 +2957,14 @@ See L<perlcall>.
 */
 
 I32
-Perl_call_sv(pTHX_ SV *sv, VOL I32 flags)
+Perl_call_sv(pTHX_ SV *sv, volatile I32 flags)
                        /* See G_* flags in cop.h */
 {
     dVAR;
     LOGOP myop;                /* fake syntax tree node */
     METHOP method_op;
     I32 oldmark;
-    VOL I32 retval = 0;
+    volatile I32 retval = 0;
     bool oldcatch = CATCH_GET;
     int ret;
     OP* const oldop = PL_op;
@@ -2943,8 +3112,8 @@ Perl_eval_sv(pTHX_ SV *sv, I32 flags)
 {
     dVAR;
     UNOP myop;         /* fake syntax tree node */
-    VOL I32 oldmark;
-    VOL I32 retval = 0;
+    volatile I32 oldmark;
+    volatile I32 retval = 0;
     int ret;
     OP* const oldop = PL_op;
     dJMPENV;
@@ -3361,12 +3530,6 @@ Perl_moreswitches(pTHX_ const char *s)
 
     case 'i':
        Safefree(PL_inplace);
-#if defined(__CYGWIN__) /* do backup extension automagically */
-       if (*(s+1) == '\0') {
-       PL_inplace = savepvs(".bak");
-       return s+1;
-       }
-#endif /* __CYGWIN__ */
        {
            const char * const start = ++s;
            while (*s && !isSPACE(*s))
@@ -3743,8 +3906,9 @@ STATIC void
 S_init_main_stash(pTHX)
 {
     GV *gv;
+    HV *hv = newHV();
 
-    PL_curstash = PL_defstash = (HV *)SvREFCNT_inc_simple_NN(newHV());
+    PL_curstash = PL_defstash = (HV *)SvREFCNT_inc_simple_NN(hv);
     /* We know that the string "main" will be in the global shared string
        table, so it's a small saving to use it rather than allocate another
        8 bytes.  */
@@ -3779,7 +3943,6 @@ S_init_main_stash(pTHX)
 #endif
     sv_grow(ERRSV, 240);       /* Preallocate - for immediate signals. */
     CLEAR_ERRSV();
-    SET_CURSTASH(PL_defstash);
     CopSTASH_set(&PL_compiling, PL_defstash);
     PL_debstash = GvHV(gv_fetchpvs("DB::", GV_ADDMULTI, SVt_PVHV));
     PL_globalstash = GvHV(gv_fetchpvs("CORE::GLOBAL::", GV_ADDMULTI,
@@ -3807,7 +3970,7 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
        /* if find_script() returns, it returns a malloc()-ed value */
        scriptname = PL_origfilename = find_script(scriptname, dosearch, NULL, 1);
 
-       if (strEQs(scriptname, "/dev/fd/")
+       if (strBEGINs(scriptname, "/dev/fd/")
             && isDIGIT(scriptname[8])
             && grok_atoUV(scriptname + 8, &uv, &s)
             && uv <= PERL_INT_MAX
@@ -3869,29 +4032,19 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
        };
        const char * const err = "Failed to create a fake bit bucket";
        if (strEQ(scriptname, BIT_BUCKET)) {
-#ifdef HAS_MKSTEMP /* Hopefully mkstemp() is safe here. */
-            int old_umask = umask(0177);
-           int tmpfd = mkstemp(tmpname);
-            umask(old_umask);
+           int tmpfd = Perl_my_mkstemp(tmpname);
            if (tmpfd > -1) {
                scriptname = tmpname;
                close(tmpfd);
            } else
                Perl_croak(aTHX_ err);
-#else
-#  ifdef HAS_MKTEMP
-           scriptname = mktemp(tmpname);
-           if (!scriptname)
-               Perl_croak(aTHX_ err);
-#  endif
-#endif
        }
 #endif
        rsfp = PerlIO_open(scriptname,PERL_SCRIPT_MODE);
 #ifdef FAKE_BIT_BUCKET
-       if (memEQ(scriptname, FAKE_BIT_BUCKET_PREFIX,
-                 sizeof(FAKE_BIT_BUCKET_PREFIX) - 1)
-           && strlen(scriptname) == sizeof(tmpname) - 1) {
+        if (   strBEGINs(scriptname, FAKE_BIT_BUCKET_PREFIX)
+           && strlen(scriptname) == sizeof(tmpname) - 1)
+        {
            unlink(scriptname);
        }
        scriptname = BIT_BUCKET;
@@ -3906,15 +4059,8 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
                    CopFILE(PL_curcop), Strerror(errno));
     }
     fd = PerlIO_fileno(rsfp);
-#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC)
-    if (fd >= 0) {
-        /* ensure close-on-exec */
-        if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
-            Perl_croak(aTHX_ "Can't open perl script \"%s\": %s\n",
-                       CopFILE(PL_curcop), Strerror(errno));
-        }
-    }
-#endif
+    if (fd >= 0)
+       setfd_cloexec(fd);
 
     if (fd < 0 ||
         (PerlLIO_fstat(fd, &tmpstatbuf) >= 0
@@ -3926,12 +4072,20 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
     return rsfp;
 }
 
-/* Mention
+/* In the days of suidperl, we refused to execute a setuid script stored on
+ * a filesystem mounted nosuid and/or noexec. This meant that we probed for the
+ * existence of the appropriate filesystem-statting function, and behaved
+ * accordingly. But even though suidperl is long gone, we must still include
+ * those probes for the benefit of modules like Filesys::Df, which expect the
+ * results of those probes to be stored in %Config; see RT#126368. So mention
+ * the relevant cpp symbols here, to ensure that metaconfig will include their
+ * probes in the generated Configure:
+ *
  * I_SYSSTATVFS        HAS_FSTATVFS
  * I_SYSMOUNT
  * I_STATFS    HAS_FSTATFS     HAS_GETFSSTAT
  * I_MNTENT    HAS_GETMNTENT   HAS_HASMNTOPT
- * here so that metaconfig picks them up. */
+ */
 
 
 #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
@@ -3988,7 +4142,7 @@ S_find_beginning(pTHX_ SV* linestr_sv, PerlIO *rsfp)
     if (*s++ == '-') {
        while (isDIGIT(s2[-1]) || s2[-1] == '-' || s2[-1] == '.'
               || s2[-1] == '_') s2--;
-       if (strEQs(s2-4,"perl"))
+       if (strBEGINs(s2-4,"perl"))
            while ((s = moreswitches(s)))
                ;
     }
@@ -4164,6 +4318,9 @@ Perl_init_stacks(pTHX)
     PL_curstackinfo = new_stackinfo(REASONABLE(128),
                                 REASONABLE(8192/sizeof(PERL_CONTEXT) - 1));
     PL_curstackinfo->si_type = PERLSI_MAIN;
+#if defined DEBUGGING && !defined DEBUGGING_RE_ONLY
+    PL_curstackinfo->si_stack_hwm = 0;
+#endif
     PL_curstack = PL_curstackinfo->si_stack;
     PL_mainstack = PL_curstack;                /* remember in case we switch stacks */
 
@@ -4537,136 +4694,24 @@ S_init_perllib(pTHX)
     /* miniperl gets just -I..., the split of $ENV{PERL5LIB}, and "." in @INC
        (and not the architecture specific directories from $ENV{PERL5LIB}) */
 
+#include "perl_inc_macro.h"
 /* Use the ~-expanded versions of APPLLIB (undocumented),
     SITEARCH, SITELIB, VENDORARCH, VENDORLIB, ARCHLIB and PRIVLIB
 */
-#ifdef APPLLIB_EXP
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(APPLLIB_EXP),
-                     INCPUSH_ADD_SUB_DIRS|INCPUSH_CAN_RELOCATE);
-#endif
-
-#ifdef SITEARCH_EXP
-    /* sitearch is always relative to sitelib on Windows for
-     * DLL-based path intuition to work correctly */
-#  if !defined(WIN32)
-       S_incpush_use_sep(aTHX_ STR_WITH_LEN(SITEARCH_EXP),
-                         INCPUSH_CAN_RELOCATE);
-#  endif
-#endif
-
-#ifdef SITELIB_EXP
-#  if defined(WIN32)
-    /* this picks up sitearch as well */
-       s = PerlEnv_sitelib_path(PERL_FS_VERSION, &len);
-       if (s)
-           incpush_use_sep(s, len, INCPUSH_ADD_SUB_DIRS|INCPUSH_CAN_RELOCATE);
-#  else
-       S_incpush_use_sep(aTHX_ STR_WITH_LEN(SITELIB_EXP), INCPUSH_CAN_RELOCATE);
-#  endif
-#endif
-
-#ifdef PERL_VENDORARCH_EXP
-    /* vendorarch is always relative to vendorlib on Windows for
-     * DLL-based path intuition to work correctly */
-#  if !defined(WIN32)
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(PERL_VENDORARCH_EXP),
-                     INCPUSH_CAN_RELOCATE);
-#  endif
-#endif
-
-#ifdef PERL_VENDORLIB_EXP
-#  if defined(WIN32)
-    /* this picks up vendorarch as well */
-       s = PerlEnv_vendorlib_path(PERL_FS_VERSION, &len);
-       if (s)
-           incpush_use_sep(s, len, INCPUSH_ADD_SUB_DIRS|INCPUSH_CAN_RELOCATE);
-#  else
-       S_incpush_use_sep(aTHX_ STR_WITH_LEN(PERL_VENDORLIB_EXP),
-                         INCPUSH_CAN_RELOCATE);
-#  endif
-#endif
-
-#ifdef ARCHLIB_EXP
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(ARCHLIB_EXP), INCPUSH_CAN_RELOCATE);
-#endif
-
-#ifndef PRIVLIB_EXP
-#  define PRIVLIB_EXP "/usr/local/lib/perl5:/usr/local/lib/perl"
-#endif
-
-#if defined(WIN32)
-    s = PerlEnv_lib_path(PERL_FS_VERSION, &len);
-    if (s)
-       incpush_use_sep(s, len, INCPUSH_ADD_SUB_DIRS|INCPUSH_CAN_RELOCATE);
-#else
-#  ifdef NETWARE
-    S_incpush_use_sep(aTHX_ PRIVLIB_EXP, 0, INCPUSH_CAN_RELOCATE);
-#  else
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(PRIVLIB_EXP), INCPUSH_CAN_RELOCATE);
-#  endif
-#endif
-
-#ifdef PERL_OTHERLIBDIRS
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(PERL_OTHERLIBDIRS),
-                     INCPUSH_ADD_VERSIONED_SUB_DIRS|INCPUSH_NOT_BASEDIR
-                     |INCPUSH_CAN_RELOCATE);
-#endif
-
-    if (!TAINTING_get) {
-#ifndef VMS
-/*
- * It isn't possible to delete an environment variable with
- * PERL_USE_SAFE_PUTENV set unless unsetenv() is also available, so in that
- * case we treat PERL5LIB as undefined if it has a zero-length value.
- */
-#if defined(PERL_USE_SAFE_PUTENV) && ! defined(HAS_UNSETENV)
-       if (perl5lib && *perl5lib != '\0')
-#else
-       if (perl5lib)
-#endif
-           incpush_use_sep(perl5lib, 0,
-                           INCPUSH_ADD_OLD_VERS|INCPUSH_NOT_BASEDIR);
-#else /* VMS */
-       /* Treat PERL5?LIB as a possible search list logical name -- the
-        * "natural" VMS idiom for a Unix path string.  We allow each
-        * element to be a set of |-separated directories for compatibility.
-        */
-       char buf[256];
-       int idx = 0;
-       if (vmstrnenv("PERL5LIB",buf,0,NULL,0))
-           do {
-               incpush_use_sep(buf, 0,
-                               INCPUSH_ADD_OLD_VERS|INCPUSH_NOT_BASEDIR);
-           } while (vmstrnenv("PERL5LIB",buf,++idx,NULL,0));
-#endif /* VMS */
-    }
-
-/* Use the ~-expanded versions of APPLLIB (undocumented),
-    SITELIB and VENDORLIB for older versions
-*/
-#ifdef APPLLIB_EXP
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(APPLLIB_EXP), INCPUSH_ADD_OLD_VERS
-                     |INCPUSH_NOT_BASEDIR|INCPUSH_CAN_RELOCATE);
-#endif
-
-#if defined(SITELIB_STEM) && defined(PERL_INC_VERSION_LIST)
-    /* Search for version-specific dirs below here */
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(SITELIB_STEM),
-                     INCPUSH_ADD_OLD_VERS|INCPUSH_CAN_RELOCATE);
-#endif
-
-
-#if defined(PERL_VENDORLIB_STEM) && defined(PERL_INC_VERSION_LIST)
-    /* Search for version-specific dirs below here */
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(PERL_VENDORLIB_STEM),
-                     INCPUSH_ADD_OLD_VERS|INCPUSH_CAN_RELOCATE);
-#endif
+    INCPUSH_APPLLIB_EXP
+    INCPUSH_SITEARCH_EXP
+    INCPUSH_SITELIB_EXP
+    INCPUSH_PERL_VENDORARCH_EXP
+    INCPUSH_PERL_VENDORLIB_EXP
+    INCPUSH_ARCHLIB_EXP
+    INCPUSH_PRIVLIB_EXP
+    INCPUSH_PERL_OTHERLIBDIRS
+    INCPUSH_PERL5LIB
+    INCPUSH_APPLLIB_OLD_EXP
+    INCPUSH_SITELIB_STEM
+    INCPUSH_PERL_VENDORLIB_STEM
+    INCPUSH_PERL_OTHERLIBDIRS_ARCHONLY
 
-#ifdef PERL_OTHERLIBDIRS
-    S_incpush_use_sep(aTHX_ STR_WITH_LEN(PERL_OTHERLIBDIRS),
-                     INCPUSH_ADD_OLD_VERS|INCPUSH_ADD_ARCHONLY_SUB_DIRS
-                     |INCPUSH_CAN_RELOCATE);
-#endif
 #endif /* !PERL_IS_MINIPERL */
 
     if (!TAINTING_get) {
@@ -4680,12 +4725,10 @@ S_init_perllib(pTHX)
 
 #if defined(DOSISH) || defined(__SYMBIAN32__)
 #    define PERLLIB_SEP ';'
-#else
-#  if defined(__VMS)
+#elif defined(__VMS)
 #    define PERLLIB_SEP PL_perllib_sep
-#  else
+#else
 #    define PERLLIB_SEP ':'
-#  endif
 #endif
 #ifndef PERLLIB_MANGLE
 #  define PERLLIB_MANGLE(s,n) (s)
@@ -4768,7 +4811,7 @@ S_mayberelocate(pTHX_ const char *const dir, STRLEN len, U32 flags)
         */
            const char *libpath = SvPVX(libdir);
            STRLEN libpath_len = SvCUR(libdir);
-           if (libpath_len >= 4 && memEQ (libpath, ".../", 4)) {
+           if (memBEGINs(libpath, libpath_len, ".../")) {
                /* Game on!  */
                SV * const caret_X = get_sv("\030", 0);
                /* Going to use the SV just as a scratch buffer holding a C
@@ -4794,12 +4837,9 @@ S_mayberelocate(pTHX_ const char *const dir, STRLEN len, U32 flags)
                libpath = SvPVX(libdir);
                libpath_len = SvCUR(libdir);
 
-               /* This would work more efficiently with memrchr, but as it's
-                  only a GNU extension we'd need to probe for it and
-                  implement our own. Not hard, but maybe not worth it?  */
-
                prefix = SvPVX(prefix_sv);
-               lastslash = strrchr(prefix, '/');
+               lastslash = (char *) my_memrchr(prefix, '/',
+                             SvEND(prefix_sv) - prefix);
 
                /* First time in with the *lastslash = '\0' we just wipe off
                   the trailing /perl from (say) /usr/foo/bin/perl
@@ -4807,8 +4847,11 @@ S_mayberelocate(pTHX_ const char *const dir, STRLEN len, U32 flags)
                if (lastslash) {
                    SV *tempsv;
                    while ((*lastslash = '\0'), /* Do that, come what may.  */
-                           (libpath_len >= 3 && _memEQs(libpath, "../")
-                           && (lastslash = strrchr(prefix, '/')))) {
+                           (   memBEGINs(libpath, libpath_len, "../")
+                           && (lastslash =
+                                  (char *) my_memrchr(prefix, '/',
+                                                   SvEND(prefix_sv) - prefix))))
+                    {
                        if (lastslash[1] == '\0'
                            || (lastslash[1] == '.'
                                && (lastslash[2] == '/' /* ends "/."  */
@@ -5011,7 +5054,7 @@ void
 Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
 {
     SV *atsv;
-    VOL const line_t oldline = PL_curcop ? CopLINE(PL_curcop) : 0;
+    volatile const line_t oldline = PL_curcop ? CopLINE(PL_curcop) : 0;
     CV *cv;
     STRLEN len;
     int ret;
@@ -5186,8 +5229,9 @@ Perl_my_failure_exit(pTHX)
 
 #else
     int exitstatus;
-    if (errno & 255)
-       STATUS_UNIX_SET(errno);
+    int eno = errno;
+    if (eno & 255)
+       STATUS_UNIX_SET(eno);
     else {
        exitstatus = STATUS_UNIX >> 8;
        if (exitstatus & 255)
@@ -5229,12 +5273,13 @@ static I32
 read_e_script(pTHX_ int idx, SV *buf_sv, int maxlen)
 {
     const char * const p  = SvPVX_const(PL_e_script);
-    const char *nl = strchr(p, '\n');
+    const char * const e  = SvEND(PL_e_script);
+    const char *nl = (char *) memchr(p, '\n', e - p);
 
     PERL_UNUSED_ARG(idx);
     PERL_UNUSED_ARG(maxlen);
 
-    nl = (nl) ? nl+1 : SvEND(PL_e_script);
+    nl = (nl) ? nl+1 : e;
     if (nl-p == 0) {
        filter_del(read_e_script);
        return 0;