char *getenv _((char *)); /* Usually in <stdlib.h> */
#endif
+#ifdef I_FCNTL
+#include <fcntl.h>
+#endif
+#ifdef I_SYS_FILE
+#include <sys/file.h>
+#endif
+
dEXTCONST char rcsid[] = "perl.c\nPatch level: ###\n";
#ifdef IAMSUID
COND_INIT(&eval_cond);
MUTEX_INIT(&threads_mutex);
COND_INIT(&nthreads_cond);
+#ifdef EMULATE_ATOMIC_REFCOUNTS
+ MUTEX_INIT(&svref_mutex);
+#endif /* EMULATE_ATOMIC_REFCOUNTS */
thr = init_main_thread();
#endif /* USE_THREADS */
#endif
}
+ init_stacks(ARGS);
#ifdef MULTIPLICITY
I_REINIT;
perl_destruct_level = 1;
localpatches = local_patches; /* For possible -v */
#endif
- PerlIO_init(); /* Hook to IO system */
+ PerlIO_init(); /* Hook to IO system */
- fdpid = newAV(); /* for remembering popen pids by fd */
+ fdpid = newAV(); /* for remembering popen pids by fd */
+ modglobal = newHV(); /* pointers to per-interpreter module globals */
- init_stacks(ARGS);
DEBUG( {
New(51,debname,128,char);
New(52,debdelim,128,char);
op_free(main_root);
main_root = Nullop;
}
+ curcop = &compiling;
main_start = Nullop;
SvREFCNT_dec(main_cv);
main_cv = Nullcv;
SvREFCNT_dec(parsehook);
parsehook = Nullsv;
+ /* call exit list functions */
+ while (exitlistlen-- > 0)
+ exitlist[exitlistlen].fn(exitlist[exitlistlen].ptr);
+
+ Safefree(exitlist);
+
if (destruct_level == 0){
DEBUG_P(debprofdump());
endav = Nullav;
initav = Nullav;
- /* temp stack during pp_sort() */
- SvREFCNT_dec(sortstack);
- sortstack = Nullav;
-
/* shortcuts just get cleared */
envgv = Nullgv;
siggv = Nullgv;
Safefree(sv_interp);
}
+void
+perl_atexit(void (*fn) (void *), void *ptr)
+{
+ Renew(exitlist, exitlistlen+1, PerlExitListEntry);
+ exitlist[exitlistlen].fn = fn;
+ exitlist[exitlistlen].ptr = ptr;
+ ++exitlistlen;
+}
+
int
perl_parse(PerlInterpreter *sv_interp, void (*xsinit) (void), int argc, char **argv, char **env)
{
char *validarg = "";
I32 oldscope;
AV* comppadlist;
+ int e_tmpfd = -1;
dJMPENV;
int ret;
s = argv[0]+1;
reswitch:
switch (*s) {
+ case ' ':
case '0':
case 'F':
case 'a':
if (euid != uid || egid != gid)
croak("No -e allowed in setuid scripts");
if (!e_fp) {
+#if defined(HAS_UMASK) && !defined(VMS)
+ int oldumask = PerlLIO_umask(0177);
+#endif
e_tmpname = savepv(TMPPATH);
+#ifdef HAS_MKSTEMP
+ e_tmpfd = PerlLIO_mkstemp(e_tmpname);
+#else /* use mktemp() */
(void)PerlLIO_mktemp(e_tmpname);
if (!*e_tmpname)
- croak("Can't mktemp()");
+ croak("Cannot generate temporary filename");
+# if defined(HAS_OPEN3) && defined(O_EXCL)
+ e_tmpfd = open(e_tmpname,
+ O_WRONLY | O_CREAT | O_EXCL,
+ 0600);
+# else
+ (void)UNLINK(e_tmpname);
+ /* Yes, potential race. But at least we can say we tried. */
e_fp = PerlIO_open(e_tmpname,"w");
- if (!e_fp)
- croak("Cannot open temporary file");
+# endif
+#endif /* ifdef HAS_MKSTEMP */
+#if defined(HAS_MKSTEMP) || (defined(HAS_OPEN3) && defined(O_EXCL))
+ if (e_tmpfd < 0)
+ croak("Cannot create temporary file \"%s\"", e_tmpname);
+ e_fp = PerlIO_fdopen(e_tmpfd,"w");
+#endif
+ if (!e_fp)
+ croak("Cannot create temporary file \"%s\"", e_tmpname);
+#if defined(HAS_UMASK) && !defined(VMS)
+ (void)PerlLIO_umask(oldumask);
+#endif
}
if (*++s)
PerlIO_puts(e_fp,s);
(void)UNLINK(e_tmpname);
Safefree(e_tmpname);
e_tmpname = Nullch;
+ e_tmpfd = -1;
}
/* now that script is parsed, we can modify record separator */
int
perl_run(PerlInterpreter *sv_interp)
{
- dTHR;
+ dSP;
I32 oldscope;
dJMPENV;
int ret;
JMPENV_POP;
return 1;
}
- if (curstack != mainstack) {
- dSP;
- SWITCHSTACK(curstack, mainstack);
- }
+ POPSTACK_TO(mainstack);
break;
}
{
dSP;
- PUSHMARK(sp);
+ PUSHMARK(SP);
if (argv) {
while (*argv) {
XPUSHs(sv_2mortal(newSVpv(*argv,0)));
/* See G_* flags in cop.h */
{
- dTHR;
+ dSP;
LOGOP myop; /* fake syntax tree node */
- SV** sp = stack_sp;
I32 oldmark;
I32 retval;
I32 oldscope;
&& (DBcv || (DBcv = GvCV(DBsub)))
/* Try harder, since this may have been a sighandler, thus
* curstash may be meaningless. */
- && (SvTYPE(sv) != SVt_PVCV || CvSTASH((CV*)sv) != debstash))
+ && (SvTYPE(sv) != SVt_PVCV || CvSTASH((CV*)sv) != debstash)
+ && !(flags & G_NODEBUG))
op->op_private |= OPpENTERSUB_DB;
if (flags & G_EVAL) {
/* See G_* flags in cop.h */
{
- dTHR;
+ dSP;
UNOP myop; /* fake syntax tree node */
- SV** sp = stack_sp;
- I32 oldmark = sp - stack_base;
+ I32 oldmark = SP - stack_base;
I32 retval;
I32 oldscope;
dJMPENV;
dSP;
SV* sv = newSVpv(p, 0);
- PUSHMARK(sp);
+ PUSHMARK(SP);
perl_eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
"-T turn on tainting checks",
"-u dump core after parsing script",
"-U allow unsafe operations",
-"-v print version number and patchlevel of perl",
+"-v print version number, patchlevel plus VERY IMPORTANT perl info",
"-V[:variable] print perl configuration information",
"-w TURN WARNINGS ON FOR COMPILATION OF YOUR SCRIPT. Recommended.",
"-x[directory] strip off text before #!perl line and perhaps cd to directory",
inplace = savepv(s+1);
/*SUPPRESS 530*/
for (s = inplace; *s && !isSPACE(*s); s++) ;
- if (*s)
+ if (*s) {
*s++ = '\0';
+ if (*s == '-') /* Additional switches on #! line. */
+ s++;
+ }
return s;
case 'I': /* -I handled both here and in parse_perl() */
forbid_setid("-I");
#endif
#ifdef DJGPP
printf("djgpp v2 port (jpl5003c) by Hirofumi Watanabe, 1996\n");
- printf("djgpp v2 port (perl5004) by Laszlo Molnar, 1997\n");
+ printf("djgpp v2 port (perl5004+) by Laszlo Molnar, 1997-1998\n");
#endif
#ifdef OS2
printf("\n\nOS/2 port Copyright (c) 1990, 1991, Raymond Chen, Kai Uwe Rommel\n"
#endif
printf("\n\
Perl may be copied only under the terms of either the Artistic License or the\n\
-GNU General Public License, which may be found in the Perl 5.0 source kit.\n\n");
+GNU General Public License, which may be found in the Perl 5.0 source kit.\n\n\
+Complete documentation for Perl, including FAQ lists, should be found on\n\
+this system using `man perl' or `perldoc perl'. If you have access to the\n\
+Internet, point your browser at http://www.perl.com/, the Perl Home Page.\n\n");
PerlProc_exit(0);
case 'w':
dowarn = TRUE;
/* compliments of Tom Christiansen */
/* unexec() can be found in the Gnu emacs distribution */
+/* Known to work with -DUNEXEC and using unexelf.c from GNU emacs-20.2 */
void
my_unexec(void)
#ifdef UNEXEC
SV* prog;
SV* file;
- int status;
+ int status = 1;
extern int etext;
- prog = newSVpv(BIN_EXP);
+ prog = newSVpv(BIN_EXP, 0);
sv_catpv(prog, "/perl");
- file = newSVpv(origfilename);
+ file = newSVpv(origfilename, 0);
sv_catpv(file, ".perldump");
- status = unexec(SvPVX(file), SvPVX(prog), &etext, sbrk(0), 0);
- if (status)
- PerlIO_printf(PerlIO_stderr(), "unexec of %s into %s failed!\n",
- SvPVX(prog), SvPVX(file));
+ unexec(SvPVX(file), SvPVX(prog), &etext, sbrk(0), 0);
+ /* unexec prints msg to stderr in case of failure */
PerlProc_exit(status);
#else
# ifdef VMS
open_script(char *scriptname, bool dosearch, SV *sv)
{
dTHR;
- char *xfound = Nullch;
- char *xfailed = Nullch;
register char *s;
- I32 len;
- int retval;
-#if defined(DOSISH) && !defined(OS2) && !defined(atarist)
-# define SEARCH_EXTS ".bat", ".cmd", NULL
-# define MAX_EXT_LEN 4
-#endif
-#ifdef OS2
-# define SEARCH_EXTS ".cmd", ".btm", ".bat", ".pl", NULL
-# define MAX_EXT_LEN 4
-#endif
-#ifdef VMS
-# define SEARCH_EXTS ".pl", ".com", NULL
-# define MAX_EXT_LEN 4
-#endif
- /* additional extensions to try in each dir if scriptname not found */
-#ifdef SEARCH_EXTS
- char *ext[] = { SEARCH_EXTS };
- int extidx = 0, i = 0;
- char *curext = Nullch;
-#else
-# define MAX_EXT_LEN 0
-#endif
-
- /*
- * If dosearch is true and if scriptname does not contain path
- * delimiters, search the PATH for scriptname.
- *
- * If SEARCH_EXTS is also defined, will look for each
- * scriptname{SEARCH_EXTS} whenever scriptname is not found
- * while searching the PATH.
- *
- * Assuming SEARCH_EXTS is C<".foo",".bar",NULL>, PATH search
- * proceeds as follows:
- * If DOSISH or VMSISH:
- * + look for ./scriptname{,.foo,.bar}
- * + search the PATH for scriptname{,.foo,.bar}
- *
- * If !DOSISH:
- * + look *only* in the PATH for scriptname{,.foo,.bar} (note
- * this will not look in '.' if it's not in the PATH)
- */
-#ifdef VMS
-# ifdef ALWAYS_DEFTYPES
- len = strlen(scriptname);
- if (!(len == 1 && *scriptname == '-') && scriptname[len-1] != ':') {
- int hasdir, idx = 0, deftypes = 1;
- bool seen_dot = 1;
-
- hasdir = !dosearch || (strpbrk(scriptname,":[</") != Nullch) ;
-# else
- if (dosearch) {
- int hasdir, idx = 0, deftypes = 1;
- bool seen_dot = 1;
-
- hasdir = (strpbrk(scriptname,":[</") != Nullch) ;
-# endif
- /* The first time through, just add SEARCH_EXTS to whatever we
- * already have, so we can check for default file types. */
- while (deftypes ||
- (!hasdir && my_trnlnm("DCL$PATH",tokenbuf,idx++)) )
- {
- if (deftypes) {
- deftypes = 0;
- *tokenbuf = '\0';
- }
- if ((strlen(tokenbuf) + strlen(scriptname)
- + MAX_EXT_LEN) >= sizeof tokenbuf)
- continue; /* don't search dir with too-long name */
- strcat(tokenbuf, scriptname);
-#else /* !VMS */
-
-#ifdef DOSISH
- if (strEQ(scriptname, "-"))
- dosearch = 0;
- if (dosearch) { /* Look in '.' first. */
- char *cur = scriptname;
-#ifdef SEARCH_EXTS
- if ((curext = strrchr(scriptname,'.'))) /* possible current ext */
- while (ext[i])
- if (strEQ(ext[i++],curext)) {
- extidx = -1; /* already has an ext */
- break;
- }
- do {
-#endif
- DEBUG_p(PerlIO_printf(Perl_debug_log,
- "Looking for %s\n",cur));
- if (Stat(cur,&statbuf) >= 0) {
- dosearch = 0;
- scriptname = cur;
-#ifdef SEARCH_EXTS
- break;
-#endif
- }
-#ifdef SEARCH_EXTS
- if (cur == scriptname) {
- len = strlen(scriptname);
- if (len+MAX_EXT_LEN+1 >= sizeof(tokenbuf))
- break;
- cur = strcpy(tokenbuf, scriptname);
- }
- } while (extidx >= 0 && ext[extidx] /* try an extension? */
- && strcpy(tokenbuf+len, ext[extidx++]));
-#endif
- }
-#endif
-
- if (dosearch && !strchr(scriptname, '/')
-#ifdef DOSISH
- && !strchr(scriptname, '\\')
-#endif
- && (s = PerlEnv_getenv("PATH"))) {
- bool seen_dot = 0;
-
- bufend = s + strlen(s);
- while (s < bufend) {
-#if defined(atarist) || defined(DOSISH)
- for (len = 0; *s
-# ifdef atarist
- && *s != ','
-# endif
- && *s != ';'; len++, s++) {
- if (len < sizeof tokenbuf)
- tokenbuf[len] = *s;
- }
- if (len < sizeof tokenbuf)
- tokenbuf[len] = '\0';
-#else /* ! (atarist || DOSISH) */
- s = delimcpy(tokenbuf, tokenbuf + sizeof tokenbuf, s, bufend,
- ':',
- &len);
-#endif /* ! (atarist || DOSISH) */
- if (s < bufend)
- s++;
- if (len + 1 + strlen(scriptname) + MAX_EXT_LEN >= sizeof tokenbuf)
- continue; /* don't search dir with too-long name */
- if (len
-#if defined(atarist) || defined(DOSISH)
- && tokenbuf[len - 1] != '/'
- && tokenbuf[len - 1] != '\\'
-#endif
- )
- tokenbuf[len++] = '/';
- if (len == 2 && tokenbuf[0] == '.')
- seen_dot = 1;
- (void)strcpy(tokenbuf + len, scriptname);
-#endif /* !VMS */
-
-#ifdef SEARCH_EXTS
- len = strlen(tokenbuf);
- if (extidx > 0) /* reset after previous loop */
- extidx = 0;
- do {
-#endif
- DEBUG_p(PerlIO_printf(Perl_debug_log, "Looking for %s\n",tokenbuf));
- retval = Stat(tokenbuf,&statbuf);
-#ifdef SEARCH_EXTS
- } while ( retval < 0 /* not there */
- && extidx>=0 && ext[extidx] /* try an extension? */
- && strcpy(tokenbuf+len, ext[extidx++])
- );
-#endif
- if (retval < 0)
- continue;
- if (S_ISREG(statbuf.st_mode)
- && cando(S_IRUSR,TRUE,&statbuf)
-#ifndef DOSISH
- && cando(S_IXUSR,TRUE,&statbuf)
-#endif
- )
- {
- xfound = tokenbuf; /* bingo! */
- break;
- }
- if (!xfailed)
- xfailed = savepv(tokenbuf);
- }
-#ifndef DOSISH
- if (!xfound && !seen_dot && !xfailed && (Stat(scriptname,&statbuf) < 0))
-#endif
- seen_dot = 1; /* Disable message. */
- if (!xfound)
- croak("Can't %s %s%s%s",
- (xfailed ? "execute" : "find"),
- (xfailed ? xfailed : scriptname),
- (xfailed ? "" : " on PATH"),
- (xfailed || seen_dot) ? "" : ", '.' not in PATH");
- if (xfailed)
- Safefree(xfailed);
- scriptname = xfound;
- }
+ scriptname = find_script(scriptname, dosearch, NULL, 0);
if (strnEQ(scriptname, "/dev/fd/", 8) && isDIGIT(scriptname[8]) ) {
char *s = scriptname + 8;
if (!rsfp) {
#ifdef DOSUID
#ifndef IAMSUID /* in case script is not readable before setuid */
- if (euid && Stat(SvPVX(GvSV(curcop->cop_filegv)),&statbuf) >= 0 &&
+ if (euid && PerlLIO_stat(SvPVX(GvSV(curcop->cop_filegv)),&statbuf) >= 0 &&
statbuf.st_mode & (S_ISUID|S_ISGID)) {
/* try again */
PerlProc_execv(form("%s/sperl%s", BIN_EXP, patchlevel), origargv);
#endif
|| getuid() != euid || geteuid() != uid)
croak("Can't swap uid and euid"); /* really paranoid */
- if (Stat(SvPVX(GvSV(curcop->cop_filegv)),&tmpstatbuf) < 0)
+ if (PerlLIO_stat(SvPVX(GvSV(curcop->cop_filegv)),&tmpstatbuf) < 0)
croak("Permission denied"); /* testing full pathname here */
if (tmpstatbuf.st_dev != statbuf.st_dev ||
tmpstatbuf.st_ino != statbuf.st_ino) {
curstash = defstash;
}
+#ifndef STRESS_REALLOC
+#define REASONABLE(size) (size)
+#else
+#define REASONABLE(size) (1) /* unreasonable */
+#endif
+
void
init_stacks(ARGSproto)
{
- curstack = newAV();
+ /* start with 128-item stack and 8K cxstack */
+ curstackinfo = new_stackinfo(REASONABLE(128),
+ REASONABLE(8192/sizeof(PERL_CONTEXT) - 1));
+ curstackinfo->si_type = SI_MAIN;
+ curstack = curstackinfo->si_stack;
mainstack = curstack; /* remember in case we switch stacks */
- AvREAL_off(curstack); /* not a real array */
- av_extend(curstack,127);
stack_base = AvARRAY(curstack);
stack_sp = stack_base;
- stack_max = stack_base + 127;
+ stack_max = stack_base + AvMAX(curstack);
- cxstack_max = 8192 / sizeof(PERL_CONTEXT) - 2; /* Use most of 8K. */
- New(50,cxstack,cxstack_max + 1,PERL_CONTEXT);
- cxstack_ix = -1;
-
- New(50,tmps_stack,128,SV*);
+ New(50,tmps_stack,REASONABLE(128),SV*);
tmps_floor = -1;
tmps_ix = -1;
- tmps_max = 128;
+ tmps_max = REASONABLE(128);
/*
* The following stacks almost certainly should be per-interpreter,
if (markstack) {
markstack_ptr = markstack;
} else {
- New(54,markstack,64,I32);
+ New(54,markstack,REASONABLE(32),I32);
markstack_ptr = markstack;
- markstack_max = markstack + 64;
+ markstack_max = markstack + REASONABLE(32);
}
+ SET_MARKBASE;
+
if (scopestack) {
scopestack_ix = 0;
} else {
- New(54,scopestack,32,I32);
+ New(54,scopestack,REASONABLE(32),I32);
scopestack_ix = 0;
- scopestack_max = 32;
+ scopestack_max = REASONABLE(32);
}
if (savestack) {
savestack_ix = 0;
} else {
- New(54,savestack,128,ANY);
+ New(54,savestack,REASONABLE(128),ANY);
savestack_ix = 0;
- savestack_max = 128;
+ savestack_max = REASONABLE(128);
}
if (retstack) {
retstack_ix = 0;
} else {
- New(54,retstack,16,OP*);
+ New(54,retstack,REASONABLE(16),OP*);
retstack_ix = 0;
- retstack_max = 16;
+ retstack_max = REASONABLE(16);
}
}
+#undef REASONABLE
+
static void
nuke_stacks(void)
{
dTHR;
- Safefree(cxstack);
+ while (curstackinfo->si_next)
+ curstackinfo = curstackinfo->si_next;
+ while (curstackinfo) {
+ PERL_SI *p = curstackinfo->si_prev;
+ /* curstackinfo->si_stack got nuked by sv_free_arenas() */
+ Safefree(curstackinfo->si_cxstack);
+ Safefree(curstackinfo);
+ curstackinfo = p;
+ }
Safefree(tmps_stack);
DEBUG( {
Safefree(debname);
ARCHLIB PRIVLIB SITEARCH and SITELIB
*/
#ifdef APPLLIB_EXP
- incpush(APPLLIB_EXP, FALSE);
+ incpush(APPLLIB_EXP, TRUE);
#endif
#ifdef ARCHLIB_EXP
/* .../archname/version if -d .../archname/version/auto */
sv_setsv(subdir, libdir);
sv_catpv(subdir, archpat_auto);
- if (Stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
+ if (PerlLIO_stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
S_ISDIR(tmpstatbuf.st_mode))
av_push(GvAVn(incgv),
newSVpv(SvPVX(subdir), SvCUR(subdir) - sizeof "auto"));
/* .../archname if -d .../archname/auto */
sv_insert(subdir, SvCUR(libdir) + sizeof(ARCHNAME),
strlen(patchlevel) + 1, "", 0);
- if (Stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
+ if (PerlLIO_stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
S_ISDIR(tmpstatbuf.st_mode))
av_push(GvAVn(incgv),
newSVpv(SvPVX(subdir), SvCUR(subdir) - sizeof "auto"));
SvLEN_set(thrsv, sizeof(thr));
*SvEND(thrsv) = '\0'; /* in the trailing_nul field */
thr->oursv = thrsv;
- curcop = &compiling;
chopset = " \n-";
MUTEX_LOCK(&threads_mutex);
STATUS_NATIVE_SET(vaxc$errno);
}
#else
+ int exitstatus;
if (errno & 255)
STATUS_POSIX_SET(errno);
- else if (STATUS_POSIX == 0)
- STATUS_POSIX_SET(255);
+ else {
+ exitstatus = STATUS_POSIX >> 8;
+ if (exitstatus & 255)
+ STATUS_POSIX_SET(exitstatus);
+ else
+ STATUS_POSIX_SET(255);
+ }
#endif
my_exit_jump();
}
static void
my_exit_jump(void)
{
- dTHR;
+ dSP;
register PERL_CONTEXT *cx;
I32 gimme;
SV **newsp;
e_tmpname = Nullch;
}
+ POPSTACK_TO(mainstack);
if (cxstack_ix >= 0) {
if (cxstack_ix > 0)
dounwind(0);