source: trunk/third/perl/perl.c @ 10730

Revision 10730, 64.3 KB checked in by ghudson, 27 years ago (diff)
Merge with perl 5.004_04. Previous local modifications are no longer necessary; will revert RCS file to vendor branch after this commit.
Line 
1/*    perl.c
2 *
3 *    Copyright (c) 1987-1997 Larry Wall
4 *
5 *    You may distribute under the terms of either the GNU General Public
6 *    License or the Artistic License, as specified in the README file.
7 *
8 */
9
10/*
11 * "A ship then new they built for him/of mithril and of elven glass" --Bilbo
12 */
13
14#include "EXTERN.h"
15#include "perl.h"
16#include "patchlevel.h"
17
18/* XXX If this causes problems, set i_unistd=undef in the hint file.  */
19#ifdef I_UNISTD
20#include <unistd.h>
21#endif
22
23#if !defined(STANDARD_C) && !defined(HAS_GETENV_PROTOTYPE)
24char *getenv _((char *)); /* Usually in <stdlib.h> */
25#endif
26
27dEXTCONST char rcsid[] = "perl.c\nPatch level: ###\n";
28
29#ifdef IAMSUID
30#ifndef DOSUID
31#define DOSUID
32#endif
33#endif
34
35#ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
36#ifdef DOSUID
37#undef DOSUID
38#endif
39#endif
40
41#define I_REINIT \
42  STMT_START {                  \
43    chopset     = " \n-";       \
44    copline     = NOLINE;       \
45    curcop      = &compiling;   \
46    curcopdb    = NULL;         \
47    cxstack_ix  = -1;           \
48    cxstack_max = 128;          \
49    dbargs      = 0;            \
50    dlmax       = 128;          \
51    laststatval = -1;           \
52    laststype   = OP_STAT;      \
53    maxscream   = -1;           \
54    maxsysfd    = MAXSYSFD;     \
55    statname    = Nullsv;       \
56    tmps_floor  = -1;           \
57    tmps_ix     = -1;           \
58    op_mask     = NULL;         \
59    dlmax       = 128;          \
60    laststatval = -1;           \
61    laststype   = OP_STAT;      \
62    mess_sv     = Nullsv;       \
63  } STMT_END
64
65static void find_beginning _((void));
66static void forbid_setid _((char *));
67static void incpush _((char *, int));
68static void init_ids _((void));
69static void init_debugger _((void));
70static void init_lexer _((void));
71static void init_main_stash _((void));
72static void init_perllib _((void));
73static void init_postdump_symbols _((int, char **, char **));
74static void init_predump_symbols _((void));
75static void init_stacks _((void));
76static void my_exit_jump _((void)) __attribute__((noreturn));
77static void nuke_stacks _((void));
78static void open_script _((char *, bool, SV *));
79static void usage _((char *));
80static void validate_suid _((char *, char*));
81
82static int fdscript = -1;
83
84PerlInterpreter *
85perl_alloc()
86{
87    PerlInterpreter *sv_interp;
88
89    curinterp = 0;
90    New(53, sv_interp, 1, PerlInterpreter);
91    return sv_interp;
92}
93
94void
95perl_construct( sv_interp )
96register PerlInterpreter *sv_interp;
97{
98    if (!(curinterp = sv_interp))
99        return;
100
101#ifdef MULTIPLICITY
102    Zero(sv_interp, 1, PerlInterpreter);
103#endif
104
105    /* Init the real globals? */
106    if (!linestr) {
107        linestr = NEWSV(65,80);
108        sv_upgrade(linestr,SVt_PVIV);
109
110        if (!SvREADONLY(&sv_undef)) {
111            SvREADONLY_on(&sv_undef);
112
113            sv_setpv(&sv_no,No);
114            SvNV(&sv_no);
115            SvREADONLY_on(&sv_no);
116
117            sv_setpv(&sv_yes,Yes);
118            SvNV(&sv_yes);
119            SvREADONLY_on(&sv_yes);
120        }
121
122        nrs = newSVpv("\n", 1);
123        rs = SvREFCNT_inc(nrs);
124
125        pidstatus = newHV();
126
127#ifdef MSDOS
128        /*
129         * There is no way we can refer to them from Perl so close them to save
130         * space.  The other alternative would be to provide STDAUX and STDPRN
131         * filehandles.
132         */
133        (void)fclose(stdaux);
134        (void)fclose(stdprn);
135#endif
136    }
137
138#ifdef MULTIPLICITY
139    I_REINIT;
140    perl_destruct_level = 1;
141#else
142   if(perl_destruct_level > 0)
143       I_REINIT;
144#endif
145
146    init_ids();
147    lex_state = LEX_NOTPARSING;
148
149    start_env.je_prev = NULL;
150    start_env.je_ret = -1;
151    start_env.je_mustcatch = TRUE;
152    top_env     = &start_env;
153    STATUS_ALL_SUCCESS;
154
155    SET_NUMERIC_STANDARD();
156#if defined(SUBVERSION) && SUBVERSION > 0
157    sprintf(patchlevel, "%7.5f",   (double) 5
158                                + ((double) PATCHLEVEL / (double) 1000)
159                                + ((double) SUBVERSION / (double) 100000));
160#else
161    sprintf(patchlevel, "%5.3f", (double) 5 +
162                                ((double) PATCHLEVEL / (double) 1000));
163#endif
164
165#if defined(LOCAL_PATCH_COUNT)
166    localpatches = local_patches;       /* For possible -v */
167#endif
168
169    PerlIO_init();      /* Hook to IO system */
170
171    fdpid = newAV();    /* for remembering popen pids by fd */
172
173    init_stacks();
174    ENTER;
175}
176
177void
178perl_destruct(sv_interp)
179register PerlInterpreter *sv_interp;
180{
181    int destruct_level;  /* 0=none, 1=full, 2=full with checks */
182    I32 last_sv_count;
183    HV *hv;
184
185    if (!(curinterp = sv_interp))
186        return;
187
188    destruct_level = perl_destruct_level;
189#ifdef DEBUGGING
190    {
191        char *s;
192        if (s = getenv("PERL_DESTRUCT_LEVEL")) {
193            int i = atoi(s);
194            if (destruct_level < i)
195                destruct_level = i;
196        }
197    }
198#endif
199
200    LEAVE;
201    FREETMPS;
202
203    /* We must account for everything.  */
204
205    /* Destroy the main CV and syntax tree */
206    if (main_root) {
207        curpad = AvARRAY(comppad);
208        op_free(main_root);
209        main_root = Nullop;
210    }
211    main_start = Nullop;
212    SvREFCNT_dec(main_cv);
213    main_cv = Nullcv;
214
215    if (sv_objcount) {
216        /*
217         * Try to destruct global references.  We do this first so that the
218         * destructors and destructees still exist.  Some sv's might remain.
219         * Non-referenced objects are on their own.
220         */
221   
222        dirty = TRUE;
223        sv_clean_objs();
224    }
225
226    /* unhook hooks which will soon be, or use, destroyed data */
227    SvREFCNT_dec(warnhook);
228    warnhook = Nullsv;
229    SvREFCNT_dec(diehook);
230    diehook = Nullsv;
231    SvREFCNT_dec(parsehook);
232    parsehook = Nullsv;
233
234    if (destruct_level == 0){
235
236        DEBUG_P(debprofdump());
237   
238        /* The exit() function will do everything that needs doing. */
239        return;
240    }
241
242    /* loosen bonds of global variables */
243
244    if(rsfp) {
245        (void)PerlIO_close(rsfp);
246        rsfp = Nullfp;
247    }
248
249    /* Filters for program text */
250    SvREFCNT_dec(rsfp_filters);
251    rsfp_filters = Nullav;
252
253    /* switches */
254    preprocess   = FALSE;
255    minus_n      = FALSE;
256    minus_p      = FALSE;
257    minus_l      = FALSE;
258    minus_a      = FALSE;
259    minus_F      = FALSE;
260    doswitches   = FALSE;
261    dowarn       = FALSE;
262    doextract    = FALSE;
263    sawampersand = FALSE;       /* must save all match strings */
264    sawstudy     = FALSE;       /* do fbm_instr on all strings */
265    sawvec       = FALSE;
266    unsafe       = FALSE;
267
268    Safefree(inplace);
269    inplace = Nullch;
270
271    Safefree(e_tmpname);
272    e_tmpname = Nullch;
273
274    if (e_fp) {
275        PerlIO_close(e_fp);
276        e_fp = Nullfp;
277    }
278
279    /* magical thingies */
280
281    Safefree(ofs);      /* $, */
282    ofs = Nullch;
283
284    Safefree(ors);      /* $\ */
285    ors = Nullch;
286
287    SvREFCNT_dec(nrs);  /* $\ helper */
288    nrs = Nullsv;
289
290    multiline = 0;      /* $* */
291
292    SvREFCNT_dec(statname);
293    statname = Nullsv;
294    statgv = Nullgv;
295
296    /* defgv, aka *_ should be taken care of elsewhere */
297
298#if 0  /* just about all regexp stuff, seems to be ok */
299
300    /* shortcuts to regexp stuff */
301    leftgv = Nullgv;
302    ampergv = Nullgv;
303
304    SAVEFREEOP(curpm);
305    SAVEFREEOP(oldlastpm); /* for saving regexp context during debugger */
306
307    regprecomp = NULL;  /* uncompiled string. */
308    regparse = NULL;    /* Input-scan pointer. */
309    regxend = NULL;     /* End of input for compile */
310    regnpar = 0;        /* () count. */
311    regcode = NULL;     /* Code-emit pointer; &regdummy = don't. */
312    regsize = 0;        /* Code size. */
313    regnaughty = 0;     /* How bad is this pattern? */
314    regsawback = 0;     /* Did we see \1, ...? */
315
316    reginput = NULL;            /* String-input pointer. */
317    regbol = NULL;              /* Beginning of input, for ^ check. */
318    regeol = NULL;              /* End of input, for $ check. */
319    regstartp = (char **)NULL;  /* Pointer to startp array. */
320    regendp = (char **)NULL;    /* Ditto for endp. */
321    reglastparen = 0;           /* Similarly for lastparen. */
322    regtill = NULL;             /* How far we are required to go. */
323    regflags = 0;               /* are we folding, multilining? */
324    regprev = (char)NULL;       /* char before regbol, \n if none */
325
326#endif /* if 0 */
327
328    /* clean up after study() */
329    SvREFCNT_dec(lastscream);
330    lastscream = Nullsv;
331    Safefree(screamfirst);
332    screamfirst = 0;
333    Safefree(screamnext);
334    screamnext  = 0;
335
336    /* startup and shutdown function lists */
337    SvREFCNT_dec(beginav);
338    SvREFCNT_dec(endav);
339    beginav = Nullav;
340    endav = Nullav;
341
342    /* temp stack during pp_sort() */
343    SvREFCNT_dec(sortstack);
344    sortstack = Nullav;
345
346    /* shortcuts just get cleared */
347    envgv = Nullgv;
348    siggv = Nullgv;
349    incgv = Nullgv;
350    errgv = Nullgv;
351    argvgv = Nullgv;
352    argvoutgv = Nullgv;
353    stdingv = Nullgv;
354    last_in_gv = Nullgv;
355
356    /* reset so print() ends up where we expect */
357    setdefout(Nullgv);
358
359    /* Prepare to destruct main symbol table.  */
360
361    hv = defstash;
362    defstash = 0;
363    SvREFCNT_dec(hv);
364
365    FREETMPS;
366    if (destruct_level >= 2) {
367        if (scopestack_ix != 0)
368            warn("Unbalanced scopes: %ld more ENTERs than LEAVEs\n",
369                 (long)scopestack_ix);
370        if (savestack_ix != 0)
371            warn("Unbalanced saves: %ld more saves than restores\n",
372                 (long)savestack_ix);
373        if (tmps_floor != -1)
374            warn("Unbalanced tmps: %ld more allocs than frees\n",
375                 (long)tmps_floor + 1);
376        if (cxstack_ix != -1)
377            warn("Unbalanced context: %ld more PUSHes than POPs\n",
378                 (long)cxstack_ix + 1);
379    }
380
381    /* Now absolutely destruct everything, somehow or other, loops or no. */
382    last_sv_count = 0;
383    SvFLAGS(strtab) |= SVTYPEMASK;              /* don't clean out strtab now */
384    while (sv_count != 0 && sv_count != last_sv_count) {
385        last_sv_count = sv_count;
386        sv_clean_all();
387    }
388    SvFLAGS(strtab) &= ~SVTYPEMASK;
389    SvFLAGS(strtab) |= SVt_PVHV;
390   
391    /* Destruct the global string table. */
392    {
393        /* Yell and reset the HeVAL() slots that are still holding refcounts,
394         * so that sv_free() won't fail on them.
395         */
396        I32 riter;
397        I32 max;
398        HE *hent;
399        HE **array;
400
401        riter = 0;
402        max = HvMAX(strtab);
403        array = HvARRAY(strtab);
404        hent = array[0];
405        for (;;) {
406            if (hent) {
407                warn("Unbalanced string table refcount: (%d) for \"%s\"",
408                     HeVAL(hent) - Nullsv, HeKEY(hent));
409                HeVAL(hent) = Nullsv;
410                hent = HeNEXT(hent);
411            }
412            if (!hent) {
413                if (++riter > max)
414                    break;
415                hent = array[riter];
416            }
417        }
418    }
419    SvREFCNT_dec(strtab);
420
421    if (sv_count != 0)
422        warn("Scalars leaked: %ld\n", (long)sv_count);
423
424    sv_free_arenas();
425
426    /* No SVs have survived, need to clean out */
427    linestr = NULL;
428    pidstatus = Nullhv;
429    if (origfilename)
430        Safefree(origfilename);
431    nuke_stacks();
432    hints = 0;          /* Reset hints. Should hints be per-interpreter ? */
433   
434    DEBUG_P(debprofdump());
435
436    /* As the absolutely last thing, free the non-arena SV for mess() */
437
438    if (mess_sv) {
439        /* we know that type >= SVt_PV */
440        SvOOK_off(mess_sv);
441        Safefree(SvPVX(mess_sv));
442        Safefree(SvANY(mess_sv));
443        Safefree(mess_sv);
444        mess_sv = Nullsv;
445    }
446}
447
448void
449perl_free(sv_interp)
450PerlInterpreter *sv_interp;
451{
452    if (!(curinterp = sv_interp))
453        return;
454    Safefree(sv_interp);
455}
456
457int
458perl_parse(sv_interp, xsinit, argc, argv, env)
459PerlInterpreter *sv_interp;
460void (*xsinit)_((void));
461int argc;
462char **argv;
463char **env;
464{
465    register SV *sv;
466    register char *s;
467    char *scriptname = NULL;
468    VOL bool dosearch = FALSE;
469    char *validarg = "";
470    I32 oldscope;
471    AV* comppadlist;
472    dJMPENV;
473    int ret;
474
475#ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
476#ifdef IAMSUID
477#undef IAMSUID
478    croak("suidperl is no longer needed since the kernel can now execute\n\
479setuid perl scripts securely.\n");
480#endif
481#endif
482
483    if (!(curinterp = sv_interp))
484        return 255;
485
486#if defined(NeXT) && defined(__DYNAMIC__)
487    _dyld_lookup_and_bind
488        ("__environ", (unsigned long *) &environ_pointer, NULL);
489#endif /* environ */
490
491    origargv = argv;
492    origargc = argc;
493#ifndef VMS  /* VMS doesn't have environ array */
494    origenviron = environ;
495#endif
496    e_tmpname = Nullch;
497
498    if (do_undump) {
499
500        /* Come here if running an undumped a.out. */
501
502        origfilename = savepv(argv[0]);
503        do_undump = FALSE;
504        cxstack_ix = -1;                /* start label stack again */
505        init_ids();
506        init_postdump_symbols(argc,argv,env);
507        return 0;
508    }
509
510    if (main_root) {
511        curpad = AvARRAY(comppad);
512        op_free(main_root);
513        main_root = Nullop;
514    }
515    main_start = Nullop;
516    SvREFCNT_dec(main_cv);
517    main_cv = Nullcv;
518
519    time(&basetime);
520    oldscope = scopestack_ix;
521
522    JMPENV_PUSH(ret);
523    switch (ret) {
524    case 1:
525        STATUS_ALL_FAILURE;
526        /* FALL THROUGH */
527    case 2:
528        /* my_exit() was called */
529        while (scopestack_ix > oldscope)
530            LEAVE;
531        FREETMPS;
532        curstash = defstash;
533        if (endav)
534            call_list(oldscope, endav);
535        JMPENV_POP;
536        return STATUS_NATIVE_EXPORT;
537    case 3:
538        JMPENV_POP;
539        PerlIO_printf(PerlIO_stderr(), "panic: top_env\n");
540        return 1;
541    }
542
543    sv_setpvn(linestr,"",0);
544    sv = newSVpv("",0);         /* first used for -I flags */
545    SAVEFREESV(sv);
546    init_main_stash();
547
548    for (argc--,argv++; argc > 0; argc--,argv++) {
549        if (argv[0][0] != '-' || !argv[0][1])
550            break;
551#ifdef DOSUID
552    if (*validarg)
553        validarg = " PHOOEY ";
554    else
555        validarg = argv[0];
556#endif
557        s = argv[0]+1;
558      reswitch:
559        switch (*s) {
560        case '0':
561        case 'F':
562        case 'a':
563        case 'c':
564        case 'd':
565        case 'D':
566        case 'h':
567        case 'i':
568        case 'l':
569        case 'M':
570        case 'm':
571        case 'n':
572        case 'p':
573        case 's':
574        case 'u':
575        case 'U':
576        case 'v':
577        case 'w':
578            if (s = moreswitches(s))
579                goto reswitch;
580            break;
581
582        case 'T':
583            tainting = TRUE;
584            s++;
585            goto reswitch;
586
587        case 'e':
588            if (euid != uid || egid != gid)
589                croak("No -e allowed in setuid scripts");
590            if (!e_fp) {
591                e_tmpname = savepv(TMPPATH);
592                (void)mktemp(e_tmpname);
593                if (!*e_tmpname)
594                    croak("Can't mktemp()");
595                e_fp = PerlIO_open(e_tmpname,"w");
596                if (!e_fp)
597                    croak("Cannot open temporary file");
598            }
599            if (*++s)
600                PerlIO_puts(e_fp,s);
601            else if (argv[1]) {
602                PerlIO_puts(e_fp,argv[1]);
603                argc--,argv++;
604            }
605            else
606                croak("No code specified for -e");
607            (void)PerlIO_putc(e_fp,'\n');
608            break;
609        case 'I':       /* -I handled both here and in moreswitches() */
610            forbid_setid("-I");
611            if (!*++s && (s=argv[1]) != Nullch) {
612                argc--,argv++;
613            }
614            while (s && isSPACE(*s))
615                ++s;
616            if (s && *s) {
617                char *e, *p;
618                for (e = s; *e && !isSPACE(*e); e++) ;
619                p = savepvn(s, e-s);
620                incpush(p, TRUE);
621                sv_catpv(sv,"-I");
622                sv_catpv(sv,p);
623                sv_catpv(sv," ");
624                Safefree(p);
625            }   /* XXX else croak? */
626            break;
627        case 'P':
628            forbid_setid("-P");
629            preprocess = TRUE;
630            s++;
631            goto reswitch;
632        case 'S':
633            forbid_setid("-S");
634            dosearch = TRUE;
635            s++;
636            goto reswitch;
637        case 'V':
638            if (!preambleav)
639                preambleav = newAV();
640            av_push(preambleav, newSVpv("use Config qw(myconfig config_vars)",0));
641            if (*++s != ':')  {
642                Sv = newSVpv("print myconfig();",0);
643#ifdef VMS
644                sv_catpv(Sv,"print \"\\nCharacteristics of this PERLSHR image: \\n\",");
645#else
646                sv_catpv(Sv,"print \"\\nCharacteristics of this binary (from libperl): \\n\",");
647#endif
648#if defined(DEBUGGING) || defined(NO_EMBED) || defined(MULTIPLICITY)
649                sv_catpv(Sv,"\"  Compile-time options:");
650#  ifdef DEBUGGING
651                sv_catpv(Sv," DEBUGGING");
652#  endif
653#  ifdef NO_EMBED
654                sv_catpv(Sv," NO_EMBED");
655#  endif
656#  ifdef MULTIPLICITY
657                sv_catpv(Sv," MULTIPLICITY");
658#  endif
659                sv_catpv(Sv,"\\n\",");
660#endif
661#if defined(LOCAL_PATCH_COUNT)
662                if (LOCAL_PATCH_COUNT > 0) {
663                    int i;
664                    sv_catpv(Sv,"\"  Locally applied patches:\\n\",");
665                    for (i = 1; i <= LOCAL_PATCH_COUNT; i++) {
666                        if (localpatches[i])
667                            sv_catpvf(Sv,"\"  \\t%s\\n\",",localpatches[i]);
668                    }
669                }
670#endif
671                sv_catpvf(Sv,"\"  Built under %s\\n\"",OSNAME);
672#ifdef __DATE__
673#  ifdef __TIME__
674                sv_catpvf(Sv,",\"  Compiled at %s %s\\n\"",__DATE__,__TIME__);
675#  else
676                sv_catpvf(Sv,",\"  Compiled on %s\\n\"",__DATE__);
677#  endif
678#endif
679                sv_catpv(Sv, "; \
680$\"=\"\\n    \"; \
681@env = map { \"$_=\\\"$ENV{$_}\\\"\" } sort grep {/^PERL/} keys %ENV; \
682print \"  \\%ENV:\\n    @env\\n\" if @env; \
683print \"  \\@INC:\\n    @INC\\n\";");
684            }
685            else {
686                Sv = newSVpv("config_vars(qw(",0);
687                sv_catpv(Sv, ++s);
688                sv_catpv(Sv, "))");
689                s += strlen(s);
690            }
691            av_push(preambleav, Sv);
692            scriptname = BIT_BUCKET;    /* don't look for script or read stdin */
693            goto reswitch;
694        case 'x':
695            doextract = TRUE;
696            s++;
697            if (*s)
698                cddir = savepv(s);
699            break;
700        case 0:
701            break;
702        case '-':
703            if (!*++s || isSPACE(*s)) {
704                argc--,argv++;
705                goto switch_end;
706            }
707            /* catch use of gnu style long options */
708            if (strEQ(s, "version")) {
709                s = "v";
710                goto reswitch;
711            }
712            if (strEQ(s, "help")) {
713                s = "h";
714                goto reswitch;
715            }
716            s--;
717            /* FALL THROUGH */
718        default:
719            croak("Unrecognized switch: -%s  (-h will show valid options)",s);
720        }
721    }
722  switch_end:
723
724    if (!tainting && (s = getenv("PERL5OPT"))) {
725        while (s && *s) {
726            while (isSPACE(*s))
727                s++;
728            if (*s == '-') {
729                s++;
730                if (isSPACE(*s))
731                    continue;
732            }
733            if (!*s)
734                break;
735            if (!strchr("DIMUdmw", *s))
736                croak("Illegal switch in PERL5OPT: -%c", *s);
737            s = moreswitches(s);
738        }
739    }
740
741    if (!scriptname)
742        scriptname = argv[0];
743    if (e_fp) {
744        if (PerlIO_flush(e_fp) || PerlIO_error(e_fp) || PerlIO_close(e_fp)) {
745#ifndef MULTIPLICITY
746            warn("Did you forget to compile with -DMULTIPLICITY?");
747#endif     
748            croak("Can't write to temp file for -e: %s", Strerror(errno));
749        }
750        e_fp = Nullfp;
751        argc++,argv--;
752        scriptname = e_tmpname;
753    }
754    else if (scriptname == Nullch) {
755#ifdef MSDOS
756        if ( isatty(PerlIO_fileno(PerlIO_stdin())) )
757            moreswitches("h");
758#endif
759        scriptname = "-";
760    }
761
762    init_perllib();
763
764    open_script(scriptname,dosearch,sv);
765
766    validate_suid(validarg, scriptname);
767
768    if (doextract)
769        find_beginning();
770
771    main_cv = compcv = (CV*)NEWSV(1104,0);
772    sv_upgrade((SV *)compcv, SVt_PVCV);
773    CvUNIQUE_on(compcv);
774
775    comppad = newAV();
776    av_push(comppad, Nullsv);
777    curpad = AvARRAY(comppad);
778    comppad_name = newAV();
779    comppad_name_fill = 0;
780    min_intro_pending = 0;
781    padix = 0;
782
783    comppadlist = newAV();
784    AvREAL_off(comppadlist);
785    av_store(comppadlist, 0, (SV*)comppad_name);
786    av_store(comppadlist, 1, (SV*)comppad);
787    CvPADLIST(compcv) = comppadlist;
788
789    boot_core_UNIVERSAL();
790    if (xsinit)
791        (*xsinit)();    /* in case linked C routines want magical variables */
792#if defined(VMS) || defined(WIN32)
793    init_os_extras();
794#endif
795
796    init_predump_symbols();
797    if (!do_undump)
798        init_postdump_symbols(argc,argv,env);
799
800    init_lexer();
801
802    /* now parse the script */
803
804    error_count = 0;
805    if (yyparse() || error_count) {
806        if (minus_c)
807            croak("%s had compilation errors.\n", origfilename);
808        else {
809            croak("Execution of %s aborted due to compilation errors.\n",
810                origfilename);
811        }
812    }
813    curcop->cop_line = 0;
814    curstash = defstash;
815    preprocess = FALSE;
816    if (e_tmpname) {
817        (void)UNLINK(e_tmpname);
818        Safefree(e_tmpname);
819        e_tmpname = Nullch;
820    }
821
822    /* now that script is parsed, we can modify record separator */
823    SvREFCNT_dec(rs);
824    rs = SvREFCNT_inc(nrs);
825    sv_setsv(GvSV(gv_fetchpv("/", TRUE, SVt_PV)), rs);
826
827    if (do_undump)
828        my_unexec();
829
830    if (dowarn)
831        gv_check(defstash);
832
833    LEAVE;
834    FREETMPS;
835
836#ifdef MYMALLOC
837    if ((s=getenv("PERL_DEBUG_MSTATS")) && atoi(s) >= 2)
838        dump_mstats("after compilation:");
839#endif
840
841    ENTER;
842    restartop = 0;
843    JMPENV_POP;
844    return 0;
845}
846
847int
848perl_run(sv_interp)
849PerlInterpreter *sv_interp;
850{
851    I32 oldscope;
852    dJMPENV;
853    int ret;
854
855    if (!(curinterp = sv_interp))
856        return 255;
857
858    oldscope = scopestack_ix;
859
860    JMPENV_PUSH(ret);
861    switch (ret) {
862    case 1:
863        cxstack_ix = -1;                /* start context stack again */
864        break;
865    case 2:
866        /* my_exit() was called */
867        while (scopestack_ix > oldscope)
868            LEAVE;
869        FREETMPS;
870        curstash = defstash;
871        if (endav)
872            call_list(oldscope, endav);
873#ifdef MYMALLOC
874        if (getenv("PERL_DEBUG_MSTATS"))
875            dump_mstats("after execution:  ");
876#endif
877        JMPENV_POP;
878        return STATUS_NATIVE_EXPORT;
879    case 3:
880        if (!restartop) {
881            PerlIO_printf(PerlIO_stderr(), "panic: restartop\n");
882            FREETMPS;
883            JMPENV_POP;
884            return 1;
885        }
886        if (curstack != mainstack) {
887            dSP;
888            SWITCHSTACK(curstack, mainstack);
889        }
890        break;
891    }
892
893    DEBUG_r(PerlIO_printf(Perl_debug_log, "%s $` $& $' support.\n",
894                    sawampersand ? "Enabling" : "Omitting"));
895
896    if (!restartop) {
897        DEBUG_x(dump_all());
898        DEBUG(PerlIO_printf(Perl_debug_log, "\nEXECUTING...\n\n"));
899
900        if (minus_c) {
901            PerlIO_printf(PerlIO_stderr(), "%s syntax OK\n", origfilename);
902            my_exit(0);
903        }
904        if (PERLDB_SINGLE && DBsingle)
905           sv_setiv(DBsingle, 1);
906    }
907
908    /* do it */
909
910    if (restartop) {
911        op = restartop;
912        restartop = 0;
913        runops();
914    }
915    else if (main_start) {
916        CvDEPTH(main_cv) = 1;
917        op = main_start;
918        runops();
919    }
920
921    my_exit(0);
922    /* NOTREACHED */
923    return 0;
924}
925
926SV*
927perl_get_sv(name, create)
928char* name;
929I32 create;
930{
931    GV* gv = gv_fetchpv(name, create, SVt_PV);
932    if (gv)
933        return GvSV(gv);
934    return Nullsv;
935}
936
937AV*
938perl_get_av(name, create)
939char* name;
940I32 create;
941{
942    GV* gv = gv_fetchpv(name, create, SVt_PVAV);
943    if (create)
944        return GvAVn(gv);
945    if (gv)
946        return GvAV(gv);
947    return Nullav;
948}
949
950HV*
951perl_get_hv(name, create)
952char* name;
953I32 create;
954{
955    GV* gv = gv_fetchpv(name, create, SVt_PVHV);
956    if (create)
957        return GvHVn(gv);
958    if (gv)
959        return GvHV(gv);
960    return Nullhv;
961}
962
963CV*
964perl_get_cv(name, create)
965char* name;
966I32 create;
967{
968    GV* gv = gv_fetchpv(name, create, SVt_PVCV);
969    if (create && !GvCVu(gv))
970        return newSUB(start_subparse(FALSE, 0),
971                      newSVOP(OP_CONST, 0, newSVpv(name,0)),
972                      Nullop,
973                      Nullop);
974    if (gv)
975        return GvCVu(gv);
976    return Nullcv;
977}
978
979/* Be sure to refetch the stack pointer after calling these routines. */
980
981I32
982perl_call_argv(subname, flags, argv)
983char *subname;
984I32 flags;              /* See G_* flags in cop.h */
985register char **argv;   /* null terminated arg list */
986{
987    dSP;
988
989    PUSHMARK(sp);
990    if (argv) {
991        while (*argv) {
992            XPUSHs(sv_2mortal(newSVpv(*argv,0)));
993            argv++;
994        }
995        PUTBACK;
996    }
997    return perl_call_pv(subname, flags);
998}
999
1000I32
1001perl_call_pv(subname, flags)
1002char *subname;          /* name of the subroutine */
1003I32 flags;              /* See G_* flags in cop.h */
1004{
1005    return perl_call_sv((SV*)perl_get_cv(subname, TRUE), flags);
1006}
1007
1008I32
1009perl_call_method(methname, flags)
1010char *methname;         /* name of the subroutine */
1011I32 flags;              /* See G_* flags in cop.h */
1012{
1013    dSP;
1014    OP myop;
1015    if (!op)
1016        op = &myop;
1017    XPUSHs(sv_2mortal(newSVpv(methname,0)));
1018    PUTBACK;
1019    pp_method();
1020    return perl_call_sv(*stack_sp--, flags);
1021}
1022
1023/* May be called with any of a CV, a GV, or an SV containing the name. */
1024I32
1025perl_call_sv(sv, flags)
1026SV* sv;
1027I32 flags;              /* See G_* flags in cop.h */
1028{
1029    LOGOP myop;         /* fake syntax tree node */
1030    SV** sp = stack_sp;
1031    I32 oldmark;
1032    I32 retval;
1033    I32 oldscope;
1034    static CV *DBcv;
1035    bool oldcatch = CATCH_GET;
1036    dJMPENV;
1037    int ret;
1038    OP* oldop = op;
1039
1040    if (flags & G_DISCARD) {
1041        ENTER;
1042        SAVETMPS;
1043    }
1044
1045    Zero(&myop, 1, LOGOP);
1046    myop.op_next = Nullop;
1047    if (!(flags & G_NOARGS))
1048        myop.op_flags |= OPf_STACKED;
1049    myop.op_flags |= ((flags & G_VOID) ? OPf_WANT_VOID :
1050                      (flags & G_ARRAY) ? OPf_WANT_LIST :
1051                      OPf_WANT_SCALAR);
1052    SAVESPTR(op);
1053    op = (OP*)&myop;
1054
1055    EXTEND(stack_sp, 1);
1056    *++stack_sp = sv;
1057    oldmark = TOPMARK;
1058    oldscope = scopestack_ix;
1059
1060    if (PERLDB_SUB && curstash != debstash
1061           /* Handle first BEGIN of -d. */
1062          && (DBcv || (DBcv = GvCV(DBsub)))
1063           /* Try harder, since this may have been a sighandler, thus
1064            * curstash may be meaningless. */
1065          && (SvTYPE(sv) != SVt_PVCV || CvSTASH((CV*)sv) != debstash))
1066        op->op_private |= OPpENTERSUB_DB;
1067
1068    if (flags & G_EVAL) {
1069        cLOGOP->op_other = op;
1070        markstack_ptr--;
1071        /* we're trying to emulate pp_entertry() here */
1072        {
1073            register CONTEXT *cx;
1074            I32 gimme = GIMME_V;
1075           
1076            ENTER;
1077            SAVETMPS;
1078           
1079            push_return(op->op_next);
1080            PUSHBLOCK(cx, CXt_EVAL, stack_sp);
1081            PUSHEVAL(cx, 0, 0);
1082            eval_root = op;             /* Only needed so that goto works right. */
1083           
1084            in_eval = 1;
1085            if (flags & G_KEEPERR)
1086                in_eval |= 4;
1087            else
1088                sv_setpv(GvSV(errgv),"");
1089        }
1090        markstack_ptr++;
1091
1092        JMPENV_PUSH(ret);
1093        switch (ret) {
1094        case 0:
1095            break;
1096        case 1:
1097            STATUS_ALL_FAILURE;
1098            /* FALL THROUGH */
1099        case 2:
1100            /* my_exit() was called */
1101            curstash = defstash;
1102            FREETMPS;
1103            JMPENV_POP;
1104            if (statusvalue)
1105                croak("Callback called exit");
1106            my_exit_jump();
1107            /* NOTREACHED */
1108        case 3:
1109            if (restartop) {
1110                op = restartop;
1111                restartop = 0;
1112                break;
1113            }
1114            stack_sp = stack_base + oldmark;
1115            if (flags & G_ARRAY)
1116                retval = 0;
1117            else {
1118                retval = 1;
1119                *++stack_sp = &sv_undef;
1120            }
1121            goto cleanup;
1122        }
1123    }
1124    else
1125        CATCH_SET(TRUE);
1126
1127    if (op == (OP*)&myop)
1128        op = pp_entersub();
1129    if (op)
1130        runops();
1131    retval = stack_sp - (stack_base + oldmark);
1132    if ((flags & G_EVAL) && !(flags & G_KEEPERR))
1133        sv_setpv(GvSV(errgv),"");
1134
1135  cleanup:
1136    if (flags & G_EVAL) {
1137        if (scopestack_ix > oldscope) {
1138            SV **newsp;
1139            PMOP *newpm;
1140            I32 gimme;
1141            register CONTEXT *cx;
1142            I32 optype;
1143
1144            POPBLOCK(cx,newpm);
1145            POPEVAL(cx);
1146            pop_return();
1147            curpm = newpm;
1148            LEAVE;
1149        }
1150        JMPENV_POP;
1151    }
1152    else
1153        CATCH_SET(oldcatch);
1154
1155    if (flags & G_DISCARD) {
1156        stack_sp = stack_base + oldmark;
1157        retval = 0;
1158        FREETMPS;
1159        LEAVE;
1160    }
1161    op = oldop;
1162    return retval;
1163}
1164
1165/* Eval a string. The G_EVAL flag is always assumed. */
1166
1167I32
1168perl_eval_sv(sv, flags)
1169SV* sv;
1170I32 flags;              /* See G_* flags in cop.h */
1171{
1172    UNOP myop;          /* fake syntax tree node */
1173    SV** sp = stack_sp;
1174    I32 oldmark = sp - stack_base;
1175    I32 retval;
1176    I32 oldscope;
1177    dJMPENV;
1178    int ret;
1179    OP* oldop = op;
1180
1181    if (flags & G_DISCARD) {
1182        ENTER;
1183        SAVETMPS;
1184    }
1185
1186    SAVESPTR(op);
1187    op = (OP*)&myop;
1188    Zero(op, 1, UNOP);
1189    EXTEND(stack_sp, 1);
1190    *++stack_sp = sv;
1191    oldscope = scopestack_ix;
1192
1193    if (!(flags & G_NOARGS))
1194        myop.op_flags = OPf_STACKED;
1195    myop.op_next = Nullop;
1196    myop.op_type = OP_ENTEREVAL;
1197    myop.op_flags |= ((flags & G_VOID) ? OPf_WANT_VOID :
1198                      (flags & G_ARRAY) ? OPf_WANT_LIST :
1199                      OPf_WANT_SCALAR);
1200    if (flags & G_KEEPERR)
1201        myop.op_flags |= OPf_SPECIAL;
1202
1203    JMPENV_PUSH(ret);
1204    switch (ret) {
1205    case 0:
1206        break;
1207    case 1:
1208        STATUS_ALL_FAILURE;
1209        /* FALL THROUGH */
1210    case 2:
1211        /* my_exit() was called */
1212        curstash = defstash;
1213        FREETMPS;
1214        JMPENV_POP;
1215        if (statusvalue)
1216            croak("Callback called exit");
1217        my_exit_jump();
1218        /* NOTREACHED */
1219    case 3:
1220        if (restartop) {
1221            op = restartop;
1222            restartop = 0;
1223            break;
1224        }
1225        stack_sp = stack_base + oldmark;
1226        if (flags & G_ARRAY)
1227            retval = 0;
1228        else {
1229            retval = 1;
1230            *++stack_sp = &sv_undef;
1231        }
1232        goto cleanup;
1233    }
1234
1235    if (op == (OP*)&myop)
1236        op = pp_entereval();
1237    if (op)
1238        runops();
1239    retval = stack_sp - (stack_base + oldmark);
1240    if (!(flags & G_KEEPERR))
1241        sv_setpv(GvSV(errgv),"");
1242
1243  cleanup:
1244    JMPENV_POP;
1245    if (flags & G_DISCARD) {
1246        stack_sp = stack_base + oldmark;
1247        retval = 0;
1248        FREETMPS;
1249        LEAVE;
1250    }
1251    op = oldop;
1252    return retval;
1253}
1254
1255SV*
1256perl_eval_pv(p, croak_on_error)
1257char* p;
1258I32 croak_on_error;
1259{
1260    dSP;
1261    SV* sv = newSVpv(p, 0);
1262
1263    PUSHMARK(sp);
1264    perl_eval_sv(sv, G_SCALAR);
1265    SvREFCNT_dec(sv);
1266
1267    SPAGAIN;
1268    sv = POPs;
1269    PUTBACK;
1270
1271    if (croak_on_error && SvTRUE(GvSV(errgv)))
1272        croak(SvPVx(GvSV(errgv), na));
1273
1274    return sv;
1275}
1276
1277/* Require a module. */
1278
1279void
1280perl_require_pv(pv)
1281char* pv;
1282{
1283    SV* sv = sv_newmortal();
1284    sv_setpv(sv, "require '");
1285    sv_catpv(sv, pv);
1286    sv_catpv(sv, "'");
1287    perl_eval_sv(sv, G_DISCARD);
1288}
1289
1290void
1291magicname(sym,name,namlen)
1292char *sym;
1293char *name;
1294I32 namlen;
1295{
1296    register GV *gv;
1297
1298    if (gv = gv_fetchpv(sym,TRUE, SVt_PV))
1299        sv_magic(GvSV(gv), (SV*)gv, 0, name, namlen);
1300}
1301
1302static void
1303usage(name)             /* XXX move this out into a module ? */
1304char *name;
1305{
1306    /* This message really ought to be max 23 lines.
1307     * Removed -h because the user already knows that opton. Others? */
1308
1309    static char *usage[] = {
1310"-0[octal]       specify record separator (\\0, if no argument)",
1311"-a              autosplit mode with -n or -p (splits $_ into @F)",
1312"-c              check syntax only (runs BEGIN and END blocks)",
1313"-d[:debugger]   run scripts under debugger",
1314"-D[number/list] set debugging flags (argument is a bit mask or flags)",
1315"-e 'command'    one line of script. Several -e's allowed. Omit [programfile].",
1316"-F/pattern/     split() pattern for autosplit (-a). The //'s are optional.",
1317"-i[extension]   edit <> files in place (make backup if extension supplied)",
1318"-Idirectory     specify @INC/#include directory (may be used more than once)",
1319"-l[octal]       enable line ending processing, specifies line terminator",
1320"-[mM][-]module.. executes `use/no module...' before executing your script.",
1321"-n              assume 'while (<>) { ... }' loop around your script",
1322"-p              assume loop like -n but print line also like sed",
1323"-P              run script through C preprocessor before compilation",
1324"-s              enable some switch parsing for switches after script name",
1325"-S              look for the script using PATH environment variable",
1326"-T              turn on tainting checks",
1327"-u              dump core after parsing script",
1328"-U              allow unsafe operations",
1329"-v              print version number and patchlevel of perl",
1330"-V[:variable]   print perl configuration information",
1331"-w              TURN WARNINGS ON FOR COMPILATION OF YOUR SCRIPT. Recommended.",
1332"-x[directory]   strip off text before #!perl line and perhaps cd to directory",
1333"\n",
1334NULL
1335};
1336    char **p = usage;
1337
1338    printf("\nUsage: %s [switches] [--] [programfile] [arguments]", name);
1339    while (*p)
1340        printf("\n  %s", *p++);
1341}
1342
1343/* This routine handles any switches that can be given during run */
1344
1345char *
1346moreswitches(s)
1347char *s;
1348{
1349    I32 numlen;
1350    U32 rschar;
1351
1352    switch (*s) {
1353    case '0':
1354        rschar = scan_oct(s, 4, &numlen);
1355        SvREFCNT_dec(nrs);
1356        if (rschar & ~((U8)~0))
1357            nrs = &sv_undef;
1358        else if (!rschar && numlen >= 2)
1359            nrs = newSVpv("", 0);
1360        else {
1361            char ch = rschar;
1362            nrs = newSVpv(&ch, 1);
1363        }
1364        return s + numlen;
1365    case 'F':
1366        minus_F = TRUE;
1367        splitstr = savepv(s + 1);
1368        s += strlen(s);
1369        return s;
1370    case 'a':
1371        minus_a = TRUE;
1372        s++;
1373        return s;
1374    case 'c':
1375        minus_c = TRUE;
1376        s++;
1377        return s;
1378    case 'd':
1379        forbid_setid("-d");
1380        s++;
1381        if (*s == ':' || *s == '=')  {
1382            my_setenv("PERL5DB", form("use Devel::%s;", ++s));
1383            s += strlen(s);
1384        }
1385        if (!perldb) {
1386            perldb = PERLDB_ALL;
1387            init_debugger();
1388        }
1389        return s;
1390    case 'D':
1391#ifdef DEBUGGING
1392        forbid_setid("-D");
1393        if (isALPHA(s[1])) {
1394            static char debopts[] = "psltocPmfrxuLHXD";
1395            char *d;
1396
1397            for (s++; *s && (d = strchr(debopts,*s)); s++)
1398                debug |= 1 << (d - debopts);
1399        }
1400        else {
1401            debug = atoi(s+1);
1402            for (s++; isDIGIT(*s); s++) ;
1403        }
1404        debug |= 0x80000000;
1405#else
1406        warn("Recompile perl with -DDEBUGGING to use -D switch\n");
1407        for (s++; isALNUM(*s); s++) ;
1408#endif
1409        /*SUPPRESS 530*/
1410        return s;
1411    case 'h':
1412        usage(origargv[0]);   
1413        exit(0);
1414    case 'i':
1415        if (inplace)
1416            Safefree(inplace);
1417        inplace = savepv(s+1);
1418        /*SUPPRESS 530*/
1419        for (s = inplace; *s && !isSPACE(*s); s++) ;
1420        if (*s)
1421            *s++ = '\0';
1422        return s;
1423    case 'I':   /* -I handled both here and in parse_perl() */
1424        forbid_setid("-I");
1425        ++s;
1426        while (*s && isSPACE(*s))
1427            ++s;
1428        if (*s) {
1429            char *e, *p;
1430            for (e = s; *e && !isSPACE(*e); e++) ;
1431            p = savepvn(s, e-s);
1432            incpush(p, TRUE);
1433            Safefree(p);
1434            s = e;
1435        }
1436        else
1437            croak("No space allowed after -I");
1438        return s;
1439    case 'l':
1440        minus_l = TRUE;
1441        s++;
1442        if (ors)
1443            Safefree(ors);
1444        if (isDIGIT(*s)) {
1445            ors = savepv("\n");
1446            orslen = 1;
1447            *ors = scan_oct(s, 3 + (*s == '0'), &numlen);
1448            s += numlen;
1449        }
1450        else {
1451            if (RsPARA(nrs)) {
1452                ors = "\n\n";
1453                orslen = 2;
1454            }
1455            else
1456                ors = SvPV(nrs, orslen);
1457            ors = savepvn(ors, orslen);
1458        }
1459        return s;
1460    case 'M':
1461        forbid_setid("-M");     /* XXX ? */
1462        /* FALL THROUGH */
1463    case 'm':
1464        forbid_setid("-m");     /* XXX ? */
1465        if (*++s) {
1466            char *start;
1467            char *use = "use ";
1468            /* -M-foo == 'no foo'       */
1469            if (*s == '-') { use = "no "; ++s; }
1470            Sv = newSVpv(use,0);
1471            start = s;
1472            /* We allow -M'Module qw(Foo Bar)'  */
1473            while(isALNUM(*s) || *s==':') ++s;
1474            if (*s != '=') {
1475                sv_catpv(Sv, start);
1476                if (*(start-1) == 'm') {
1477                    if (*s != '\0')
1478                        croak("Can't use '%c' after -mname", *s);
1479                    sv_catpv( Sv, " ()");
1480                }
1481            } else {
1482                sv_catpvn(Sv, start, s-start);
1483                sv_catpv(Sv, " split(/,/,q{");
1484                sv_catpv(Sv, ++s);
1485                sv_catpv(Sv,    "})");
1486            }
1487            s += strlen(s);
1488            if (preambleav == NULL)
1489                preambleav = newAV();
1490            av_push(preambleav, Sv);
1491        }
1492        else
1493            croak("No space allowed after -%c", *(s-1));
1494        return s;
1495    case 'n':
1496        minus_n = TRUE;
1497        s++;
1498        return s;
1499    case 'p':
1500        minus_p = TRUE;
1501        s++;
1502        return s;
1503    case 's':
1504        forbid_setid("-s");
1505        doswitches = TRUE;
1506        s++;
1507        return s;
1508    case 'T':
1509        if (!tainting)
1510            croak("Too late for \"-T\" option");
1511        s++;
1512        return s;
1513    case 'u':
1514        do_undump = TRUE;
1515        s++;
1516        return s;
1517    case 'U':
1518        unsafe = TRUE;
1519        s++;
1520        return s;
1521    case 'v':
1522#if defined(SUBVERSION) && SUBVERSION > 0
1523        printf("\nThis is perl, version 5.%03d_%02d built for %s",
1524            PATCHLEVEL, SUBVERSION, ARCHNAME);
1525#else
1526        printf("\nThis is perl, version %s built for %s",
1527                patchlevel, ARCHNAME);
1528#endif
1529#if defined(LOCAL_PATCH_COUNT)
1530        if (LOCAL_PATCH_COUNT > 0)
1531            printf("\n(with %d registered patch%s, see perl -V for more detail)",
1532                LOCAL_PATCH_COUNT, (LOCAL_PATCH_COUNT!=1) ? "es" : "");
1533#endif
1534
1535        printf("\n\nCopyright 1987-1997, Larry Wall\n");
1536#ifdef MSDOS
1537        printf("\nMS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n");
1538#endif
1539#ifdef DJGPP
1540        printf("djgpp v2 port (jpl5003c) by Hirofumi Watanabe, 1996\n");
1541#endif
1542#ifdef OS2
1543        printf("\n\nOS/2 port Copyright (c) 1990, 1991, Raymond Chen, Kai Uwe Rommel\n"
1544            "Version 5 port Copyright (c) 1994-1997, Andreas Kaiser, Ilya Zakharevich\n");
1545#endif
1546#ifdef atarist
1547        printf("atariST series port, ++jrb  bammi@cadence.com\n");
1548#endif
1549        printf("\n\
1550Perl may be copied only under the terms of either the Artistic License or the\n\
1551GNU General Public License, which may be found in the Perl 5.0 source kit.\n\n");
1552        exit(0);
1553    case 'w':
1554        dowarn = TRUE;
1555        s++;
1556        return s;
1557    case '*':
1558    case ' ':
1559        if (s[1] == '-')        /* Additional switches on #! line. */
1560            return s+2;
1561        break;
1562    case '-':
1563    case 0:
1564    case '\n':
1565    case '\t':
1566        break;
1567#ifdef ALTERNATE_SHEBANG
1568    case 'S':                   /* OS/2 needs -S on "extproc" line. */
1569        break;
1570#endif
1571    case 'P':
1572        if (preprocess)
1573            return s+1;
1574        /* FALL THROUGH */
1575    default:
1576        croak("Can't emulate -%.1s on #! line",s);
1577    }
1578    return Nullch;
1579}
1580
1581/* compliments of Tom Christiansen */
1582
1583/* unexec() can be found in the Gnu emacs distribution */
1584
1585void
1586my_unexec()
1587{
1588#ifdef UNEXEC
1589    SV*    prog;
1590    SV*    file;
1591    int    status;
1592    extern int etext;
1593
1594    prog = newSVpv(BIN_EXP);
1595    sv_catpv(prog, "/perl");
1596    file = newSVpv(origfilename);
1597    sv_catpv(file, ".perldump");
1598
1599    status = unexec(SvPVX(file), SvPVX(prog), &etext, sbrk(0), 0);
1600    if (status)
1601        PerlIO_printf(PerlIO_stderr(), "unexec of %s into %s failed!\n",
1602                      SvPVX(prog), SvPVX(file));
1603    exit(status);
1604#else
1605#  ifdef VMS
1606#    include <lib$routines.h>
1607     lib$signal(SS$_DEBUG);  /* ssdef.h #included from vmsish.h */
1608#  else
1609    ABORT();            /* for use with undump */
1610#  endif
1611#endif
1612}
1613
1614static void
1615init_main_stash()
1616{
1617    GV *gv;
1618
1619    /* Note that strtab is a rather special HV.  Assumptions are made
1620       about not iterating on it, and not adding tie magic to it.
1621       It is properly deallocated in perl_destruct() */
1622    strtab = newHV();
1623    HvSHAREKEYS_off(strtab);                    /* mandatory */
1624    Newz(506,((XPVHV*)SvANY(strtab))->xhv_array,
1625         sizeof(HE*) * (((XPVHV*)SvANY(strtab))->xhv_max + 1), char);
1626   
1627    curstash = defstash = newHV();
1628    curstname = newSVpv("main",4);
1629    gv = gv_fetchpv("main::",TRUE, SVt_PVHV);
1630    SvREFCNT_dec(GvHV(gv));
1631    GvHV(gv) = (HV*)SvREFCNT_inc(defstash);
1632    SvREADONLY_on(gv);
1633    HvNAME(defstash) = savepv("main");
1634    incgv = gv_HVadd(gv_AVadd(gv_fetchpv("INC",TRUE, SVt_PVAV)));
1635    GvMULTI_on(incgv);
1636    defgv = gv_fetchpv("_",TRUE, SVt_PVAV);
1637    errgv = gv_HVadd(gv_fetchpv("@", TRUE, SVt_PV));
1638    GvMULTI_on(errgv);
1639    (void)form("%240s","");     /* Preallocate temp - for immediate signals. */
1640    sv_grow(GvSV(errgv), 240);  /* Preallocate - for immediate signals. */
1641    sv_setpvn(GvSV(errgv), "", 0);
1642    curstash = defstash;
1643    compiling.cop_stash = defstash;
1644    debstash = GvHV(gv_fetchpv("DB::", GV_ADDMULTI, SVt_PVHV));
1645    /* We must init $/ before switches are processed. */
1646    sv_setpvn(GvSV(gv_fetchpv("/", TRUE, SVt_PV)), "\n", 1);
1647}
1648
1649#ifdef CAN_PROTOTYPE
1650static void
1651open_script(char *scriptname, bool dosearch, SV *sv)
1652#else
1653static void
1654open_script(scriptname,dosearch,sv)
1655char *scriptname;
1656bool dosearch;
1657SV *sv;
1658#endif
1659{
1660    char *xfound = Nullch;
1661    char *xfailed = Nullch;
1662    register char *s;
1663    I32 len;
1664    int retval;
1665#if defined(DOSISH) && !defined(OS2) && !defined(atarist)
1666#  define SEARCH_EXTS ".bat", ".cmd", NULL
1667#  define MAX_EXT_LEN 4
1668#endif
1669#ifdef OS2
1670#  define SEARCH_EXTS ".cmd", ".btm", ".bat", ".pl", NULL
1671#  define MAX_EXT_LEN 4
1672#endif
1673#ifdef VMS
1674#  define SEARCH_EXTS ".pl", ".com", NULL
1675#  define MAX_EXT_LEN 4
1676#endif
1677    /* additional extensions to try in each dir if scriptname not found */
1678#ifdef SEARCH_EXTS
1679    char *ext[] = { SEARCH_EXTS };
1680    int extidx = 0, i = 0;
1681    char *curext = Nullch;
1682#else
1683#  define MAX_EXT_LEN 0
1684#endif
1685
1686    /*
1687     * If dosearch is true and if scriptname does not contain path
1688     * delimiters, search the PATH for scriptname.
1689     *
1690     * If SEARCH_EXTS is also defined, will look for each
1691     * scriptname{SEARCH_EXTS} whenever scriptname is not found
1692     * while searching the PATH.
1693     *
1694     * Assuming SEARCH_EXTS is C<".foo",".bar",NULL>, PATH search
1695     * proceeds as follows:
1696     *   If DOSISH:
1697     *     + look for ./scriptname{,.foo,.bar}
1698     *     + search the PATH for scriptname{,.foo,.bar}
1699     *
1700     *   If !DOSISH:
1701     *     + look *only* in the PATH for scriptname{,.foo,.bar} (note
1702     *       this will not look in '.' if it's not in the PATH)
1703     */
1704
1705#ifdef VMS
1706    if (dosearch) {
1707        int hasdir, idx = 0, deftypes = 1;
1708        bool seen_dot = 1;
1709
1710        hasdir = (strpbrk(scriptname,":[</") != Nullch) ;
1711        /* The first time through, just add SEARCH_EXTS to whatever we
1712         * already have, so we can check for default file types. */
1713        while (deftypes ||
1714               (!hasdir && my_trnlnm("DCL$PATH",tokenbuf,idx++)) )
1715        {
1716            if (deftypes) {
1717                deftypes = 0;
1718                *tokenbuf = '\0';
1719            }
1720            if ((strlen(tokenbuf) + strlen(scriptname)
1721                 + MAX_EXT_LEN) >= sizeof tokenbuf)
1722                continue;       /* don't search dir with too-long name */
1723            strcat(tokenbuf, scriptname);
1724#else  /* !VMS */
1725
1726#ifdef DOSISH
1727    if (strEQ(scriptname, "-"))
1728        dosearch = 0;
1729    if (dosearch) {             /* Look in '.' first. */
1730        char *cur = scriptname;
1731#ifdef SEARCH_EXTS
1732        if ((curext = strrchr(scriptname,'.'))) /* possible current ext */
1733            while (ext[i])
1734                if (strEQ(ext[i++],curext)) {
1735                    extidx = -1;                /* already has an ext */
1736                    break;
1737                }
1738        do {
1739#endif
1740            DEBUG_p(PerlIO_printf(Perl_debug_log,
1741                                  "Looking for %s\n",cur));
1742            if (Stat(cur,&statbuf) >= 0) {
1743                dosearch = 0;
1744                scriptname = cur;
1745#ifdef SEARCH_EXTS
1746                break;
1747#endif
1748            }
1749#ifdef SEARCH_EXTS
1750            if (cur == scriptname) {
1751                len = strlen(scriptname);
1752                if (len+MAX_EXT_LEN+1 >= sizeof(tokenbuf))
1753                    break;
1754                cur = strcpy(tokenbuf, scriptname);
1755            }
1756        } while (extidx >= 0 && ext[extidx]     /* try an extension? */
1757                 && strcpy(tokenbuf+len, ext[extidx++]));
1758#endif
1759    }
1760#endif
1761
1762    if (dosearch && !strchr(scriptname, '/')
1763#ifdef DOSISH
1764                 && !strchr(scriptname, '\\')
1765#endif
1766                 && (s = getenv("PATH"))) {
1767        bool seen_dot = 0;
1768       
1769        bufend = s + strlen(s);
1770        while (s < bufend) {
1771#if defined(atarist) || defined(DOSISH)
1772            for (len = 0; *s
1773#  ifdef atarist
1774                    && *s != ','
1775#  endif
1776                    && *s != ';'; len++, s++) {
1777                if (len < sizeof tokenbuf)
1778                    tokenbuf[len] = *s;
1779            }
1780            if (len < sizeof tokenbuf)
1781                tokenbuf[len] = '\0';
1782#else  /* ! (atarist || DOSISH) */
1783            s = delimcpy(tokenbuf, tokenbuf + sizeof tokenbuf, s, bufend,
1784                        ':',
1785                        &len);
1786#endif /* ! (atarist || DOSISH) */
1787            if (s < bufend)
1788                s++;
1789            if (len + 1 + strlen(scriptname) + MAX_EXT_LEN >= sizeof tokenbuf)
1790                continue;       /* don't search dir with too-long name */
1791            if (len
1792#if defined(atarist) || defined(DOSISH)
1793                && tokenbuf[len - 1] != '/'
1794                && tokenbuf[len - 1] != '\\'
1795#endif
1796               )
1797                tokenbuf[len++] = '/';
1798            if (len == 2 && tokenbuf[0] == '.')
1799                seen_dot = 1;
1800            (void)strcpy(tokenbuf + len, scriptname);
1801#endif  /* !VMS */
1802
1803#ifdef SEARCH_EXTS
1804            len = strlen(tokenbuf);
1805            if (extidx > 0)     /* reset after previous loop */
1806                extidx = 0;
1807            do {
1808#endif
1809                DEBUG_p(PerlIO_printf(Perl_debug_log, "Looking for %s\n",tokenbuf));
1810                retval = Stat(tokenbuf,&statbuf);
1811#ifdef SEARCH_EXTS
1812            } while (  retval < 0               /* not there */
1813                    && extidx>=0 && ext[extidx] /* try an extension? */
1814                    && strcpy(tokenbuf+len, ext[extidx++])
1815                );
1816#endif
1817            if (retval < 0)
1818                continue;
1819            if (S_ISREG(statbuf.st_mode)
1820                && cando(S_IRUSR,TRUE,&statbuf)
1821#ifndef DOSISH
1822                && cando(S_IXUSR,TRUE,&statbuf)
1823#endif
1824                )
1825            {
1826                xfound = tokenbuf;              /* bingo! */
1827                break;
1828            }
1829            if (!xfailed)
1830                xfailed = savepv(tokenbuf);
1831        }
1832#ifndef DOSISH
1833        if (!xfound && !seen_dot && !xfailed && (Stat(scriptname,&statbuf) < 0))
1834#endif
1835            seen_dot = 1;                       /* Disable message. */
1836        if (!xfound)
1837            croak("Can't %s %s%s%s",
1838                  (xfailed ? "execute" : "find"),
1839                  (xfailed ? xfailed : scriptname),
1840                  (xfailed ? "" : " on PATH"),
1841                  (xfailed || seen_dot) ? "" : ", '.' not in PATH");
1842        if (xfailed)
1843            Safefree(xfailed);
1844        scriptname = xfound;
1845    }
1846
1847    if (strnEQ(scriptname, "/dev/fd/", 8) && isDIGIT(scriptname[8]) ) {
1848        char *s = scriptname + 8;
1849        fdscript = atoi(s);
1850        while (isDIGIT(*s))
1851            s++;
1852        if (*s)
1853            scriptname = s + 1;
1854    }
1855    else
1856        fdscript = -1;
1857    origfilename = savepv(e_tmpname ? "-e" : scriptname);
1858    curcop->cop_filegv = gv_fetchfile(origfilename);
1859    if (strEQ(origfilename,"-"))
1860        scriptname = "";
1861    if (fdscript >= 0) {
1862        rsfp = PerlIO_fdopen(fdscript,"r");
1863#if defined(HAS_FCNTL) && defined(F_SETFD)
1864        if (rsfp)
1865            fcntl(PerlIO_fileno(rsfp),F_SETFD,1);  /* ensure close-on-exec */
1866#endif
1867    }
1868    else if (preprocess) {
1869        char *cpp_cfg = CPPSTDIN;
1870        SV *cpp = NEWSV(0,0);
1871        SV *cmd = NEWSV(0,0);
1872
1873        if (strEQ(cpp_cfg, "cppstdin"))
1874            sv_catpvf(cpp, "%s/", BIN_EXP);
1875        sv_catpv(cpp, cpp_cfg);
1876
1877        sv_catpv(sv,"-I");
1878        sv_catpv(sv,PRIVLIB_EXP);
1879
1880#ifdef MSDOS
1881        sv_setpvf(cmd, "\
1882sed %s -e \"/^[^#]/b\" \
1883 -e \"/^#[      ]*include[      ]/b\" \
1884 -e \"/^#[      ]*define[       ]/b\" \
1885 -e \"/^#[      ]*if[   ]/b\" \
1886 -e \"/^#[      ]*ifdef[        ]/b\" \
1887 -e \"/^#[      ]*ifndef[       ]/b\" \
1888 -e \"/^#[      ]*else/b\" \
1889 -e \"/^#[      ]*elif[         ]/b\" \
1890 -e \"/^#[      ]*undef[        ]/b\" \
1891 -e \"/^#[      ]*endif/b\" \
1892 -e \"s/^#.*//\" \
1893 %s | %_ -C %_ %s",
1894          (doextract ? "-e \"1,/^#/d\n\"" : ""),
1895#else
1896        sv_setpvf(cmd, "\
1897%s %s -e '/^[^#]/b' \
1898 -e '/^#[       ]*include[      ]/b' \
1899 -e '/^#[       ]*define[       ]/b' \
1900 -e '/^#[       ]*if[   ]/b' \
1901 -e '/^#[       ]*ifdef[        ]/b' \
1902 -e '/^#[       ]*ifndef[       ]/b' \
1903 -e '/^#[       ]*else/b' \
1904 -e '/^#[       ]*elif[         ]/b' \
1905 -e '/^#[       ]*undef[        ]/b' \
1906 -e '/^#[       ]*endif/b' \
1907 -e 's/^[       ]*#.*//' \
1908 %s | %_ -C %_ %s",
1909#ifdef LOC_SED
1910          LOC_SED,
1911#else
1912          "sed",
1913#endif
1914          (doextract ? "-e '1,/^#/d\n'" : ""),
1915#endif
1916          scriptname, cpp, sv, CPPMINUS);
1917        doextract = FALSE;
1918#ifdef IAMSUID                          /* actually, this is caught earlier */
1919        if (euid != uid && !euid) {     /* if running suidperl */
1920#ifdef HAS_SETEUID
1921            (void)seteuid(uid);         /* musn't stay setuid root */
1922#else
1923#ifdef HAS_SETREUID
1924            (void)setreuid((Uid_t)-1, uid);
1925#else
1926#ifdef HAS_SETRESUID
1927            (void)setresuid((Uid_t)-1, uid, (Uid_t)-1);
1928#else
1929            setuid(uid);
1930#endif
1931#endif
1932#endif
1933            if (geteuid() != uid)
1934                croak("Can't do seteuid!\n");
1935        }
1936#endif /* IAMSUID */
1937        rsfp = my_popen(SvPVX(cmd), "r");
1938        SvREFCNT_dec(cmd);
1939        SvREFCNT_dec(cpp);
1940    }
1941    else if (!*scriptname) {
1942        forbid_setid("program input from stdin");
1943        rsfp = PerlIO_stdin();
1944    }
1945    else {
1946        rsfp = PerlIO_open(scriptname,"r");
1947#if defined(HAS_FCNTL) && defined(F_SETFD)
1948        if (rsfp)
1949            fcntl(PerlIO_fileno(rsfp),F_SETFD,1);  /* ensure close-on-exec */
1950#endif
1951    }
1952    if (e_tmpname) {
1953        e_fp = rsfp;
1954    }
1955    if (!rsfp) {
1956#ifdef DOSUID
1957#ifndef IAMSUID         /* in case script is not readable before setuid */
1958        if (euid && Stat(SvPVX(GvSV(curcop->cop_filegv)),&statbuf) >= 0 &&
1959          statbuf.st_mode & (S_ISUID|S_ISGID)) {
1960            /* try again */
1961            execv(form("%s/sperl%s", BIN_EXP, patchlevel), origargv);
1962            croak("Can't do setuid\n");
1963        }
1964#endif
1965#endif
1966        croak("Can't open perl script \"%s\": %s\n",
1967          SvPVX(GvSV(curcop->cop_filegv)), Strerror(errno));
1968    }
1969}
1970
1971static void
1972validate_suid(validarg, scriptname)
1973char *validarg;
1974char *scriptname;
1975{
1976    int which;
1977
1978    /* do we need to emulate setuid on scripts? */
1979
1980    /* This code is for those BSD systems that have setuid #! scripts disabled
1981     * in the kernel because of a security problem.  Merely defining DOSUID
1982     * in perl will not fix that problem, but if you have disabled setuid
1983     * scripts in the kernel, this will attempt to emulate setuid and setgid
1984     * on scripts that have those now-otherwise-useless bits set.  The setuid
1985     * root version must be called suidperl or sperlN.NNN.  If regular perl
1986     * discovers that it has opened a setuid script, it calls suidperl with
1987     * the same argv that it had.  If suidperl finds that the script it has
1988     * just opened is NOT setuid root, it sets the effective uid back to the
1989     * uid.  We don't just make perl setuid root because that loses the
1990     * effective uid we had before invoking perl, if it was different from the
1991     * uid.
1992     *
1993     * DOSUID must be defined in both perl and suidperl, and IAMSUID must
1994     * be defined in suidperl only.  suidperl must be setuid root.  The
1995     * Configure script will set this up for you if you want it.
1996     */
1997
1998#ifdef DOSUID
1999    char *s, *s2;
2000
2001    if (Fstat(PerlIO_fileno(rsfp),&statbuf) < 0)        /* normal stat is insecure */
2002        croak("Can't stat script \"%s\"",origfilename);
2003    if (fdscript < 0 && statbuf.st_mode & (S_ISUID|S_ISGID)) {
2004        I32 len;
2005
2006#ifdef IAMSUID
2007#ifndef HAS_SETREUID
2008        /* On this access check to make sure the directories are readable,
2009         * there is actually a small window that the user could use to make
2010         * filename point to an accessible directory.  So there is a faint
2011         * chance that someone could execute a setuid script down in a
2012         * non-accessible directory.  I don't know what to do about that.
2013         * But I don't think it's too important.  The manual lies when
2014         * it says access() is useful in setuid programs.
2015         */
2016        if (access(SvPVX(GvSV(curcop->cop_filegv)),1))  /*double check*/
2017            croak("Permission denied");
2018#else
2019        /* If we can swap euid and uid, then we can determine access rights
2020         * with a simple stat of the file, and then compare device and
2021         * inode to make sure we did stat() on the same file we opened.
2022         * Then we just have to make sure he or she can execute it.
2023         */
2024        {
2025            struct stat tmpstatbuf;
2026
2027            if (
2028#ifdef HAS_SETREUID
2029                setreuid(euid,uid) < 0
2030#else
2031# if HAS_SETRESUID
2032                setresuid(euid,uid,(Uid_t)-1) < 0
2033# endif
2034#endif
2035                || getuid() != euid || geteuid() != uid)
2036                croak("Can't swap uid and euid");       /* really paranoid */
2037            if (Stat(SvPVX(GvSV(curcop->cop_filegv)),&tmpstatbuf) < 0)
2038                croak("Permission denied");     /* testing full pathname here */
2039            if (tmpstatbuf.st_dev != statbuf.st_dev ||
2040                tmpstatbuf.st_ino != statbuf.st_ino) {
2041                (void)PerlIO_close(rsfp);
2042                if (rsfp = my_popen("/bin/mail root","w")) {    /* heh, heh */
2043                    PerlIO_printf(rsfp,
2044"User %ld tried to run dev %ld ino %ld in place of dev %ld ino %ld!\n\
2045(Filename of set-id script was %s, uid %ld gid %ld.)\n\nSincerely,\nperl\n",
2046                        (long)uid,(long)tmpstatbuf.st_dev, (long)tmpstatbuf.st_ino,
2047                        (long)statbuf.st_dev, (long)statbuf.st_ino,
2048                        SvPVX(GvSV(curcop->cop_filegv)),
2049                        (long)statbuf.st_uid, (long)statbuf.st_gid);
2050                    (void)my_pclose(rsfp);
2051                }
2052                croak("Permission denied\n");
2053            }
2054            if (
2055#ifdef HAS_SETREUID
2056              setreuid(uid,euid) < 0
2057#else
2058# if defined(HAS_SETRESUID)
2059              setresuid(uid,euid,(Uid_t)-1) < 0
2060# endif
2061#endif
2062              || getuid() != uid || geteuid() != euid)
2063                croak("Can't reswap uid and euid");
2064            if (!cando(S_IXUSR,FALSE,&statbuf))         /* can real uid exec? */
2065                croak("Permission denied\n");
2066        }
2067#endif /* HAS_SETREUID */
2068#endif /* IAMSUID */
2069
2070        if (!S_ISREG(statbuf.st_mode))
2071            croak("Permission denied");
2072        if (statbuf.st_mode & S_IWOTH)
2073            croak("Setuid/gid script is writable by world");
2074        doswitches = FALSE;             /* -s is insecure in suid */
2075        curcop->cop_line++;
2076        if (sv_gets(linestr, rsfp, 0) == Nullch ||
2077          strnNE(SvPV(linestr,na),"#!",2) )     /* required even on Sys V */
2078            croak("No #! line");
2079        s = SvPV(linestr,na)+2;
2080        if (*s == ' ') s++;
2081        while (!isSPACE(*s)) s++;
2082        for (s2 = s;  (s2 > SvPV(linestr,na)+2 &&
2083                       (isDIGIT(s2[-1]) || strchr("._-", s2[-1])));  s2--) ;
2084        if (strnNE(s2-4,"perl",4) && strnNE(s-9,"perl",4))  /* sanity check */
2085            croak("Not a perl script");
2086        while (*s == ' ' || *s == '\t') s++;
2087        /*
2088         * #! arg must be what we saw above.  They can invoke it by
2089         * mentioning suidperl explicitly, but they may not add any strange
2090         * arguments beyond what #! says if they do invoke suidperl that way.
2091         */
2092        len = strlen(validarg);
2093        if (strEQ(validarg," PHOOEY ") ||
2094            strnNE(s,validarg,len) || !isSPACE(s[len]))
2095            croak("Args must match #! line");
2096
2097#ifndef IAMSUID
2098        if (euid != uid && (statbuf.st_mode & S_ISUID) &&
2099            euid == statbuf.st_uid)
2100            if (!do_undump)
2101                croak("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
2102FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
2103#endif /* IAMSUID */
2104
2105        if (euid) {     /* oops, we're not the setuid root perl */
2106            (void)PerlIO_close(rsfp);
2107#ifndef IAMSUID
2108            /* try again */
2109            execv(form("%s/sperl%s", BIN_EXP, patchlevel), origargv);
2110#endif
2111            croak("Can't do setuid\n");
2112        }
2113
2114        if (statbuf.st_mode & S_ISGID && statbuf.st_gid != egid) {
2115#ifdef HAS_SETEGID
2116            (void)setegid(statbuf.st_gid);
2117#else
2118#ifdef HAS_SETREGID
2119           (void)setregid((Gid_t)-1,statbuf.st_gid);
2120#else
2121#ifdef HAS_SETRESGID
2122           (void)setresgid((Gid_t)-1,statbuf.st_gid,(Gid_t)-1);
2123#else
2124            setgid(statbuf.st_gid);
2125#endif
2126#endif
2127#endif
2128            if (getegid() != statbuf.st_gid)
2129                croak("Can't do setegid!\n");
2130        }
2131        if (statbuf.st_mode & S_ISUID) {
2132            if (statbuf.st_uid != euid)
2133#ifdef HAS_SETEUID
2134                (void)seteuid(statbuf.st_uid);  /* all that for this */
2135#else
2136#ifdef HAS_SETREUID
2137                (void)setreuid((Uid_t)-1,statbuf.st_uid);
2138#else
2139#ifdef HAS_SETRESUID
2140                (void)setresuid((Uid_t)-1,statbuf.st_uid,(Uid_t)-1);
2141#else
2142                setuid(statbuf.st_uid);
2143#endif
2144#endif
2145#endif
2146            if (geteuid() != statbuf.st_uid)
2147                croak("Can't do seteuid!\n");
2148        }
2149        else if (uid) {                 /* oops, mustn't run as root */
2150#ifdef HAS_SETEUID
2151          (void)seteuid((Uid_t)uid);
2152#else
2153#ifdef HAS_SETREUID
2154          (void)setreuid((Uid_t)-1,(Uid_t)uid);
2155#else
2156#ifdef HAS_SETRESUID
2157          (void)setresuid((Uid_t)-1,(Uid_t)uid,(Uid_t)-1);
2158#else
2159          setuid((Uid_t)uid);
2160#endif
2161#endif
2162#endif
2163            if (geteuid() != uid)
2164                croak("Can't do seteuid!\n");
2165        }
2166        init_ids();
2167        if (!cando(S_IXUSR,TRUE,&statbuf))
2168            croak("Permission denied\n");       /* they can't do this */
2169    }
2170#ifdef IAMSUID
2171    else if (preprocess)
2172        croak("-P not allowed for setuid/setgid script\n");
2173    else if (fdscript >= 0)
2174        croak("fd script not allowed in suidperl\n");
2175    else
2176        croak("Script is not setuid/setgid in suidperl\n");
2177
2178    /* We absolutely must clear out any saved ids here, so we */
2179    /* exec the real perl, substituting fd script for scriptname. */
2180    /* (We pass script name as "subdir" of fd, which perl will grok.) */
2181    PerlIO_rewind(rsfp);
2182    lseek(PerlIO_fileno(rsfp),(Off_t)0,0);  /* just in case rewind didn't */
2183    for (which = 1; origargv[which] && origargv[which] != scriptname; which++) ;
2184    if (!origargv[which])
2185        croak("Permission denied");
2186    origargv[which] = savepv(form("/dev/fd/%d/%s",
2187                                  PerlIO_fileno(rsfp), origargv[which]));
2188#if defined(HAS_FCNTL) && defined(F_SETFD)
2189    fcntl(PerlIO_fileno(rsfp),F_SETFD,0);       /* ensure no close-on-exec */
2190#endif
2191    execv(form("%s/perl%s", BIN_EXP, patchlevel), origargv);    /* try again */
2192    croak("Can't do setuid\n");
2193#endif /* IAMSUID */
2194#else /* !DOSUID */
2195    if (euid != uid || egid != gid) {   /* (suidperl doesn't exist, in fact) */
2196#ifndef SETUID_SCRIPTS_ARE_SECURE_NOW
2197        Fstat(PerlIO_fileno(rsfp),&statbuf);    /* may be either wrapped or real suid */
2198        if ((euid != uid && euid == statbuf.st_uid && statbuf.st_mode & S_ISUID)
2199            ||
2200            (egid != gid && egid == statbuf.st_gid && statbuf.st_mode & S_ISGID)
2201           )
2202            if (!do_undump)
2203                croak("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
2204FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
2205#endif /* SETUID_SCRIPTS_ARE_SECURE_NOW */
2206        /* not set-id, must be wrapped */
2207    }
2208#endif /* DOSUID */
2209}
2210
2211static void
2212find_beginning()
2213{
2214    register char *s, *s2;
2215
2216    /* skip forward in input to the real script? */
2217
2218    forbid_setid("-x");
2219    while (doextract) {
2220        if ((s = sv_gets(linestr, rsfp, 0)) == Nullch)
2221            croak("No Perl script found in input\n");
2222        if (*s == '#' && s[1] == '!' && (s = instr(s,"perl"))) {
2223            PerlIO_ungetc(rsfp, '\n');          /* to keep line count right */
2224            doextract = FALSE;
2225            while (*s && !(isSPACE (*s) || *s == '#')) s++;
2226            s2 = s;
2227            while (*s == ' ' || *s == '\t') s++;
2228            if (*s++ == '-') {
2229                while (isDIGIT(s2[-1]) || strchr("-._", s2[-1])) s2--;
2230                if (strnEQ(s2-4,"perl",4))
2231                    /*SUPPRESS 530*/
2232                    while (s = moreswitches(s)) ;
2233            }
2234            if (cddir && chdir(cddir) < 0)
2235                croak("Can't chdir to %s",cddir);
2236        }
2237    }
2238}
2239
2240static void
2241init_ids()
2242{
2243    uid = (int)getuid();
2244    euid = (int)geteuid();
2245    gid = (int)getgid();
2246    egid = (int)getegid();
2247#ifdef VMS
2248    uid |= gid << 16;
2249    euid |= egid << 16;
2250#endif
2251    tainting |= (uid && (euid != uid || egid != gid));
2252}
2253
2254static void
2255forbid_setid(s)
2256char *s;
2257{
2258    if (euid != uid)
2259        croak("No %s allowed while running setuid", s);
2260    if (egid != gid)
2261        croak("No %s allowed while running setgid", s);
2262}
2263
2264static void
2265init_debugger()
2266{
2267    curstash = debstash;
2268    dbargs = GvAV(gv_AVadd((gv_fetchpv("args", GV_ADDMULTI, SVt_PVAV))));
2269    AvREAL_off(dbargs);
2270    DBgv = gv_fetchpv("DB", GV_ADDMULTI, SVt_PVGV);
2271    DBline = gv_fetchpv("dbline", GV_ADDMULTI, SVt_PVAV);
2272    DBsub = gv_HVadd(gv_fetchpv("sub", GV_ADDMULTI, SVt_PVHV));
2273    DBsingle = GvSV((gv_fetchpv("single", GV_ADDMULTI, SVt_PV)));
2274    sv_setiv(DBsingle, 0);
2275    DBtrace = GvSV((gv_fetchpv("trace", GV_ADDMULTI, SVt_PV)));
2276    sv_setiv(DBtrace, 0);
2277    DBsignal = GvSV((gv_fetchpv("signal", GV_ADDMULTI, SVt_PV)));
2278    sv_setiv(DBsignal, 0);
2279    curstash = defstash;
2280}
2281
2282static void
2283init_stacks()
2284{
2285    curstack = newAV();
2286    mainstack = curstack;               /* remember in case we switch stacks */
2287    AvREAL_off(curstack);               /* not a real array */
2288    av_extend(curstack,127);
2289
2290    stack_base = AvARRAY(curstack);
2291    stack_sp = stack_base;
2292    stack_max = stack_base + 127;
2293
2294    cxstack_max = 8192 / sizeof(CONTEXT) - 2;   /* Use most of 8K. */
2295    New(50,cxstack,cxstack_max + 1,CONTEXT);
2296    cxstack_ix  = -1;
2297
2298    New(50,tmps_stack,128,SV*);
2299    tmps_ix = -1;
2300    tmps_max = 128;
2301
2302    DEBUG( {
2303        New(51,debname,128,char);
2304        New(52,debdelim,128,char);
2305    } )
2306
2307    /*
2308     * The following stacks almost certainly should be per-interpreter,
2309     * but for now they're not.  XXX
2310     */
2311
2312    if (markstack) {
2313        markstack_ptr = markstack;
2314    } else {
2315        New(54,markstack,64,I32);
2316        markstack_ptr = markstack;
2317        markstack_max = markstack + 64;
2318    }
2319
2320    if (scopestack) {
2321        scopestack_ix = 0;
2322    } else {
2323        New(54,scopestack,32,I32);
2324        scopestack_ix = 0;
2325        scopestack_max = 32;
2326    }
2327
2328    if (savestack) {
2329        savestack_ix = 0;
2330    } else {
2331        New(54,savestack,128,ANY);
2332        savestack_ix = 0;
2333        savestack_max = 128;
2334    }
2335
2336    if (retstack) {
2337        retstack_ix = 0;
2338    } else {
2339        New(54,retstack,16,OP*);
2340        retstack_ix = 0;
2341        retstack_max = 16;
2342    }
2343}
2344
2345static void
2346nuke_stacks()
2347{
2348    Safefree(cxstack);
2349    Safefree(tmps_stack);
2350    DEBUG( {
2351        Safefree(debname);
2352        Safefree(debdelim);
2353    } )
2354}
2355
2356static PerlIO *tmpfp;  /* moved outside init_lexer() because of UNICOS bug */
2357
2358static void
2359init_lexer()
2360{
2361    tmpfp = rsfp;
2362    rsfp = Nullfp;
2363    lex_start(linestr);
2364    rsfp = tmpfp;
2365    subname = newSVpv("main",4);
2366}
2367
2368static void
2369init_predump_symbols()
2370{
2371    GV *tmpgv;
2372    GV *othergv;
2373
2374    sv_setpvn(GvSV(gv_fetchpv("\"", TRUE, SVt_PV)), " ", 1);
2375
2376    stdingv = gv_fetchpv("STDIN",TRUE, SVt_PVIO);
2377    GvMULTI_on(stdingv);
2378    IoIFP(GvIOp(stdingv)) = PerlIO_stdin();
2379    tmpgv = gv_fetchpv("stdin",TRUE, SVt_PV);
2380    GvMULTI_on(tmpgv);
2381    GvIOp(tmpgv) = (IO*)SvREFCNT_inc(GvIOp(stdingv));
2382
2383    tmpgv = gv_fetchpv("STDOUT",TRUE, SVt_PVIO);
2384    GvMULTI_on(tmpgv);
2385    IoOFP(GvIOp(tmpgv)) = IoIFP(GvIOp(tmpgv)) = PerlIO_stdout();
2386    setdefout(tmpgv);
2387    tmpgv = gv_fetchpv("stdout",TRUE, SVt_PV);
2388    GvMULTI_on(tmpgv);
2389    GvIOp(tmpgv) = (IO*)SvREFCNT_inc(GvIOp(defoutgv));
2390
2391    othergv = gv_fetchpv("STDERR",TRUE, SVt_PVIO);
2392    GvMULTI_on(othergv);
2393    IoOFP(GvIOp(othergv)) = IoIFP(GvIOp(othergv)) = PerlIO_stderr();
2394    tmpgv = gv_fetchpv("stderr",TRUE, SVt_PV);
2395    GvMULTI_on(tmpgv);
2396    GvIOp(tmpgv) = (IO*)SvREFCNT_inc(GvIOp(othergv));
2397
2398    statname = NEWSV(66,0);             /* last filename we did stat on */
2399
2400    if (!osname)
2401        osname = savepv(OSNAME);
2402}
2403
2404static void
2405init_postdump_symbols(argc,argv,env)
2406register int argc;
2407register char **argv;
2408register char **env;
2409{
2410    char *s;
2411    SV *sv;
2412    GV* tmpgv;
2413
2414    argc--,argv++;      /* skip name of script */
2415    if (doswitches) {
2416        for (; argc > 0 && **argv == '-'; argc--,argv++) {
2417            if (!argv[0][1])
2418                break;
2419            if (argv[0][1] == '-') {
2420                argc--,argv++;
2421                break;
2422            }
2423            if (s = strchr(argv[0], '=')) {
2424                *s++ = '\0';
2425                sv_setpv(GvSV(gv_fetchpv(argv[0]+1,TRUE, SVt_PV)),s);
2426            }
2427            else
2428                sv_setiv(GvSV(gv_fetchpv(argv[0]+1,TRUE, SVt_PV)),1);
2429        }
2430    }
2431    toptarget = NEWSV(0,0);
2432    sv_upgrade(toptarget, SVt_PVFM);
2433    sv_setpvn(toptarget, "", 0);
2434    bodytarget = NEWSV(0,0);
2435    sv_upgrade(bodytarget, SVt_PVFM);
2436    sv_setpvn(bodytarget, "", 0);
2437    formtarget = bodytarget;
2438
2439    TAINT;
2440    if (tmpgv = gv_fetchpv("0",TRUE, SVt_PV)) {
2441        sv_setpv(GvSV(tmpgv),origfilename);
2442        magicname("0", "0", 1);
2443    }
2444    if (tmpgv = gv_fetchpv("\030",TRUE, SVt_PV))
2445        sv_setpv(GvSV(tmpgv),origargv[0]);
2446    if (argvgv = gv_fetchpv("ARGV",TRUE, SVt_PVAV)) {
2447        GvMULTI_on(argvgv);
2448        (void)gv_AVadd(argvgv);
2449        av_clear(GvAVn(argvgv));
2450        for (; argc > 0; argc--,argv++) {
2451            av_push(GvAVn(argvgv),newSVpv(argv[0],0));
2452        }
2453    }
2454    if (envgv = gv_fetchpv("ENV",TRUE, SVt_PVHV)) {
2455        HV *hv;
2456        GvMULTI_on(envgv);
2457        hv = GvHVn(envgv);
2458        hv_magic(hv, envgv, 'E');
2459#ifndef VMS  /* VMS doesn't have environ array */
2460        /* Note that if the supplied env parameter is actually a copy
2461           of the global environ then it may now point to free'd memory
2462           if the environment has been modified since. To avoid this
2463           problem we treat env==NULL as meaning 'use the default'
2464        */
2465        if (!env)
2466            env = environ;
2467        if (env != environ)
2468            environ[0] = Nullch;
2469        for (; *env; env++) {
2470            if (!(s = strchr(*env,'=')))
2471                continue;
2472            *s++ = '\0';
2473#ifdef WIN32
2474            (void)strupr(*env);
2475#endif
2476            sv = newSVpv(s--,0);
2477            (void)hv_store(hv, *env, s - *env, sv, 0);
2478            *s = '=';
2479#if defined(__BORLANDC__) && defined(USE_WIN32_RTL_ENV)
2480            /* Sins of the RTL. See note in my_setenv(). */
2481            (void)putenv(savepv(*env));
2482#endif
2483        }
2484#endif
2485#ifdef DYNAMIC_ENV_FETCH
2486        HvNAME(hv) = savepv(ENV_HV_NAME);
2487#endif
2488    }
2489    TAINT_NOT;
2490    if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV))
2491        sv_setiv(GvSV(tmpgv), (IV)getpid());
2492}
2493
2494static void
2495init_perllib()
2496{
2497    char *s;
2498    if (!tainting) {
2499#ifndef VMS
2500        s = getenv("PERL5LIB");
2501        if (s)
2502            incpush(s, TRUE);
2503        else
2504            incpush(getenv("PERLLIB"), FALSE);
2505#else /* VMS */
2506        /* Treat PERL5?LIB as a possible search list logical name -- the
2507         * "natural" VMS idiom for a Unix path string.  We allow each
2508         * element to be a set of |-separated directories for compatibility.
2509         */
2510        char buf[256];
2511        int idx = 0;
2512        if (my_trnlnm("PERL5LIB",buf,0))
2513            do { incpush(buf,TRUE); } while (my_trnlnm("PERL5LIB",buf,++idx));
2514        else
2515            while (my_trnlnm("PERLLIB",buf,idx++)) incpush(buf,FALSE);
2516#endif /* VMS */
2517    }
2518
2519/* Use the ~-expanded versions of APPLLIB (undocumented),
2520    ARCHLIB PRIVLIB SITEARCH SITELIB and OLDARCHLIB
2521*/
2522#ifdef APPLLIB_EXP
2523    incpush(APPLLIB_EXP, FALSE);
2524#endif
2525
2526#ifdef ARCHLIB_EXP
2527    incpush(ARCHLIB_EXP, FALSE);
2528#endif
2529#ifndef PRIVLIB_EXP
2530#define PRIVLIB_EXP "/usr/local/lib/perl5:/usr/local/lib/perl"
2531#endif
2532    incpush(PRIVLIB_EXP, FALSE);
2533
2534#ifdef SITEARCH_EXP
2535    incpush(SITEARCH_EXP, FALSE);
2536#endif
2537#ifdef SITELIB_EXP
2538    incpush(SITELIB_EXP, FALSE);
2539#endif
2540#ifdef OLDARCHLIB_EXP  /* 5.00[01] compatibility */
2541    incpush(OLDARCHLIB_EXP, FALSE);
2542#endif
2543   
2544    if (!tainting)
2545        incpush(".", FALSE);
2546}
2547
2548#if defined(DOSISH)
2549#    define PERLLIB_SEP ';'
2550#else
2551#  if defined(VMS)
2552#    define PERLLIB_SEP '|'
2553#  else
2554#    define PERLLIB_SEP ':'
2555#  endif
2556#endif
2557#ifndef PERLLIB_MANGLE
2558#  define PERLLIB_MANGLE(s,n) (s)
2559#endif
2560
2561static void
2562incpush(p, addsubdirs)
2563char *p;
2564int addsubdirs;
2565{
2566    SV *subdir = Nullsv;
2567    static char *archpat_auto;
2568
2569    if (!p)
2570        return;
2571
2572    if (addsubdirs) {
2573        subdir = newSV(0);
2574        if (!archpat_auto) {
2575            STRLEN len = (sizeof(ARCHNAME) + strlen(patchlevel)
2576                          + sizeof("//auto"));
2577            New(55, archpat_auto, len, char);
2578            sprintf(archpat_auto, "/%s/%s/auto", ARCHNAME, patchlevel);
2579#ifdef VMS
2580        for (len = sizeof(ARCHNAME) + 2;
2581             archpat_auto[len] != '\0' && archpat_auto[len] != '/'; len++)
2582                if (archpat_auto[len] == '.') archpat_auto[len] = '_';
2583#endif
2584        }
2585    }
2586
2587    /* Break at all separators */
2588    while (p && *p) {
2589        SV *libdir = newSV(0);
2590        char *s;
2591
2592        /* skip any consecutive separators */
2593        while ( *p == PERLLIB_SEP ) {
2594            /* Uncomment the next line for PATH semantics */
2595            /* av_push(GvAVn(incgv), newSVpv(".", 1)); */
2596            p++;
2597        }
2598
2599        if ( (s = strchr(p, PERLLIB_SEP)) != Nullch ) {
2600            sv_setpvn(libdir, PERLLIB_MANGLE(p, (STRLEN)(s - p)),
2601                      (STRLEN)(s - p));
2602            p = s + 1;
2603        }
2604        else {
2605            sv_setpv(libdir, PERLLIB_MANGLE(p, 0));
2606            p = Nullch; /* break out */
2607        }
2608
2609        /*
2610         * BEFORE pushing libdir onto @INC we may first push version- and
2611         * archname-specific sub-directories.
2612         */
2613        if (addsubdirs) {
2614            struct stat tmpstatbuf;
2615#ifdef VMS
2616            char *unix;
2617            STRLEN len;
2618
2619            if ((unix = tounixspec_ts(SvPV(libdir,na),Nullch)) != Nullch) {
2620                len = strlen(unix);
2621                while (unix[len-1] == '/') len--;  /* Cosmetic */
2622                sv_usepvn(libdir,unix,len);
2623            }
2624            else
2625                PerlIO_printf(PerlIO_stderr(),
2626                              "Failed to unixify @INC element \"%s\"\n",
2627                              SvPV(libdir,na));
2628#endif
2629            /* .../archname/version if -d .../archname/version/auto */
2630            sv_setsv(subdir, libdir);
2631            sv_catpv(subdir, archpat_auto);
2632            if (Stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
2633                  S_ISDIR(tmpstatbuf.st_mode))
2634                av_push(GvAVn(incgv),
2635                        newSVpv(SvPVX(subdir), SvCUR(subdir) - sizeof "auto"));
2636
2637            /* .../archname if -d .../archname/auto */
2638            sv_insert(subdir, SvCUR(libdir) + sizeof(ARCHNAME),
2639                      strlen(patchlevel) + 1, "", 0);
2640            if (Stat(SvPVX(subdir), &tmpstatbuf) >= 0 &&
2641                  S_ISDIR(tmpstatbuf.st_mode))
2642                av_push(GvAVn(incgv),
2643                        newSVpv(SvPVX(subdir), SvCUR(subdir) - sizeof "auto"));
2644        }
2645
2646        /* finally push this lib directory on the end of @INC */
2647        av_push(GvAVn(incgv), libdir);
2648    }
2649
2650    SvREFCNT_dec(subdir);
2651}
2652
2653void
2654call_list(oldscope, list)
2655I32 oldscope;
2656AV* list;
2657{
2658    line_t oldline = curcop->cop_line;
2659    STRLEN len;
2660    dJMPENV;
2661    int ret;
2662
2663    while (AvFILL(list) >= 0) {
2664        CV *cv = (CV*)av_shift(list);
2665
2666        SAVEFREESV(cv);
2667
2668        JMPENV_PUSH(ret);
2669        switch (ret) {
2670        case 0: {
2671                SV* atsv = GvSV(errgv);
2672                PUSHMARK(stack_sp);
2673                perl_call_sv((SV*)cv, G_EVAL|G_DISCARD);
2674                (void)SvPV(atsv, len);
2675                if (len) {
2676                    JMPENV_POP;
2677                    curcop = &compiling;
2678                    curcop->cop_line = oldline;
2679                    if (list == beginav)
2680                        sv_catpv(atsv, "BEGIN failed--compilation aborted");
2681                    else
2682                        sv_catpv(atsv, "END failed--cleanup aborted");
2683                    while (scopestack_ix > oldscope)
2684                        LEAVE;
2685                    croak("%s", SvPVX(atsv));
2686                }
2687            }
2688            break;
2689        case 1:
2690            STATUS_ALL_FAILURE;
2691            /* FALL THROUGH */
2692        case 2:
2693            /* my_exit() was called */
2694            while (scopestack_ix > oldscope)
2695                LEAVE;
2696            FREETMPS;
2697            curstash = defstash;
2698            if (endav)
2699                call_list(oldscope, endav);
2700            JMPENV_POP;
2701            curcop = &compiling;
2702            curcop->cop_line = oldline;
2703            if (statusvalue) {
2704                if (list == beginav)
2705                    croak("BEGIN failed--compilation aborted");
2706                else
2707                    croak("END failed--cleanup aborted");
2708            }
2709            my_exit_jump();
2710            /* NOTREACHED */
2711        case 3:
2712            if (!restartop) {
2713                PerlIO_printf(PerlIO_stderr(), "panic: restartop\n");
2714                FREETMPS;
2715                break;
2716            }
2717            JMPENV_POP;
2718            curcop = &compiling;
2719            curcop->cop_line = oldline;
2720            JMPENV_JUMP(3);
2721        }
2722        JMPENV_POP;
2723    }
2724}
2725
2726void
2727my_exit(status)
2728U32 status;
2729{
2730    switch (status) {
2731    case 0:
2732        STATUS_ALL_SUCCESS;
2733        break;
2734    case 1:
2735        STATUS_ALL_FAILURE;
2736        break;
2737    default:
2738        STATUS_NATIVE_SET(status);
2739        break;
2740    }
2741    my_exit_jump();
2742}
2743
2744void
2745my_failure_exit()
2746{
2747#ifdef VMS
2748    if (vaxc$errno & 1) {
2749        if (STATUS_NATIVE & 1)          /* fortuitiously includes "-1" */
2750            STATUS_NATIVE_SET(44);
2751    }
2752    else {
2753        if (!vaxc$errno && errno)       /* unlikely */
2754            STATUS_NATIVE_SET(44);
2755        else
2756            STATUS_NATIVE_SET(vaxc$errno);
2757    }
2758#else
2759    if (errno & 255)
2760        STATUS_POSIX_SET(errno);
2761    else if (STATUS_POSIX == 0)
2762        STATUS_POSIX_SET(255);
2763#endif
2764    my_exit_jump();
2765}
2766
2767static void
2768my_exit_jump()
2769{
2770    register CONTEXT *cx;
2771    I32 gimme;
2772    SV **newsp;
2773
2774    if (e_tmpname) {
2775        if (e_fp) {
2776            PerlIO_close(e_fp);
2777            e_fp = Nullfp;
2778        }
2779        (void)UNLINK(e_tmpname);
2780        Safefree(e_tmpname);
2781        e_tmpname = Nullch;
2782    }
2783
2784    if (cxstack_ix >= 0) {
2785        if (cxstack_ix > 0)
2786            dounwind(0);
2787        POPBLOCK(cx,curpm);
2788        LEAVE;
2789    }
2790
2791    JMPENV_JUMP(2);
2792}
Note: See TracBrowser for help on using the repository browser.