1 char rcsid[] = "$RCSfile: perl.c,v $$Revision: 4.0.1.4 $$Date: 91/06/10 01:23:07 $\nPatch level: ###\n";
3 * Copyright (c) 1991, Larry Wall
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.
9 * Revision 4.0.1.4 91/06/10 01:23:07 lwall
10 * patch10: perl -v printed incorrect copyright notice
12 * Revision 4.0.1.3 91/06/07 11:40:18 lwall
13 * patch4: changed old $^P to $^X
15 * Revision 4.0.1.2 91/06/07 11:26:16 lwall
16 * patch4: new copyright notice
17 * patch4: added $^P variable to control calling of perldb routines
18 * patch4: added $^F variable to specify maximum system fd, default 2
19 * patch4: debugger lost track of lines in eval
21 * Revision 4.0.1.1 91/04/11 17:49:05 lwall
22 * patch1: fixed undefined environ problem
24 * Revision 4.0 91/03/20 01:37:44 lwall
35 #include "patchlevel.h"
46 #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
52 static char* moreswitches();
55 static char patchlevel[6];
56 static char *nrs = "\n";
57 static int nrschar = '\n'; /* final char of rs, or 0777 if none */
58 static int nrslen = 1;
68 bool dosearch = FALSE;
73 #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
76 fatal("suidperl is no longer needed since the kernel can now execute\n\
77 setuid perl scripts securely.\n");
83 origenviron = environ;
85 euid = (int)geteuid();
87 egid = (int)getegid();
88 sprintf(patchlevel,"%3.3s%2.2d", index(rcsid,'4'), PATCHLEVEL);
91 * There is no way we can refer to them from Perl so close them to save
92 * space. The other alternative would be to provide STDAUX and STDPRN
99 origfilename = savestr(argv[0]);
101 loop_ptr = -1; /* start label stack again */
104 (void)sprintf(index(rcsid,'#'), "%d\n", PATCHLEVEL);
105 linestr = Str_new(65,80);
106 str_nset(linestr,"",0);
107 str = str_make("",0); /* first used for -I flags */
108 curstash = defstash = hnew(0);
109 curstname = str_make("main",4);
110 stab_xhash(stabent("_main",TRUE)) = defstash;
111 defstash->tbl_name = "main";
112 incstab = hadd(aadd(stabent("INC",TRUE)));
113 incstab->str_pok |= SP_MULTI;
114 for (argc--,argv++; argc > 0; argc--,argv++) {
115 if (argv[0][0] != '-' || !argv[0][1])
119 validarg = " PHOOEY ";
139 if (s = moreswitches(s))
145 if (euid != uid || egid != gid)
146 fatal("No -e allowed in setuid scripts");
149 e_tmpname = savestr(TMPPATH);
150 (void)mktemp(e_tmpname);
151 e_fp = fopen(e_tmpname,"w");
153 fatal("Cannot open temporary file");
159 (void)putc('\n', e_fp);
163 if (euid != uid || egid != gid)
164 fatal("No -I allowed in setuid scripts");
170 (void)apush(stab_array(incstab),str_make(s,0));
173 (void)apush(stab_array(incstab),str_make(argv[1],0));
174 str_cat(str,argv[1]);
181 if (euid != uid || egid != gid)
182 fatal("No -P allowed in setuid scripts");
189 if (euid != uid || egid != gid)
190 fatal("No -s allowed in setuid scripts");
211 fatal("Unrecognized switch: -%s",s);
222 #define PERLLIB_SEP ';'
224 #define PERLLIB_SEP ':'
226 #ifndef TAINT /* Can't allow arbitrary PERLLIB in setuid script */
228 char * s2 = getenv("PERLLIB");
231 /* Break at all separators */
233 /* First, skip any consecutive separators */
234 while ( *s2 == PERLLIB_SEP ) {
235 /* Uncomment the next line for PATH semantics */
236 /* (void)apush(stab_array(incstab),str_make(".",1)); */
239 if ( (s = index(s2,PERLLIB_SEP)) != Nullch ) {
240 (void)apush(stab_array(incstab),str_make(s2,(int)(s-s2)));
243 (void)apush(stab_array(incstab),str_make(s2,0));
252 #define PRIVLIB "/usr/local/lib/perl"
254 (void)apush(stab_array(incstab),str_make(PRIVLIB,0));
255 (void)apush(stab_array(incstab),str_make(".",1));
258 str_set(&str_yes,Yes);
262 if (argv[0] == Nullch)
265 if ( isatty(fileno(stdin)) )
272 if (dosearch && !index(argv[0], '/') && (s = getenv("PATH"))) {
273 char *xfound = Nullch, *xfailed = Nullch;
276 bufend = s + strlen(s);
279 s = cpytill(tokenbuf,s,bufend,':',&len);
281 for (len = 0; *s && *s != ';'; tokenbuf[len++] = *s++);
282 tokenbuf[len] = '\0';
287 if (len && tokenbuf[len-1] != '/')
289 if (len && tokenbuf[len-1] != '\\')
291 (void)strcat(tokenbuf+len,"/");
292 (void)strcat(tokenbuf+len,argv[0]);
295 fprintf(stderr,"Looking for %s\n",tokenbuf);
297 if (stat(tokenbuf,&statbuf) < 0) /* not there? */
299 if (S_ISREG(statbuf.st_mode)
300 && cando(S_IRUSR,TRUE,&statbuf) && cando(S_IXUSR,TRUE,&statbuf)) {
301 xfound = tokenbuf; /* bingo! */
305 xfailed = savestr(tokenbuf);
308 fatal("Can't execute %s", xfailed ? xfailed : argv[0] );
311 argv[0] = savestr(xfound);
314 fdpid = anew(Nullstab); /* for remembering popen pids by fd */
315 pidstatus = hnew(COEFFSIZE);/* for remembering status of dead pids */
317 origfilename = savestr(argv[0]);
318 curcmd->c_filestab = fstab(origfilename);
319 if (strEQ(origfilename,"-"))
323 str_cat(str,PRIVLIB);
324 (void)sprintf(buf, "\
325 %ssed %s -e '/^[^#]/b' \
326 -e '/^#[ ]*include[ ]/b' \
327 -e '/^#[ ]*define[ ]/b' \
328 -e '/^#[ ]*if[ ]/b' \
329 -e '/^#[ ]*ifdef[ ]/b' \
330 -e '/^#[ ]*ifndef[ ]/b' \
332 -e '/^#[ ]*endif/b' \
340 (doextract ? "-e '1,/^#/d\n'" : ""),
341 argv[0], CPPSTDIN, str_get(str), CPPMINUS);
349 #ifdef IAMSUID /* actually, this is caught earlier */
350 if (euid != uid && !euid) /* if running suidperl */
352 (void)seteuid(uid); /* musn't stay setuid root */
355 (void)setreuid(-1, uid);
361 rsfp = mypopen(buf,"r");
366 rsfp = fopen(argv[0],"r");
367 if (rsfp == Nullfp) {
369 #ifndef IAMSUID /* in case script is not readable before setuid */
370 if (euid && stat(stab_val(curcmd->c_filestab)->str_ptr,&statbuf) >= 0 &&
371 statbuf.st_mode & (S_ISUID|S_ISGID)) {
372 (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
373 execv(buf, origargv); /* try again */
374 fatal("Can't do setuid\n");
378 fatal("Can't open perl script \"%s\": %s\n",
379 stab_val(curcmd->c_filestab)->str_ptr, strerror(errno));
381 str_free(str); /* free -I directories */
384 /* do we need to emulate setuid on scripts? */
386 /* This code is for those BSD systems that have setuid #! scripts disabled
387 * in the kernel because of a security problem. Merely defining DOSUID
388 * in perl will not fix that problem, but if you have disabled setuid
389 * scripts in the kernel, this will attempt to emulate setuid and setgid
390 * on scripts that have those now-otherwise-useless bits set. The setuid
391 * root version must be called suidperl or sperlN.NNN. If regular perl
392 * discovers that it has opened a setuid script, it calls suidperl with
393 * the same argv that it had. If suidperl finds that the script it has
394 * just opened is NOT setuid root, it sets the effective uid back to the
395 * uid. We don't just make perl setuid root because that loses the
396 * effective uid we had before invoking perl, if it was different from the
399 * DOSUID must be defined in both perl and suidperl, and IAMSUID must
400 * be defined in suidperl only. suidperl must be setuid root. The
401 * Configure script will set this up for you if you want it.
403 * There is also the possibility of have a script which is running
404 * set-id due to a C wrapper. We want to do the TAINT checks
405 * on these set-id scripts, but don't want to have the overhead of
406 * them in normal perl, and can't use suidperl because it will lose
407 * the effective uid info, so we have an additional non-setuid root
408 * version called taintperl or tperlN.NNN that just does the TAINT checks.
412 if (fstat(fileno(rsfp),&statbuf) < 0) /* normal stat is insecure */
413 fatal("Can't stat script \"%s\"",origfilename);
414 if (statbuf.st_mode & (S_ISUID|S_ISGID)) {
419 /* On this access check to make sure the directories are readable,
420 * there is actually a small window that the user could use to make
421 * filename point to an accessible directory. So there is a faint
422 * chance that someone could execute a setuid script down in a
423 * non-accessible directory. I don't know what to do about that.
424 * But I don't think it's too important. The manual lies when
425 * it says access() is useful in setuid programs.
427 if (access(stab_val(curcmd->c_filestab)->str_ptr,1)) /*double check*/
428 fatal("Permission denied");
430 /* If we can swap euid and uid, then we can determine access rights
431 * with a simple stat of the file, and then compare device and
432 * inode to make sure we did stat() on the same file we opened.
433 * Then we just have to make sure he or she can execute it.
436 struct stat tmpstatbuf;
438 if (setreuid(euid,uid) < 0 || getuid() != euid || geteuid() != uid)
439 fatal("Can't swap uid and euid"); /* really paranoid */
440 if (stat(stab_val(curcmd->c_filestab)->str_ptr,&tmpstatbuf) < 0)
441 fatal("Permission denied"); /* testing full pathname here */
442 if (tmpstatbuf.st_dev != statbuf.st_dev ||
443 tmpstatbuf.st_ino != statbuf.st_ino) {
445 if (rsfp = mypopen("/bin/mail root","w")) { /* heh, heh */
447 "User %d tried to run dev %d ino %d in place of dev %d ino %d!\n\
448 (Filename of set-id script was %s, uid %d gid %d.)\n\nSincerely,\nperl\n",
449 uid,tmpstatbuf.st_dev, tmpstatbuf.st_ino,
450 statbuf.st_dev, statbuf.st_ino,
451 stab_val(curcmd->c_filestab)->str_ptr,
452 statbuf.st_uid, statbuf.st_gid);
453 (void)mypclose(rsfp);
455 fatal("Permission denied\n");
457 if (setreuid(uid,euid) < 0 || getuid() != uid || geteuid() != euid)
458 fatal("Can't reswap uid and euid");
459 if (!cando(S_IXUSR,FALSE,&statbuf)) /* can real uid exec? */
460 fatal("Permission denied\n");
462 #endif /* HAS_SETREUID */
465 if (!S_ISREG(statbuf.st_mode))
466 fatal("Permission denied");
467 if (statbuf.st_mode & S_IWOTH)
468 fatal("Setuid/gid script is writable by world");
469 doswitches = FALSE; /* -s is insecure in suid */
471 if (fgets(tokenbuf,sizeof tokenbuf, rsfp) == Nullch ||
472 strnNE(tokenbuf,"#!",2) ) /* required even on Sys V */
476 while (!isspace(*s)) s++;
477 if (strnNE(s-4,"perl",4) && strnNE(s-9,"perl",4)) /* sanity check */
478 fatal("Not a perl script");
479 while (*s == ' ' || *s == '\t') s++;
481 * #! arg must be what we saw above. They can invoke it by
482 * mentioning suidperl explicitly, but they may not add any strange
483 * arguments beyond what #! says if they do invoke suidperl that way.
485 len = strlen(validarg);
486 if (strEQ(validarg," PHOOEY ") ||
487 strnNE(s,validarg,len) || !isspace(s[len]))
488 fatal("Args must match #! line");
491 if (euid != uid && (statbuf.st_mode & S_ISUID) &&
492 euid == statbuf.st_uid)
494 fatal("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
495 FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
498 if (euid) { /* oops, we're not the setuid root perl */
501 (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
502 execv(buf, origargv); /* try again */
504 fatal("Can't do setuid\n");
507 if (statbuf.st_mode & S_ISGID && statbuf.st_gid != egid)
509 (void)setegid(statbuf.st_gid);
512 (void)setregid((GIDTYPE)-1,statbuf.st_gid);
514 setgid(statbuf.st_gid);
517 if (statbuf.st_mode & S_ISUID) {
518 if (statbuf.st_uid != euid)
520 (void)seteuid(statbuf.st_uid); /* all that for this */
523 (void)setreuid((UIDTYPE)-1,statbuf.st_uid);
525 setuid(statbuf.st_uid);
529 else if (uid) /* oops, mustn't run as root */
531 (void)seteuid((UIDTYPE)uid);
534 (void)setreuid((UIDTYPE)-1,(UIDTYPE)uid);
536 setuid((UIDTYPE)uid);
540 euid = (int)geteuid();
542 egid = (int)getegid();
543 if (!cando(S_IXUSR,TRUE,&statbuf))
544 fatal("Permission denied\n"); /* they can't do this */
548 fatal("-P not allowed for setuid/setgid script\n");
550 fatal("Script is not setuid/setgid in suidperl\n");
552 #ifndef TAINT /* we aren't taintperl or suidperl */
553 /* script has a wrapper--can't run suidperl or we lose euid */
554 else if (euid != uid || egid != gid) {
556 (void)sprintf(buf, "%s/tperl%s", BIN, patchlevel);
557 execv(buf, origargv); /* try again */
558 fatal("Can't run setuid script with taint checks");
563 #ifndef TAINT /* we aren't taintperl or suidperl */
564 if (euid != uid || egid != gid) { /* (suidperl doesn't exist, in fact) */
565 #ifndef SETUID_SCRIPTS_ARE_SECURE_NOW
566 fstat(fileno(rsfp),&statbuf); /* may be either wrapped or real suid */
567 if ((euid != uid && euid == statbuf.st_uid && statbuf.st_mode & S_ISUID)
569 (egid != gid && egid == statbuf.st_gid && statbuf.st_mode & S_ISGID)
572 fatal("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
573 FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
574 #endif /* SETUID_SCRIPTS_ARE_SECURE_NOW */
575 /* not set-id, must be wrapped */
577 (void)sprintf(buf, "%s/tperl%s", BIN, patchlevel);
578 execv(buf, origargv); /* try again */
579 fatal("Can't run setuid script with taint checks");
584 #if !defined(IAMSUID) && !defined(TAINT)
586 /* skip forward in input to the real script? */
589 if ((s = str_gets(linestr, rsfp, 0)) == Nullch)
590 fatal("No Perl script found in input\n");
591 if (*s == '#' && s[1] == '!' && instr(s,"perl")) {
592 ungetc('\n',rsfp); /* to keep line count right */
594 if (s = instr(s,"perl -")) {
596 while (s = moreswitches(s)) ;
598 if (cddir && chdir(cddir) < 0)
599 fatal("Can't chdir to %s",cddir);
602 #endif /* !defined(IAMSUID) && !defined(TAINT) */
604 defstab = stabent("_",TRUE);
608 stab_xhash(stabent("_DB",TRUE)) = debstash;
610 dbargs = stab_xarray(aadd((tmpstab = stabent("args",TRUE))));
611 tmpstab->str_pok |= SP_MULTI;
612 dbargs->ary_flags = 0;
613 subname = str_make("main",4);
614 DBstab = stabent("DB",TRUE);
615 DBstab->str_pok |= SP_MULTI;
616 DBline = stabent("dbline",TRUE);
617 DBline->str_pok |= SP_MULTI;
618 DBsub = hadd(tmpstab = stabent("sub",TRUE));
619 tmpstab->str_pok |= SP_MULTI;
620 DBsingle = stab_val((tmpstab = stabent("single",TRUE)));
621 tmpstab->str_pok |= SP_MULTI;
622 DBtrace = stab_val((tmpstab = stabent("trace",TRUE)));
623 tmpstab->str_pok |= SP_MULTI;
624 DBsignal = stab_val((tmpstab = stabent("signal",TRUE)));
625 tmpstab->str_pok |= SP_MULTI;
631 bufend = bufptr = str_get(linestr);
633 savestack = anew(Nullstab); /* for saving non-local values */
634 stack = anew(Nullstab); /* for saving non-local values */
635 stack->ary_flags = 0; /* not a real array */
636 afill(stack,63); afill(stack,-1); /* preextend stack */
637 afill(savestack,63); afill(savestack,-1);
639 /* now parse the script */
642 if (yyparse() || error_count) {
644 fatal("%s had compilation errors.\n", origfilename);
646 fatal("Execution of %s aborted due to compilation errors.\n",
651 New(50,loop_stack,128,struct loop);
654 New(51,debname,128,char);
655 New(52,debdelim,128,char);
663 (void)UNLINK(e_tmpname);
666 /* initialize everything that won't change if we undump */
668 if (sigstab = stabent("SIG",allstabs)) {
669 sigstab->str_pok |= SP_MULTI;
673 magicalize("!#?^~=-%.+&*()<>,\\/[|`':\004\t\020\024\027\006");
674 userinit(); /* in case linked C routines want magical variables */
676 amperstab = stabent("&",allstabs);
677 leftstab = stabent("`",allstabs);
678 rightstab = stabent("'",allstabs);
679 sawampersand = (amperstab || leftstab || rightstab);
680 if (tmpstab = stabent(":",allstabs))
681 str_set(STAB_STR(tmpstab),chopset);
682 if (tmpstab = stabent("\024",allstabs))
685 /* these aren't necessarily magical */
686 if (tmpstab = stabent(";",allstabs))
687 str_set(STAB_STR(tmpstab),"\034");
688 if (tmpstab = stabent("]",allstabs)) {
689 str = STAB_STR(tmpstab);
691 str->str_u.str_nval = atof(patchlevel);
694 str_nset(stab_val(stabent("\"", TRUE)), " ", 1);
696 stdinstab = stabent("STDIN",TRUE);
697 stdinstab->str_pok |= SP_MULTI;
698 stab_io(stdinstab) = stio_new();
699 stab_io(stdinstab)->ifp = stdin;
700 tmpstab = stabent("stdin",TRUE);
701 stab_io(tmpstab) = stab_io(stdinstab);
702 tmpstab->str_pok |= SP_MULTI;
704 tmpstab = stabent("STDOUT",TRUE);
705 tmpstab->str_pok |= SP_MULTI;
706 stab_io(tmpstab) = stio_new();
707 stab_io(tmpstab)->ofp = stab_io(tmpstab)->ifp = stdout;
708 defoutstab = tmpstab;
709 tmpstab = stabent("stdout",TRUE);
710 stab_io(tmpstab) = stab_io(defoutstab);
711 tmpstab->str_pok |= SP_MULTI;
713 curoutstab = stabent("STDERR",TRUE);
714 curoutstab->str_pok |= SP_MULTI;
715 stab_io(curoutstab) = stio_new();
716 stab_io(curoutstab)->ofp = stab_io(curoutstab)->ifp = stderr;
717 tmpstab = stabent("stderr",TRUE);
718 stab_io(tmpstab) = stab_io(curoutstab);
719 tmpstab->str_pok |= SP_MULTI;
720 curoutstab = defoutstab; /* switch back to STDOUT */
722 statname = Str_new(66,0); /* last filename we did stat on */
724 /* now that script is parsed, we can modify record separator */
729 str_nset(stab_val(stabent("/", TRUE)), rs, rslen);
734 just_doit: /* come here if running an undumped a.out */
735 argc--,argv++; /* skip name of script */
737 for (; argc > 0 && **argv == '-'; argc--,argv++) {
738 if (argv[0][1] == '-') {
742 if (s = index(argv[0], '=')) {
744 str_set(stab_val(stabent(argv[0]+1,TRUE)),s);
747 str_numset(stab_val(stabent(argv[0]+1,TRUE)),(double)1.0);
753 if (tmpstab = stabent("0",allstabs)) {
754 str_set(stab_val(tmpstab),origfilename);
755 magicname("0", Nullch, 0);
757 if (tmpstab = stabent("\030",allstabs))
758 str_set(stab_val(tmpstab),origargv[0]);
759 if (argvstab = stabent("ARGV",allstabs)) {
760 argvstab->str_pok |= SP_MULTI;
761 (void)aadd(argvstab);
762 aclear(stab_array(argvstab));
763 for (; argc > 0; argc--,argv++) {
764 (void)apush(stab_array(argvstab),str_make(argv[0],0));
768 (void) stabent("ENV",TRUE); /* must test PATH and IFS */
770 if (envstab = stabent("ENV",allstabs)) {
771 envstab->str_pok |= SP_MULTI;
773 hclear(stab_hash(envstab), FALSE);
776 for (; *env; env++) {
777 if (!(s = index(*env,'=')))
780 str = str_make(s--,0);
781 str_magic(str, envstab, 'E', *env, s - *env);
782 (void)hstore(stab_hash(envstab), *env, s - *env, str, 0);
789 if (tmpstab = stabent("$",allstabs))
790 str_numset(STAB_STR(tmpstab),(double)getpid());
797 if (setjmp(top_env)) /* sets goto_targ on longjump */
798 loop_ptr = -1; /* start label stack again */
804 fprintf(stderr,"\nEXECUTING...\n\n");
808 fprintf(stderr,"%s syntax OK\n", origfilename);
814 (void) cmd_exec(main_root,G_SCALAR,-1);
817 fatal("Can't find label \"%s\"--aborting",goto_targ);
829 while (*sym = *list++)
830 magicname(sym, Nullch, 0);
834 magicname(sym,name,namlen)
841 if (stab = stabent(sym,allstabs)) {
842 stab_flags(stab) = SF_VMAGIC;
843 str_magic(stab_val(stab), stab, 0, name, namlen);
848 savelines(array, str)
852 register char *s = str->str_ptr;
853 register char *send = str->str_ptr + str->str_cur;
855 register int line = 1;
857 while (s && s < send) {
858 STR *tmpstr = Str_new(85,0);
866 str_nset(tmpstr, s, t - s);
867 astore(array, line++, tmpstr);
872 /* this routine is in perl.c by virtue of being sort of an alternate main() */
875 do_eval(str,optype,stash,gimme,arglast)
882 STR **st = stack->ary_array;
884 CMD *myroot = Nullcmd;
887 CMD * VOLATILE oldcurcmd = curcmd;
888 VOLATILE int oldtmps_base = tmps_base;
889 VOLATILE int oldsave = savestack->ary_fill;
890 VOLATILE int oldperldb = perldb;
891 SPAT * VOLATILE oldspat = curspat;
892 SPAT * VOLATILE oldlspat = lastspat;
893 static char *last_eval = Nullch;
894 static CMD *last_root = Nullcmd;
895 VOLATILE int sp = arglast[0];
900 tmps_base = tmps_max;
901 if (curstash != stash) {
902 (void)savehptr(&curstash);
905 str_set(stab_val(stabent("@",TRUE)),"");
906 if (curcmd->c_line == 0) /* don't debug debugger... */
909 if (optype == O_EVAL) { /* normal eval */
910 curcmd->c_filestab = fstab("(eval)");
912 str_sset(linestr,str);
913 str_cat(linestr,";\n"); /* be kind to them */
915 savelines(stab_xarray(curcmd->c_filestab), linestr);
918 if (last_root && !in_eval) {
924 specfilename = str_get(str);
926 if (optype == O_REQUIRE && &str_undef !=
927 hfetch(stab_hash(incstab), specfilename, strlen(specfilename), 0)) {
929 tmps_base = oldtmps_base;
934 tmpfilename = savestr(specfilename);
935 if (index("/.", *tmpfilename))
936 rsfp = fopen(tmpfilename,"r");
938 ar = stab_array(incstab);
939 for (i = 0; i <= ar->ary_fill; i++) {
940 (void)sprintf(buf, "%s/%s",
941 str_get(afetch(ar,i,TRUE)), specfilename);
942 rsfp = fopen(buf,"r");
946 if (*s == '.' && s[1] == '/')
948 Safefree(tmpfilename);
949 tmpfilename = savestr(s);
954 curcmd->c_filestab = fstab(tmpfilename);
955 Safefree(tmpfilename);
956 tmpfilename = Nullch;
959 tmps_base = oldtmps_base;
960 if (optype == O_REQUIRE) {
961 sprintf(tokenbuf,"Can't locate %s in @INC", specfilename);
962 if (instr(tokenbuf,".h "))
963 strcat(tokenbuf," (change .h to .ph maybe?)");
964 if (instr(tokenbuf,".ph "))
965 strcat(tokenbuf," (did you run h2ph?)");
966 fatal("%s",tokenbuf);
968 if (gimme != G_ARRAY)
969 st[++sp] = &str_undef;
976 oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
977 bufend = bufptr + linestr->str_cur;
978 if (++loop_ptr >= loop_max) {
980 Renew(loop_stack, loop_max, struct loop);
982 loop_stack[loop_ptr].loop_label = "_EVAL_";
983 loop_stack[loop_ptr].loop_sp = sp;
986 deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
990 if (setjmp(loop_stack[loop_ptr].loop_env)) {
997 retval |= error_count;
999 else if (last_root && *bufptr == *last_eval && strEQ(bufptr,last_eval)){
1001 eval_root = last_root; /* no point in reparsing */
1003 else if (in_eval == 1) {
1005 Safefree(last_eval);
1007 cmd_free(last_root);
1009 last_root = Nullcmd;
1010 last_eval = savestr(bufptr);
1012 retval |= error_count;
1014 last_root = eval_root;
1016 Safefree(last_eval);
1023 myroot = eval_root; /* in case cmd_exec does another eval! */
1026 st = stack->ary_array;
1028 if (gimme != G_ARRAY)
1029 st[++sp] = &str_undef;
1031 #ifndef MANGLEDPARSE
1034 fprintf(stderr,"Freeing eval_root %lx\n",(long)eval_root);
1036 cmd_free(eval_root);
1038 if (eval_root == last_root)
1039 last_root = Nullcmd;
1040 eval_root = myroot = Nullcmd;
1049 sp = cmd_exec(eval_root,gimme,sp);
1050 st = stack->ary_array;
1051 for (i = arglast[0] + 1; i <= sp; i++)
1052 st[i] = str_mortal(st[i]);
1053 /* if we don't save result, free zaps it */
1054 if (in_eval != 1 && myroot != last_root)
1062 char *tmps = loop_stack[loop_ptr].loop_label;
1063 deb("(Popping label #%d %s)\n",loop_ptr,
1068 tmps_base = oldtmps_base;
1070 lastspat = oldlspat;
1071 if (savestack->ary_fill > oldsave) /* let them use local() */
1072 restorelist(oldsave);
1074 if (optype != O_EVAL) {
1076 if (optype == O_REQUIRE)
1077 fatal("%s", str_get(stab_val(stabent("@",TRUE))));
1081 if (gimme == G_SCALAR ? str_true(st[sp]) : sp > arglast[0]) {
1082 (void)hstore(stab_hash(incstab), specfilename,
1083 strlen(specfilename), str_smake(stab_val(curcmd->c_filestab)),
1086 else if (optype == O_REQUIRE)
1087 fatal("%s did not return a true value", specfilename);
1094 /* This routine handles any switches that can be given during run */
1105 nrschar = scanoct(s, 4, &numlen);
1106 nrs = nsavestr("\n",1);
1108 if (nrschar > 0377) {
1112 else if (!nrschar && numlen >= 2) {
1128 if (euid != uid || egid != gid)
1129 fatal("No -d allowed in setuid scripts");
1137 if (euid != uid || egid != gid)
1138 fatal("No -D allowed in setuid scripts");
1140 debug = atoi(s+1) | 32768;
1142 warn("Recompile perl with -DDEBUGGING to use -D switch\n");
1144 for (s++; isdigit(*s); s++) ;
1147 inplace = savestr(s+1);
1148 for (s = inplace; *s && !isspace(*s); s++) ;
1153 if (euid != uid || egid != gid)
1154 fatal("No -I allowed in setuid scripts");
1157 (void)apush(stab_array(incstab),str_make(s,0));
1160 fatal("No space allowed after -I");
1166 ors = savestr("\n");
1168 *ors = scanoct(s, 3 + (*s == '0'), &numlen);
1172 ors = nsavestr(nrs,nrslen);
1193 fputs("\nThis is perl, version 4.0\n\n",stdout);
1194 fputs(rcsid,stdout);
1195 fputs("\nCopyright (c) 1989, 1990, 1991, Larry Wall\n",stdout);
1197 fputs("MS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n",
1200 fputs("OS/2 port Copyright (c) 1990, Raymond Chen, Kai Uwe Rommel\n",
1205 Perl may be copied only under the terms of either the Artistic License or the\n\
1206 GNU General Public License, which may be found in the Perl 4.0 source kit.\n",stdout);
1220 fatal("Switch meaningless after -x: -%s",s);
1225 /* compliments of Tom Christiansen */
1227 /* unexec() can be found in the Gnu emacs distribution */
1234 static char dumpname[BUFSIZ];
1235 static char perlpath[256];
1237 sprintf (dumpname, "%s.perldump", origfilename);
1238 sprintf (perlpath, "%s/perl", BIN);
1240 status = unexec(dumpname, perlpath, &etext, sbrk(0), 0);
1242 fprintf(stderr, "unexec of %s into %s failed!\n", perlpath, dumpname);
1246 abort(); /* nothing else to do */
1249 # define SIGABRT SIGILL
1252 # define SIGILL 6 /* blech */
1254 kill(getpid(),SIGABRT); /* for use with undump */
1255 #endif /* ! MSDOS */