2 * Copyright (c) 1991, 1992, 1993, 1994 Larry Wall
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Artistic License, as specified in the README file.
8 * Revision 4.1 92/08/07 18:25:50 lwall
10 * Revision 4.0.1.7 92/06/08 14:50:39 lwall
11 * patch20: PERLLIB now supports multiple directories
12 * patch20: running taintperl explicitly now does checks even if $< == $>
13 * patch20: -e 'cmd' no longer fails silently if /tmp runs out of space
14 * patch20: perl -P now uses location of sed determined by Configure
15 * patch20: form feed for formats is now specifiable via $^L
16 * patch20: paragraph mode now skips extra newlines automatically
17 * patch20: oldeval "1 #comment" didn't work
18 * patch20: couldn't require . files
19 * patch20: semantic compilation errors didn't abort execution
21 * Revision 4.0.1.6 91/11/11 16:38:45 lwall
22 * patch19: default arg for shift was wrong after first subroutine definition
23 * patch19: op/regexp.t failed from missing arg to bcmp()
25 * Revision 4.0.1.5 91/11/05 18:03:32 lwall
26 * patch11: random cleanup
27 * patch11: $0 was being truncated at times
28 * patch11: cppstdin now installed outside of source directory
29 * patch11: -P didn't allow use of #elif or #undef
30 * patch11: prepared for ctype implementations that don't define isascii()
31 * patch11: added oldeval {}
32 * patch11: oldeval confused by string containing null
34 * Revision 4.0.1.4 91/06/10 01:23:07 lwall
35 * patch10: perl -v printed incorrect copyright notice
37 * Revision 4.0.1.3 91/06/07 11:40:18 lwall
38 * patch4: changed old $^P to $^X
40 * Revision 4.0.1.2 91/06/07 11:26:16 lwall
41 * patch4: new copyright notice
42 * patch4: added $^P variable to control calling of perldb routines
43 * patch4: added $^F variable to specify maximum system fd, default 2
44 * patch4: debugger lost track of lines in oldeval
46 * Revision 4.0.1.1 91/04/11 17:49:05 lwall
47 * patch1: fixed undefined environ problem
49 * Revision 4.0 91/03/20 01:37:44 lwall
59 #include "patchlevel.h"
61 char rcsid[] = "$RCSfile: perl.c,v $$Revision: 5.0 $$Date: 92/08/07 18:25:50 $\nPatch level: ###\n";
69 #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
75 static void incpush();
76 static void validate_suid();
77 static void find_beginning();
78 static void init_main_stash();
79 static void open_script();
80 static void init_debugger();
81 static void init_stacks();
82 static void init_lexer();
83 static void init_predump_symbols();
84 static void init_postdump_symbols();
85 static void init_perllib();
90 PerlInterpreter *sv_interp;
94 /* Zero(&junk, 1, PerlInterpreter); */
95 New(53, sv_interp, 1, PerlInterpreter);
100 perl_construct( sv_interp )
101 register PerlInterpreter *sv_interp;
103 if (!(curinterp = sv_interp))
107 Zero(sv_interp, 1, PerlInterpreter);
110 /* Init the real globals? */
112 linestr = NEWSV(65,80);
113 sv_upgrade(linestr,SVt_PVIV);
115 SvREADONLY_on(&sv_undef);
119 SvREADONLY_on(&sv_no);
121 sv_setpv(&sv_yes,Yes);
123 SvREADONLY_on(&sv_yes);
127 * There is no way we can refer to them from Perl so close them to save
128 * space. The other alternative would be to provide STDAUX and STDPRN
131 (void)fclose(stdaux);
132 (void)fclose(stdprn);
157 euid = (int)geteuid();
159 egid = (int)getegid();
160 tainting = (euid != uid || egid != gid);
161 sprintf(patchlevel,"%3.3s%2.2d", strchr(rcsid,'5'), PATCHLEVEL);
163 (void)sprintf(strchr(rcsid,'#'), "%d\n", PATCHLEVEL);
165 fdpid = newAV(); /* for remembering popen pids by fd */
166 pidstatus = newHV();/* for remembering status of dead pids */
173 perl_destruct(sv_interp)
174 register PerlInterpreter *sv_interp;
178 if (!(curinterp = sv_interp))
184 /* The exit() function may do everything that needs doing. */
189 /* Not so lucky. We must account for everything. First the syntax tree. */
191 curpad = AvARRAY(comppad);
197 * Try to destruct global references. We do this first so that the
198 * destructors and destructees still exist. This code currently
199 * will break simple reference loops but may fail on more complicated
200 * ones. If so, the code below will clean up, but any destructors
201 * may fail to find what they're looking for.
206 /* Delete self-reference from main symbol table */
207 GvHV(gv_fetchpv("::_main",TRUE)) = 0;
208 --SvREFCNT(defstash);
210 /* Try to destruct main symbol table. May fail on reference loops. */
211 SvREFCNT_dec(defstash);
215 if (scopestack_ix != 0)
216 warn("Unbalanced scopes: %d more ENTERs than LEAVEs\n", scopestack_ix);
217 if (savestack_ix != 0)
218 warn("Unbalanced saves: %d more saves than restores\n", savestack_ix);
219 if (tmps_floor != -1)
220 warn("Unbalanced tmps: %d more allocs than frees\n", tmps_floor + 1);
221 if (cxstack_ix != -1)
222 warn("Unbalanced context: %d more PUSHes than POPs\n", cxstack_ix + 1);
225 /* Now absolutely destruct everything, somehow or other, loops or no. */
226 #ifdef APPARENTLY_UNNECESSARY
231 while (sv_count != 0 && sv_count != last_sv_count) {
232 last_sv_count = sv_count;
236 warn("Scalars leaked: %d\n", sv_count);
241 PerlInterpreter *sv_interp;
243 if (!(curinterp = sv_interp))
249 perl_parse(sv_interp, argc, argv, env)
250 PerlInterpreter *sv_interp;
252 register char **argv;
259 bool dosearch = FALSE;
262 #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
265 croak("suidperl is no longer needed since the kernel can now execute\n\
266 setuid perl scripts securely.\n");
270 if (!(curinterp = sv_interp))
279 origenviron = environ;
281 switch (setjmp(top_env)) {
288 return(statusvalue); /* my_exit() was called */
290 fprintf(stderr, "panic: top_env\n");
296 /* Come here if running an undumped a.out. */
298 origfilename = savestr(argv[0]);
300 cxstack_ix = -1; /* start label stack again */
301 init_postdump_symbols(argc,argv,env);
305 sv_setpvn(linestr,"",0);
306 sv = newSVpv("",0); /* first used for -I flags */
309 for (argc--,argv++; argc > 0; argc--,argv++) {
310 if (argv[0][0] != '-' || !argv[0][1])
314 validarg = " PHOOEY ";
336 if (s = moreswitches(s))
341 if (euid != uid || egid != gid)
342 croak("No -e allowed in setuid scripts");
344 e_tmpname = savestr(TMPPATH);
345 (void)mktemp(e_tmpname);
347 croak("Can't mktemp()");
348 e_fp = fopen(e_tmpname,"w");
350 croak("Cannot open temporary file");
356 (void)putc('\n', e_fp);
364 (void)av_push(GvAVn(incgv),newSVpv(s,0));
367 (void)av_push(GvAVn(incgv),newSVpv(argv[1],0));
368 sv_catpv(sv,argv[1]);
395 croak("Unrecognized switch: -%s",s);
399 scriptname = argv[0];
401 if (fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
402 croak("Can't write to temp file for -e: %s", strerror(errno));
404 scriptname = e_tmpname;
406 else if (scriptname == Nullch) {
408 if ( isatty(fileno(stdin)) )
416 open_script(scriptname,dosearch,sv);
418 validate_suid(validarg);
428 av_push(comppad, Nullsv);
429 curpad = AvARRAY(comppad);
431 comppad_name = padname;
432 comppad_name_fill = 0;
433 min_intro_pending = 0;
436 perl_init_ext(); /* in case linked C routines want magical variables */
438 init_predump_symbols();
440 init_postdump_symbols(argc,argv,env);
444 /* now parse the script */
447 if (yyparse() || error_count) {
449 croak("%s had compilation errors.\n", origfilename);
451 croak("Execution of %s aborted due to compilation errors.\n",
455 curcop->cop_line = 0;
460 (void)UNLINK(e_tmpname);
463 /* now that script is parsed, we can modify record separator */
468 rspara = (nrslen == 2);
469 sv_setpvn(GvSV(gv_fetchpv("/", TRUE)), rs, rslen);
482 PerlInterpreter *sv_interp;
484 if (!(curinterp = sv_interp))
486 switch (setjmp(top_env)) {
488 cxstack_ix = -1; /* start context stack again */
495 return(statusvalue); /* my_exit() was called */
498 fprintf(stderr, "panic: restartop\n");
502 if (stack != mainstack) {
504 SWITCHSTACK(stack, mainstack);
511 DEBUG(fprintf(stderr,"\nEXECUTING...\n\n"));
514 fprintf(stderr,"%s syntax OK\n", origfilename);
526 else if (main_start) {
538 statusvalue = (unsigned short)(status & 0xffff);
542 /* Be sure to refetch the stack pointer after calling these routines. */
545 perl_callargv(subname, sp, gimme, argv)
547 register I32 sp; /* current stack pointer */
548 I32 gimme; /* TRUE if called in list context */
549 register char **argv; /* null terminated arg list, NULL for no arglist */
551 register I32 items = 0;
552 I32 hasargs = (argv != 0);
554 av_store(stack, ++sp, Nullsv); /* reserve spot for sub reference */
557 av_store(stack, ++sp, sv_2mortal(newSVpv(*argv,0)));
562 return perl_callpv(subname, sp, gimme, hasargs, items);
566 perl_callpv(subname, sp, gimme, hasargs, numargs)
568 I32 sp; /* stack pointer after args are pushed */
569 I32 gimme; /* TRUE if called in list context */
570 I32 hasargs; /* whether to create a @_ array for routine */
571 I32 numargs; /* how many args are pushed on the stack */
573 return perl_callsv((SV*)gv_fetchpv(subname, TRUE),
574 sp, gimme, hasargs, numargs);
577 /* May be called with any of a CV, a GV, or an SV containing the name. */
579 perl_callsv(sv, sp, gimme, hasargs, numargs)
581 I32 sp; /* stack pointer after args are pushed */
582 I32 gimme; /* TRUE if called in list context */
583 I32 hasargs; /* whether to create a @_ array for routine */
584 I32 numargs; /* how many args are pushed on the stack */
586 BINOP myop; /* fake syntax tree node */
591 stack_base = AvARRAY(stack);
592 stack_sp = stack_base + sp - numargs - 1;
595 pp_pushmark(); /* doesn't look at op, actually, except to return */
600 myop.op_flags = OPf_STACKED;
601 myop.op_last = (OP*)&myop;
603 myop.op_next = Nullop;
605 if (op = pp_entersubr())
609 return stack_sp - stack_base;
613 magicname(sym,name,namlen)
620 if (gv = gv_fetchpv(sym,TRUE))
621 sv_magic(GvSV(gv), (SV*)gv, 0, name, namlen);
625 #define PERLLIB_SEP ';'
627 #define PERLLIB_SEP ':'
639 /* Break at all separators */
641 /* First, skip any consecutive separators */
642 while ( *p == PERLLIB_SEP ) {
643 /* Uncomment the next line for PATH semantics */
644 /* (void)av_push(GvAVn(incgv), newSVpv(".", 1)); */
647 if ( (s = strchr(p, PERLLIB_SEP)) != Nullch ) {
648 (void)av_push(GvAVn(incgv), newSVpv(p, (I32)(s - p)));
651 (void)av_push(GvAVn(incgv), newSVpv(p, 0));
657 /* This routine handles any switches that can be given during run */
667 nrschar = scan_oct(s, 4, &numlen);
668 nrs = nsavestr("\n",1);
670 if (nrschar > 0377) {
674 else if (!nrschar && numlen >= 2) {
697 static char debopts[] = "psltocPmfrxuLHXD";
700 for (s++; *s && (d = strchr(debopts,*s)); s++)
701 debug |= 1 << (d - debopts);
705 for (s++; isDIGIT(*s); s++) ;
709 warn("Recompile perl with -DDEBUGGING to use -D switch\n");
710 for (s++; isDIGIT(*s); s++) ;
717 inplace = savestr(s+1);
719 for (s = inplace; *s && !isSPACE(*s); s++) ;
725 (void)av_push(GvAVn(incgv),newSVpv(s,0));
728 croak("No space allowed after -I");
736 *ors = scan_oct(s, 3 + (*s == '0'), &numlen);
740 ors = nsavestr(nrs,nrslen);
770 fputs("\nThis is perl, version 5.0, Alpha 6 (unsupported)\n\n",stdout);
772 fputs("\nCopyright (c) 1989, 1990, 1991, 1992, 1993, 1994 Larry Wall\n",stdout);
774 fputs("MS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n",
777 fputs("OS/2 port Copyright (c) 1990, 1991, Raymond Chen, Kai Uwe Rommel\n",
782 fputs("atariST series port, ++jrb bammi@cadence.com\n", stdout);
785 Perl may be copied only under the terms of either the Artistic License or the\n\
786 GNU General Public License, which may be found in the Perl 5.0 source kit.\n",stdout);
796 if (s[1] == '-') /* Additional switches on #! line. */
804 croak("Switch meaningless after -x: -%s",s);
809 /* compliments of Tom Christiansen */
811 /* unexec() can be found in the Gnu emacs distribution */
820 sprintf (buf, "%s.perldump", origfilename);
821 sprintf (tokenbuf, "%s/perl", BIN);
823 status = unexec(buf, tokenbuf, &etext, sbrk(0), 0);
825 fprintf(stderr, "unexec of %s into %s failed!\n", tokenbuf, buf);
828 ABORT(); /* for use with undump */
836 curstash = defstash = newHV();
837 curstname = newSVpv("main",4);
838 GvHV(gv = gv_fetchpv("_main",TRUE)) = (HV*)SvREFCNT_inc(defstash);
840 HvNAME(defstash) = "main";
841 incgv = gv_HVadd(gv_AVadd(gv_fetchpv("INC",TRUE)));
843 defgv = gv_fetchpv("_",TRUE);
845 compiling.cop_stash = defstash;
849 open_script(scriptname,dosearch,sv)
854 char *xfound = Nullch;
855 char *xfailed = Nullch;
859 if (dosearch && !strchr(scriptname, '/') && (s = getenv("PATH"))) {
861 bufend = s + strlen(s);
864 s = cpytill(tokenbuf,s,bufend,':',&len);
867 for (len = 0; *s && *s != ',' && *s != ';'; tokenbuf[len++] = *s++);
868 tokenbuf[len] = '\0';
870 for (len = 0; *s && *s != ';'; tokenbuf[len++] = *s++);
871 tokenbuf[len] = '\0';
877 if (len && tokenbuf[len-1] != '/')
880 if (len && ((tokenbuf[len-1] != '\\') && (tokenbuf[len-1] != '/')))
882 if (len && tokenbuf[len-1] != '\\')
885 (void)strcat(tokenbuf+len,"/");
886 (void)strcat(tokenbuf+len,scriptname);
887 DEBUG_p(fprintf(stderr,"Looking for %s\n",tokenbuf));
888 if (stat(tokenbuf,&statbuf) < 0) /* not there? */
890 if (S_ISREG(statbuf.st_mode)
891 && cando(S_IRUSR,TRUE,&statbuf) && cando(S_IXUSR,TRUE,&statbuf)) {
892 xfound = tokenbuf; /* bingo! */
896 xfailed = savestr(tokenbuf);
899 croak("Can't execute %s", xfailed ? xfailed : scriptname );
905 origfilename = savestr(e_fp ? "-e" : scriptname);
906 curcop->cop_filegv = gv_fetchfile(origfilename);
907 if (strEQ(origfilename,"-"))
910 char *cpp = CPPSTDIN;
912 if (strEQ(cpp,"cppstdin"))
913 sprintf(tokenbuf, "%s/%s", SCRIPTDIR, cpp);
915 sprintf(tokenbuf, "%s", cpp);
917 sv_catpv(sv,PRIVLIB);
919 (void)sprintf(buf, "\
920 sed %s -e \"/^[^#]/b\" \
921 -e \"/^#[ ]*include[ ]/b\" \
922 -e \"/^#[ ]*define[ ]/b\" \
923 -e \"/^#[ ]*if[ ]/b\" \
924 -e \"/^#[ ]*ifdef[ ]/b\" \
925 -e \"/^#[ ]*ifndef[ ]/b\" \
926 -e \"/^#[ ]*else/b\" \
927 -e \"/^#[ ]*elif[ ]/b\" \
928 -e \"/^#[ ]*undef[ ]/b\" \
929 -e \"/^#[ ]*endif/b\" \
932 (doextract ? "-e \"1,/^#/d\n\"" : ""),
934 (void)sprintf(buf, "\
935 %s %s -e '/^[^#]/b' \
936 -e '/^#[ ]*include[ ]/b' \
937 -e '/^#[ ]*define[ ]/b' \
938 -e '/^#[ ]*if[ ]/b' \
939 -e '/^#[ ]*ifdef[ ]/b' \
940 -e '/^#[ ]*ifndef[ ]/b' \
942 -e '/^#[ ]*elif[ ]/b' \
943 -e '/^#[ ]*undef[ ]/b' \
944 -e '/^#[ ]*endif/b' \
952 (doextract ? "-e '1,/^#/d\n'" : ""),
954 scriptname, tokenbuf, SvPV(sv, na), CPPMINUS);
955 DEBUG_P(fprintf(stderr, "%s\n", buf));
957 #ifdef IAMSUID /* actually, this is caught earlier */
958 if (euid != uid && !euid) { /* if running suidperl */
960 (void)seteuid(uid); /* musn't stay setuid root */
963 (void)setreuid(-1, uid);
968 if (geteuid() != uid)
969 croak("Can't do seteuid!\n");
972 rsfp = my_popen(buf,"r");
974 else if (!*scriptname) {
975 taint_not("program input from stdin");
979 rsfp = fopen(scriptname,"r");
980 if ((FILE*)rsfp == Nullfp) {
982 #ifndef IAMSUID /* in case script is not readable before setuid */
983 if (euid && stat(SvPVX(GvSV(curcop->cop_filegv)),&statbuf) >= 0 &&
984 statbuf.st_mode & (S_ISUID|S_ISGID)) {
985 (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
986 execv(buf, origargv); /* try again */
987 croak("Can't do setuid\n");
991 croak("Can't open perl script \"%s\": %s\n",
992 SvPVX(GvSV(curcop->cop_filegv)), strerror(errno));
997 validate_suid(validarg)
1001 /* do we need to emulate setuid on scripts? */
1003 /* This code is for those BSD systems that have setuid #! scripts disabled
1004 * in the kernel because of a security problem. Merely defining DOSUID
1005 * in perl will not fix that problem, but if you have disabled setuid
1006 * scripts in the kernel, this will attempt to emulate setuid and setgid
1007 * on scripts that have those now-otherwise-useless bits set. The setuid
1008 * root version must be called suidperl or sperlN.NNN. If regular perl
1009 * discovers that it has opened a setuid script, it calls suidperl with
1010 * the same argv that it had. If suidperl finds that the script it has
1011 * just opened is NOT setuid root, it sets the effective uid back to the
1012 * uid. We don't just make perl setuid root because that loses the
1013 * effective uid we had before invoking perl, if it was different from the
1016 * DOSUID must be defined in both perl and suidperl, and IAMSUID must
1017 * be defined in suidperl only. suidperl must be setuid root. The
1018 * Configure script will set this up for you if you want it.
1022 if (fstat(fileno(rsfp),&statbuf) < 0) /* normal stat is insecure */
1023 croak("Can't stat script \"%s\"",origfilename);
1024 if (statbuf.st_mode & (S_ISUID|S_ISGID)) {
1028 #ifndef HAS_SETREUID
1029 /* On this access check to make sure the directories are readable,
1030 * there is actually a small window that the user could use to make
1031 * filename point to an accessible directory. So there is a faint
1032 * chance that someone could execute a setuid script down in a
1033 * non-accessible directory. I don't know what to do about that.
1034 * But I don't think it's too important. The manual lies when
1035 * it says access() is useful in setuid programs.
1037 if (access(SvPVX(GvSV(curcop->cop_filegv)),1)) /*double check*/
1038 croak("Permission denied");
1040 /* If we can swap euid and uid, then we can determine access rights
1041 * with a simple stat of the file, and then compare device and
1042 * inode to make sure we did stat() on the same file we opened.
1043 * Then we just have to make sure he or she can execute it.
1046 struct stat tmpstatbuf;
1048 if (setreuid(euid,uid) < 0 || getuid() != euid || geteuid() != uid)
1049 croak("Can't swap uid and euid"); /* really paranoid */
1050 if (stat(SvPVX(GvSV(curcop->cop_filegv)),&tmpstatbuf) < 0)
1051 croak("Permission denied"); /* testing full pathname here */
1052 if (tmpstatbuf.st_dev != statbuf.st_dev ||
1053 tmpstatbuf.st_ino != statbuf.st_ino) {
1055 if (rsfp = my_popen("/bin/mail root","w")) { /* heh, heh */
1057 "User %d tried to run dev %d ino %d in place of dev %d ino %d!\n\
1058 (Filename of set-id script was %s, uid %d gid %d.)\n\nSincerely,\nperl\n",
1059 uid,tmpstatbuf.st_dev, tmpstatbuf.st_ino,
1060 statbuf.st_dev, statbuf.st_ino,
1061 SvPVX(GvSV(curcop->cop_filegv)),
1062 statbuf.st_uid, statbuf.st_gid);
1063 (void)my_pclose(rsfp);
1065 croak("Permission denied\n");
1067 if (setreuid(uid,euid) < 0 || getuid() != uid || geteuid() != euid)
1068 croak("Can't reswap uid and euid");
1069 if (!cando(S_IXUSR,FALSE,&statbuf)) /* can real uid exec? */
1070 croak("Permission denied\n");
1072 #endif /* HAS_SETREUID */
1073 #endif /* IAMSUID */
1075 if (!S_ISREG(statbuf.st_mode))
1076 croak("Permission denied");
1077 if (statbuf.st_mode & S_IWOTH)
1078 croak("Setuid/gid script is writable by world");
1079 doswitches = FALSE; /* -s is insecure in suid */
1081 if (fgets(tokenbuf,sizeof tokenbuf, rsfp) == Nullch ||
1082 strnNE(tokenbuf,"#!",2) ) /* required even on Sys V */
1083 croak("No #! line");
1086 while (!isSPACE(*s)) s++;
1087 if (strnNE(s-4,"perl",4) && strnNE(s-9,"perl",4)) /* sanity check */
1088 croak("Not a perl script");
1089 while (*s == ' ' || *s == '\t') s++;
1091 * #! arg must be what we saw above. They can invoke it by
1092 * mentioning suidperl explicitly, but they may not add any strange
1093 * arguments beyond what #! says if they do invoke suidperl that way.
1095 len = strlen(validarg);
1096 if (strEQ(validarg," PHOOEY ") ||
1097 strnNE(s,validarg,len) || !isSPACE(s[len]))
1098 croak("Args must match #! line");
1101 if (euid != uid && (statbuf.st_mode & S_ISUID) &&
1102 euid == statbuf.st_uid)
1104 croak("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
1105 FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
1106 #endif /* IAMSUID */
1108 if (euid) { /* oops, we're not the setuid root perl */
1111 (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
1112 execv(buf, origargv); /* try again */
1114 croak("Can't do setuid\n");
1117 if (statbuf.st_mode & S_ISGID && statbuf.st_gid != egid) {
1119 (void)setegid(statbuf.st_gid);
1122 (void)setregid((GIDTYPE)-1,statbuf.st_gid);
1124 setgid(statbuf.st_gid);
1127 if (getegid() != statbuf.st_gid)
1128 croak("Can't do setegid!\n");
1130 if (statbuf.st_mode & S_ISUID) {
1131 if (statbuf.st_uid != euid)
1133 (void)seteuid(statbuf.st_uid); /* all that for this */
1136 (void)setreuid((UIDTYPE)-1,statbuf.st_uid);
1138 setuid(statbuf.st_uid);
1141 if (geteuid() != statbuf.st_uid)
1142 croak("Can't do seteuid!\n");
1144 else if (uid) { /* oops, mustn't run as root */
1146 (void)seteuid((UIDTYPE)uid);
1149 (void)setreuid((UIDTYPE)-1,(UIDTYPE)uid);
1151 setuid((UIDTYPE)uid);
1154 if (geteuid() != uid)
1155 croak("Can't do seteuid!\n");
1157 uid = (int)getuid();
1158 euid = (int)geteuid();
1159 gid = (int)getgid();
1160 egid = (int)getegid();
1161 tainting |= (euid != uid || egid != gid);
1162 if (!cando(S_IXUSR,TRUE,&statbuf))
1163 croak("Permission denied\n"); /* they can't do this */
1166 else if (preprocess)
1167 croak("-P not allowed for setuid/setgid script\n");
1169 croak("Script is not setuid/setgid in suidperl\n");
1170 #endif /* IAMSUID */
1172 if (euid != uid || egid != gid) { /* (suidperl doesn't exist, in fact) */
1173 #ifndef SETUID_SCRIPTS_ARE_SECURE_NOW
1174 fstat(fileno(rsfp),&statbuf); /* may be either wrapped or real suid */
1175 if ((euid != uid && euid == statbuf.st_uid && statbuf.st_mode & S_ISUID)
1177 (egid != gid && egid == statbuf.st_gid && statbuf.st_mode & S_ISGID)
1180 croak("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
1181 FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
1182 #endif /* SETUID_SCRIPTS_ARE_SECURE_NOW */
1183 /* not set-id, must be wrapped */
1193 /* skip forward in input to the real script? */
1197 if ((s = sv_gets(linestr, rsfp, 0)) == Nullch)
1198 croak("No Perl script found in input\n");
1199 if (*s == '#' && s[1] == '!' && instr(s,"perl")) {
1200 ungetc('\n',rsfp); /* to keep line count right */
1202 if (s = instr(s,"perl -")) {
1205 while (s = moreswitches(s)) ;
1207 if (cddir && chdir(cddir) < 0)
1208 croak("Can't chdir to %s",cddir);
1219 GvHV(gv_fetchpv("::_DB",TRUE)) = debstash;
1220 curstash = debstash;
1221 dbargs = GvAV(gv_AVadd((tmpgv = gv_fetchpv("args",TRUE))));
1224 DBgv = gv_fetchpv("DB",TRUE);
1226 DBline = gv_fetchpv("dbline",TRUE);
1228 DBsub = gv_HVadd(tmpgv = gv_fetchpv("sub",TRUE));
1230 DBsingle = GvSV((tmpgv = gv_fetchpv("single",TRUE)));
1232 DBtrace = GvSV((tmpgv = gv_fetchpv("trace",TRUE)));
1234 DBsignal = GvSV((tmpgv = gv_fetchpv("signal",TRUE)));
1236 curstash = defstash;
1243 mainstack = stack; /* remember in case we switch stacks */
1244 AvREAL_off(stack); /* not a real array */
1245 av_fill(stack,127); av_fill(stack,-1); /* preextend stack */
1247 stack_base = AvARRAY(stack);
1248 stack_sp = stack_base;
1249 stack_max = stack_base + 127;
1251 New(54,markstack,64,int);
1252 markstack_ptr = markstack;
1253 markstack_max = markstack + 64;
1255 New(54,scopestack,32,int);
1257 scopestack_max = 32;
1259 New(54,savestack,128,ANY);
1261 savestack_max = 128;
1263 New(54,retstack,16,OP*);
1267 New(50,cxstack,128,CONTEXT);
1271 New(50,tmps_stack,128,SV*);
1276 New(51,debname,128,char);
1277 New(52,debdelim,128,char);
1288 subname = newSVpv("main",4);
1292 init_predump_symbols()
1296 sv_setpvn(GvSV(gv_fetchpv("\"", TRUE)), " ", 1);
1298 stdingv = gv_fetchpv("STDIN",TRUE);
1299 SvMULTI_on(stdingv);
1301 GvIO(stdingv) = newIO();
1302 IoIFP(GvIO(stdingv)) = stdin;
1303 tmpgv = gv_fetchpv("stdin",TRUE);
1304 GvIO(tmpgv) = (IO*)SvREFCNT_inc(GvIO(stdingv));
1307 tmpgv = gv_fetchpv("STDOUT",TRUE);
1310 GvIO(tmpgv) = newIO();
1311 IoOFP(GvIO(tmpgv)) = IoIFP(GvIO(tmpgv)) = stdout;
1313 tmpgv = gv_fetchpv("stdout",TRUE);
1314 GvIO(tmpgv) = (IO*)SvREFCNT_inc(GvIO(defoutgv));
1317 curoutgv = gv_fetchpv("STDERR",TRUE);
1318 SvMULTI_on(curoutgv);
1319 if (!GvIO(curoutgv))
1320 GvIO(curoutgv) = newIO();
1321 IoOFP(GvIO(curoutgv)) = IoIFP(GvIO(curoutgv)) = stderr;
1322 tmpgv = gv_fetchpv("stderr",TRUE);
1323 GvIO(tmpgv) = (IO*)SvREFCNT_inc(GvIO(curoutgv));
1325 curoutgv = defoutgv; /* switch back to STDOUT */
1327 statname = NEWSV(66,0); /* last filename we did stat on */
1331 init_postdump_symbols(argc,argv,env)
1333 register char **argv;
1334 register char **env;
1340 argc--,argv++; /* skip name of script */
1342 for (; argc > 0 && **argv == '-'; argc--,argv++) {
1345 if (argv[0][1] == '-') {
1349 if (s = strchr(argv[0], '=')) {
1351 sv_setpv(GvSV(gv_fetchpv(argv[0]+1,TRUE)),s);
1354 sv_setiv(GvSV(gv_fetchpv(argv[0]+1,TRUE)),1);
1357 toptarget = NEWSV(0,0);
1358 sv_upgrade(toptarget, SVt_PVFM);
1359 sv_setpvn(toptarget, "", 0);
1360 bodytarget = NEWSV(0,0);
1361 sv_upgrade(bodytarget, SVt_PVFM);
1362 sv_setpvn(bodytarget, "", 0);
1363 formtarget = bodytarget;
1366 if (tmpgv = gv_fetchpv("0",TRUE)) {
1367 sv_setpv(GvSV(tmpgv),origfilename);
1368 magicname("0", "0", 1);
1370 if (tmpgv = gv_fetchpv("\024",TRUE))
1372 if (tmpgv = gv_fetchpv("\030",TRUE))
1373 sv_setpv(GvSV(tmpgv),origargv[0]);
1374 if (argvgv = gv_fetchpv("ARGV",TRUE)) {
1376 (void)gv_AVadd(argvgv);
1377 av_clear(GvAVn(argvgv));
1378 for (; argc > 0; argc--,argv++) {
1379 (void)av_push(GvAVn(argvgv),newSVpv(argv[0],0));
1382 if (envgv = gv_fetchpv("ENV",TRUE)) {
1387 if (env != environ) {
1388 environ[0] = Nullch;
1389 hv_magic(hv, envgv, 'E');
1391 for (; *env; env++) {
1392 if (!(s = strchr(*env,'=')))
1395 sv = newSVpv(s--,0);
1396 (void)hv_store(hv, *env, s - *env, sv, 0);
1399 hv_magic(hv, envgv, 'E');
1402 if (tmpgv = gv_fetchpv("$",TRUE))
1403 sv_setiv(GvSV(tmpgv),(I32)getpid());
1411 incpush(getenv("PERLLIB"));
1414 #define PRIVLIB "/usr/local/lib/perl"
1417 (void)av_push(GvAVn(incgv),newSVpv(".",1));
1425 I32 sp = stack_sp - stack_base;
1427 av_store(stack, ++sp, Nullsv); /* reserve spot for sub reference */
1428 Copy(top_env, oldtop, 1, jmp_buf);
1430 while (AvFILL(list) >= 0) {
1431 CV *cv = (CV*)av_shift(list);
1434 if (setjmp(top_env)) {
1435 if (list == beginav) {
1436 warn("BEGIN failed--execution aborted");
1437 Copy(oldtop, top_env, 1, jmp_buf);
1442 perl_callsv((SV*)cv, sp, G_SCALAR, 0, 0);
1446 Copy(oldtop, top_env, 1, jmp_buf);