This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 3.0 patch #7 (combined patch)
[perl5.git] / perly.c
CommitLineData
ffed7fef 1char rcsid[] = "$Header: perly.c,v 3.0.1.2 89/11/17 15:34:42 lwall Locked $\nPatch level: ###\n";
8d063cd8 2/*
a687059c
LW
3 * Copyright (c) 1989, Larry Wall
4 *
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
7 *
8d063cd8 8 * $Log: perly.c,v $
ffed7fef
LW
9 * Revision 3.0.1.2 89/11/17 15:34:42 lwall
10 * patch5: fixed possible confusion about current effective gid
11 *
ae986130
LW
12 * Revision 3.0.1.1 89/11/11 04:50:04 lwall
13 * patch2: moved yydebug to where its type didn't matter
14 *
a687059c
LW
15 * Revision 3.0 89/10/18 15:22:21 lwall
16 * 3.0 baseline
8d063cd8
LW
17 *
18 */
19
378cc40b
LW
20#include "EXTERN.h"
21#include "perl.h"
22#include "perly.h"
a687059c 23#include "patchlevel.h"
378cc40b 24
a687059c
LW
25#ifdef IAMSUID
26#ifndef DOSUID
27#define DOSUID
28#endif
29#endif
378cc40b 30
a687059c
LW
31#ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
32#ifdef DOSUID
33#undef DOSUID
34#endif
35#endif
8d063cd8
LW
36
37main(argc,argv,env)
38register int argc;
39register char **argv;
40register char **env;
41{
42 register STR *str;
43 register char *s;
378cc40b
LW
44 char *index(), *strcpy(), *getenv();
45 bool dosearch = FALSE;
13281fa4 46 char **origargv = argv;
a687059c 47#ifdef DOSUID
13281fa4
LW
48 char *validarg = "";
49#endif
8d063cd8 50
a687059c
LW
51#ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
52#ifdef IAMSUID
53#undef IAMSUID
54 fatal("suidperl is no longer needed since the kernel can now execute\n\
55setuid perl scripts securely.\n");
56#endif
57#endif
58
378cc40b
LW
59 uid = (int)getuid();
60 euid = (int)geteuid();
a687059c
LW
61 gid = (int)getgid();
62 egid = (int)getegid();
63 if (do_undump) {
64 do_undump = 0;
65 loop_ptr = 0; /* start label stack again */
66 goto just_doit;
67 }
68 (void)sprintf(index(rcsid,'#'), "%d\n", PATCHLEVEL);
69 linestr = Str_new(65,80);
378cc40b 70 str_nset(linestr,"",0);
a687059c
LW
71 str = str_make("",0); /* first used for -I flags */
72 curstash = defstash = hnew(0);
73 curstname = str_make("main",4);
74 stab_xhash(stabent("_main",TRUE)) = defstash;
378cc40b 75 incstab = aadd(stabent("INC",TRUE));
a687059c 76 incstab->str_pok |= SP_MULTI;
8d063cd8
LW
77 for (argc--,argv++; argc; argc--,argv++) {
78 if (argv[0][0] != '-' || !argv[0][1])
79 break;
13281fa4
LW
80#ifdef DOSUID
81 if (*validarg)
82 validarg = " PHOOEY ";
83 else
84 validarg = argv[0];
85#endif
86 s = argv[0]+1;
8d063cd8 87 reswitch:
13281fa4 88 switch (*s) {
378cc40b
LW
89 case 'a':
90 minus_a = TRUE;
13281fa4 91 s++;
378cc40b 92 goto reswitch;
a687059c
LW
93 case 'd':
94#ifdef TAINT
95 if (euid != uid || egid != gid)
96 fatal("No -d allowed in setuid scripts");
97#endif
98 perldb = TRUE;
99 s++;
100 goto reswitch;
8d063cd8 101 case 'D':
ae986130 102#ifdef DEBUGGING
a687059c
LW
103#ifdef TAINT
104 if (euid != uid || egid != gid)
105 fatal("No -D allowed in setuid scripts");
106#endif
13281fa4 107 debug = atoi(s+1);
ae986130
LW
108#else
109 warn("Recompile perl with -DDEBUGGING to use -D switch\n");
8d063cd8
LW
110#endif
111 break;
8d063cd8 112 case 'e':
a687059c
LW
113#ifdef TAINT
114 if (euid != uid || egid != gid)
115 fatal("No -e allowed in setuid scripts");
116#endif
8d063cd8 117 if (!e_fp) {
a687059c
LW
118 e_tmpname = savestr(TMPPATH);
119 (void)mktemp(e_tmpname);
8d063cd8
LW
120 e_fp = fopen(e_tmpname,"w");
121 }
122 if (argv[1])
123 fputs(argv[1],e_fp);
a687059c 124 (void)putc('\n', e_fp);
8d063cd8
LW
125 argc--,argv++;
126 break;
127 case 'i':
13281fa4 128 inplace = savestr(s+1);
8d063cd8
LW
129 argvoutstab = stabent("ARGVOUT",TRUE);
130 break;
131 case 'I':
a687059c
LW
132#ifdef TAINT
133 if (euid != uid || egid != gid)
134 fatal("No -I allowed in setuid scripts");
135#endif
13281fa4
LW
136 str_cat(str,"-");
137 str_cat(str,s);
8d063cd8 138 str_cat(str," ");
a687059c
LW
139 if (*++s) {
140 (void)apush(stab_array(incstab),str_make(s,0));
378cc40b
LW
141 }
142 else {
a687059c 143 (void)apush(stab_array(incstab),str_make(argv[1],0));
8d063cd8
LW
144 str_cat(str,argv[1]);
145 argc--,argv++;
146 str_cat(str," ");
147 }
148 break;
149 case 'n':
378cc40b 150 minus_n = TRUE;
13281fa4 151 s++;
8d063cd8
LW
152 goto reswitch;
153 case 'p':
378cc40b 154 minus_p = TRUE;
13281fa4 155 s++;
8d063cd8
LW
156 goto reswitch;
157 case 'P':
a687059c
LW
158#ifdef TAINT
159 if (euid != uid || egid != gid)
160 fatal("No -P allowed in setuid scripts");
161#endif
8d063cd8 162 preprocess = TRUE;
13281fa4 163 s++;
8d063cd8
LW
164 goto reswitch;
165 case 's':
a687059c
LW
166#ifdef TAINT
167 if (euid != uid || egid != gid)
168 fatal("No -s allowed in setuid scripts");
169#endif
8d063cd8 170 doswitches = TRUE;
13281fa4 171 s++;
8d063cd8 172 goto reswitch;
378cc40b
LW
173 case 'S':
174 dosearch = TRUE;
13281fa4 175 s++;
378cc40b 176 goto reswitch;
a687059c
LW
177 case 'u':
178 do_undump = TRUE;
179 s++;
180 goto reswitch;
378cc40b
LW
181 case 'U':
182 unsafe = TRUE;
13281fa4 183 s++;
378cc40b 184 goto reswitch;
8d063cd8 185 case 'v':
a687059c
LW
186 fputs(rcsid,stdout);
187 fputs("\nCopyright (c) 1989, Larry Wall\n\n\
188Perl may be copied only under the terms of the GNU General Public License,\n\
189a copy of which can be found with the Perl 3.0 distribution kit.\n",stdout);
8d063cd8 190 exit(0);
378cc40b
LW
191 case 'w':
192 dowarn = TRUE;
13281fa4 193 s++;
378cc40b 194 goto reswitch;
8d063cd8
LW
195 case '-':
196 argc--,argv++;
197 goto switch_end;
198 case 0:
199 break;
200 default:
13281fa4 201 fatal("Unrecognized switch: -%s",s);
8d063cd8
LW
202 }
203 }
204 switch_end:
205 if (e_fp) {
a687059c 206 (void)fclose(e_fp);
8d063cd8
LW
207 argc++,argv--;
208 argv[0] = e_tmpname;
209 }
378cc40b
LW
210#ifndef PRIVLIB
211#define PRIVLIB "/usr/local/lib/perl"
212#endif
a687059c 213 (void)apush(stab_array(incstab),str_make(PRIVLIB,0));
8d063cd8
LW
214
215 str_set(&str_no,No);
216 str_set(&str_yes,Yes);
8d063cd8
LW
217
218 /* open script */
219
220 if (argv[0] == Nullch)
221 argv[0] = "-";
a687059c 222 if (dosearch && !index(argv[0], '/') && (s = getenv("PATH"))) {
378cc40b 223 char *xfound = Nullch, *xfailed = Nullch;
a687059c 224 int len;
378cc40b 225
a687059c 226 bufend = s + strlen(s);
378cc40b 227 while (*s) {
a687059c 228 s = cpytill(tokenbuf,s,bufend,':',&len);
378cc40b
LW
229 if (*s)
230 s++;
a687059c
LW
231 if (len)
232 (void)strcat(tokenbuf+len,"/");
233 (void)strcat(tokenbuf+len,argv[0]);
378cc40b
LW
234#ifdef DEBUGGING
235 if (debug & 1)
236 fprintf(stderr,"Looking for %s\n",tokenbuf);
237#endif
238 if (stat(tokenbuf,&statbuf) < 0) /* not there? */
239 continue;
240 if ((statbuf.st_mode & S_IFMT) == S_IFREG
a687059c 241 && cando(S_IREAD,TRUE,&statbuf) && cando(S_IEXEC,TRUE,&statbuf)) {
378cc40b
LW
242 xfound = tokenbuf; /* bingo! */
243 break;
244 }
245 if (!xfailed)
246 xfailed = savestr(tokenbuf);
247 }
248 if (!xfound)
a687059c 249 fatal("Can't execute %s", xfailed ? xfailed : argv[0] );
378cc40b 250 if (xfailed)
a687059c 251 Safefree(xfailed);
378cc40b
LW
252 argv[0] = savestr(xfound);
253 }
a687059c
LW
254
255 pidstatary = anew(Nullstab); /* for remembering popen pids, status */
256
8d063cd8 257 filename = savestr(argv[0]);
378cc40b 258 origfilename = savestr(filename);
8d063cd8
LW
259 if (strEQ(filename,"-"))
260 argv[0] = "";
261 if (preprocess) {
378cc40b
LW
262 str_cat(str,"-I");
263 str_cat(str,PRIVLIB);
a687059c 264 (void)sprintf(buf, "\
8d063cd8
LW
265/bin/sed -e '/^[^#]/b' \
266 -e '/^#[ ]*include[ ]/b' \
267 -e '/^#[ ]*define[ ]/b' \
268 -e '/^#[ ]*if[ ]/b' \
269 -e '/^#[ ]*ifdef[ ]/b' \
378cc40b 270 -e '/^#[ ]*ifndef[ ]/b' \
8d063cd8
LW
271 -e '/^#[ ]*else/b' \
272 -e '/^#[ ]*endif/b' \
273 -e 's/^#.*//' \
378cc40b
LW
274 %s | %s -C %s %s",
275 argv[0], CPPSTDIN, str_get(str), CPPMINUS);
a687059c 276#ifdef IAMSUID /* actually, this is caught earlier */
13281fa4 277 if (euid != uid && !euid) /* if running suidperl */
a687059c
LW
278#ifdef SETEUID
279 (void)seteuid(uid); /* musn't stay setuid root */
280#else
281#ifdef SETREUID
282 (void)setreuid(-1, uid);
283#else
284 setuid(uid);
285#endif
13281fa4 286#endif
a687059c
LW
287#endif /* IAMSUID */
288 rsfp = mypopen(buf,"r");
8d063cd8
LW
289 }
290 else if (!*argv[0])
291 rsfp = stdin;
292 else
293 rsfp = fopen(argv[0],"r");
13281fa4 294 if (rsfp == Nullfp) {
a687059c
LW
295 extern char *sys_errlist[];
296 extern int errno;
297
13281fa4 298#ifdef DOSUID
a687059c 299#ifndef IAMSUID /* in case script is not readable before setuid */
13281fa4
LW
300 if (euid && stat(filename,&statbuf) >= 0 &&
301 statbuf.st_mode & (S_ISUID|S_ISGID)) {
a687059c
LW
302 (void)sprintf(buf, "%s/%s", BIN, "suidperl");
303 execv(buf, origargv); /* try again */
13281fa4
LW
304 fatal("Can't do setuid\n");
305 }
306#endif
307#endif
a687059c
LW
308 fatal("Can't open perl script \"%s\": %s\n",
309 filename, sys_errlist[errno]);
13281fa4 310 }
8d063cd8
LW
311 str_free(str); /* free -I directories */
312
13281fa4
LW
313 /* do we need to emulate setuid on scripts? */
314
315 /* This code is for those BSD systems that have setuid #! scripts disabled
316 * in the kernel because of a security problem. Merely defining DOSUID
317 * in perl will not fix that problem, but if you have disabled setuid
318 * scripts in the kernel, this will attempt to emulate setuid and setgid
319 * on scripts that have those now-otherwise-useless bits set. The setuid
320 * root version must be called suidperl. If regular perl discovers that
321 * it has opened a setuid script, it calls suidperl with the same argv
322 * that it had. If suidperl finds that the script it has just opened
323 * is NOT setuid root, it sets the effective uid back to the uid. We
324 * don't just make perl setuid root because that loses the effective
325 * uid we had before invoking perl, if it was different from the uid.
326 *
327 * DOSUID must be defined in both perl and suidperl, and IAMSUID must
328 * be defined in suidperl only. suidperl must be setuid root. The
329 * Configure script will set this up for you if you want it.
a687059c
LW
330 *
331 * There is also the possibility of have a script which is running
332 * set-id due to a C wrapper. We want to do the TAINT checks
333 * on these set-id scripts, but don't want to have the overhead of
334 * them in normal perl, and can't use suidperl because it will lose
335 * the effective uid info, so we have an additional non-setuid root
336 * version called taintperl that just does the TAINT checks.
13281fa4 337 */
a687059c 338
13281fa4
LW
339#ifdef DOSUID
340 if (fstat(fileno(rsfp),&statbuf) < 0) /* normal stat is insecure */
341 fatal("Can't stat script \"%s\"",filename);
342 if (statbuf.st_mode & (S_ISUID|S_ISGID)) {
343 int len;
344
a687059c
LW
345#ifdef IAMSUID
346#ifndef SETREUID
347 /* On this access check to make sure the directories are readable,
348 * there is actually a small window that the user could use to make
349 * filename point to an accessible directory. So there is a faint
350 * chance that someone could execute a setuid script down in a
351 * non-accessible directory. I don't know what to do about that.
352 * But I don't think it's too important. The manual lies when
353 * it says access() is useful in setuid programs.
354 */
13281fa4
LW
355 if (access(filename,1)) /* as a double check */
356 fatal("Permission denied");
a687059c
LW
357#else
358 /* If we can swap euid and uid, then we can determine access rights
359 * with a simple stat of the file, and then compare device and
360 * inode to make sure we did stat() on the same file we opened.
361 * Then we just have to make sure he or she can execute it.
362 */
363 {
364 struct stat tmpstatbuf;
365
366 if (setreuid(euid,uid) < 0 || getuid() != euid || geteuid() != uid)
367 fatal("Can't swap uid and euid"); /* really paranoid */
368 if (stat(filename,&tmpstatbuf) < 0) /* testing full pathname here */
369 fatal("Permission denied");
370 if (tmpstatbuf.st_dev != statbuf.st_dev ||
371 tmpstatbuf.st_ino != statbuf.st_ino) {
372 (void)fclose(rsfp);
373 if (rsfp = mypopen("/bin/mail root","w")) { /* heh, heh */
374 fprintf(rsfp,
375"User %d tried to run dev %d ino %d in place of dev %d ino %d!\n\
376(Filename of set-id script was %s, uid %d gid %d.)\n\nSincerely,\nperl\n",
377 uid,tmpstatbuf.st_dev, tmpstatbuf.st_ino,
378 statbuf.st_dev, statbuf.st_ino,
379 filename, statbuf.st_uid, statbuf.st_gid);
380 (void)mypclose(rsfp);
381 }
382 fatal("Permission denied\n");
383 }
384 if (setreuid(uid,euid) < 0 || getuid() != uid || geteuid() != euid)
385 fatal("Can't reswap uid and euid");
386 if (!cando(S_IEXEC,FALSE,&statbuf)) /* can real uid exec? */
387 fatal("Permission denied\n");
388 }
389#endif /* SETREUID */
390#endif /* IAMSUID */
391
13281fa4
LW
392 if ((statbuf.st_mode & S_IFMT) != S_IFREG)
393 fatal("Permission denied");
a687059c
LW
394 if ((statbuf.st_mode >> 6) & S_IWRITE)
395 fatal("Setuid/gid script is writable by world");
13281fa4
LW
396 doswitches = FALSE; /* -s is insecure in suid */
397 line++;
398 if (fgets(tokenbuf,sizeof tokenbuf, rsfp) == Nullch ||
399 strnNE(tokenbuf,"#!",2) ) /* required even on Sys V */
400 fatal("No #! line");
401 for (s = tokenbuf+2; !isspace(*s); s++) ;
402 if (strnNE(s-4,"perl",4)) /* sanity check */
403 fatal("Not a perl script");
a687059c 404 while (*s == ' ' || *s == '\t') s++;
13281fa4
LW
405 /*
406 * #! arg must be what we saw above. They can invoke it by
407 * mentioning suidperl explicitly, but they may not add any strange
408 * arguments beyond what #! says if they do invoke suidperl that way.
409 */
410 len = strlen(validarg);
411 if (strEQ(validarg," PHOOEY ") ||
412 strnNE(s,validarg,len) || !isspace(s[len]))
a687059c
LW
413 fatal("Args must match #! line");
414
415#ifndef IAMSUID
416 if (euid != uid && (statbuf.st_mode & S_ISUID) &&
417 euid == statbuf.st_uid)
418 if (!do_undump)
419 fatal("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
420FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
421#endif /* IAMSUID */
13281fa4
LW
422
423 if (euid) { /* oops, we're not the setuid root perl */
a687059c 424 (void)fclose(rsfp);
13281fa4 425#ifndef IAMSUID
a687059c
LW
426 (void)sprintf(buf, "%s/%s", BIN, "suidperl");
427 execv(buf, origargv); /* try again */
13281fa4
LW
428#endif
429 fatal("Can't do setuid\n");
430 }
431
ffed7fef 432 if (statbuf.st_mode & S_ISGID && statbuf.st_gid != egid)
a687059c
LW
433#ifdef SETEGID
434 (void)setegid(statbuf.st_gid);
435#else
436#ifdef SETREGID
437 (void)setregid((GIDTYPE)-1,statbuf.st_gid);
438#else
439 setgid(statbuf.st_gid);
440#endif
441#endif
442 if (statbuf.st_mode & S_ISUID) {
443 if (statbuf.st_uid != euid)
444#ifdef SETEUID
445 (void)seteuid(statbuf.st_uid); /* all that for this */
446#else
447#ifdef SETREUID
448 (void)setreuid((UIDTYPE)-1,statbuf.st_uid);
449#else
450 setuid(statbuf.st_uid);
451#endif
452#endif
453 }
454 else if (uid) /* oops, mustn't run as root */
455#ifdef SETEUID
456 (void)seteuid((UIDTYPE)uid);
457#else
458#ifdef SETREUID
459 (void)setreuid((UIDTYPE)-1,(UIDTYPE)uid);
460#else
461 setuid((UIDTYPE)uid);
462#endif
463#endif
ffed7fef 464 uid = (int)getuid();
13281fa4 465 euid = (int)geteuid();
ffed7fef
LW
466 gid = (int)getgid();
467 egid = (int)getegid();
a687059c 468 if (!cando(S_IEXEC,TRUE,&statbuf))
13281fa4
LW
469 fatal("Permission denied\n"); /* they can't do this */
470 }
471#ifdef IAMSUID
472 else if (preprocess)
473 fatal("-P not allowed for setuid/setgid script\n");
474 else
475 fatal("Script is not setuid/setgid in suidperl\n");
a687059c
LW
476#else
477#ifndef TAINT /* we aren't taintperl or suidperl */
478 /* script has a wrapper--can't run suidperl or we lose euid */
479 else if (euid != uid || egid != gid) {
480 (void)fclose(rsfp);
481 (void)sprintf(buf, "%s/%s", BIN, "taintperl");
482 execv(buf, origargv); /* try again */
483 fatal("Can't run setuid script with taint checks");
484 }
485#endif /* TAINT */
13281fa4 486#endif /* IAMSUID */
a687059c
LW
487#else /* !DOSUID */
488#ifndef TAINT /* we aren't taintperl or suidperl */
489 if (euid != uid || egid != gid) { /* (suidperl doesn't exist, in fact) */
490#ifndef SETUID_SCRIPTS_ARE_SECURE_NOW
491 fstat(fileno(rsfp),&statbuf); /* may be either wrapped or real suid */
492 if ((euid != uid && euid == statbuf.st_uid && statbuf.st_mode & S_ISUID)
493 ||
494 (egid != gid && egid == statbuf.st_gid && statbuf.st_mode & S_ISGID)
495 )
496 if (!do_undump)
497 fatal("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
498FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
499#endif /* SETUID_SCRIPTS_ARE_SECURE_NOW */
500 /* not set-id, must be wrapped */
501 (void)fclose(rsfp);
502 (void)sprintf(buf, "%s/%s", BIN, "taintperl");
503 execv(buf, origargv); /* try again */
504 fatal("Can't run setuid script with taint checks");
505 }
506#endif /* TAINT */
13281fa4
LW
507#endif /* DOSUID */
508
8d063cd8
LW
509 defstab = stabent("_",TRUE);
510
a687059c
LW
511 if (perldb) {
512 debstash = hnew(0);
513 stab_xhash(stabent("_DB",TRUE)) = debstash;
514 curstash = debstash;
515 lineary = stab_xarray(aadd((tmpstab = stabent("line",TRUE))));
516 tmpstab->str_pok |= SP_MULTI;
517 subname = str_make("main",4);
518 DBstab = stabent("DB",TRUE);
519 DBstab->str_pok |= SP_MULTI;
520 DBsub = hadd(tmpstab = stabent("sub",TRUE));
521 tmpstab->str_pok |= SP_MULTI;
522 DBsingle = stab_val((tmpstab = stabent("single",TRUE)));
523 tmpstab->str_pok |= SP_MULTI;
524 curstash = defstash;
525 }
526
8d063cd8
LW
527 /* init tokener */
528
a687059c
LW
529 bufend = bufptr = str_get(linestr);
530
531 savestack = anew(Nullstab); /* for saving non-local values */
532 stack = anew(Nullstab); /* for saving non-local values */
533 stack->ary_flags = 0; /* not a real array */
8d063cd8 534
a687059c 535 /* now parse the script */
8d063cd8 536
a687059c
LW
537 error_count = 0;
538 if (yyparse() || error_count)
8d063cd8
LW
539 fatal("Execution aborted due to compilation errors.\n");
540
a687059c 541 New(50,loop_stack,128,struct loop);
ae986130
LW
542#ifdef DEBUGGING
543 if (debug) {
544 New(51,debname,128,char);
545 New(52,debdelim,128,char);
546 }
547#endif
a687059c 548 curstash = defstash;
378cc40b
LW
549
550 preprocess = FALSE;
8d063cd8
LW
551 if (e_fp) {
552 e_fp = Nullfp;
a687059c
LW
553 (void)UNLINK(e_tmpname);
554 }
555
556 /* initialize everything that won't change if we undump */
557
558 if (sigstab = stabent("SIG",allstabs)) {
559 sigstab->str_pok |= SP_MULTI;
560 (void)hadd(sigstab);
561 }
562
563 magicalize("!#?^~=-%0123456789.+&*()<>,\\/[|`':");
564
565 amperstab = stabent("&",allstabs);
566 leftstab = stabent("`",allstabs);
567 rightstab = stabent("'",allstabs);
568 sawampersand = (amperstab || leftstab || rightstab);
569 if (tmpstab = stabent(":",allstabs))
570 str_set(STAB_STR(tmpstab),chopset);
571
572 /* these aren't necessarily magical */
573 if (tmpstab = stabent(";",allstabs))
574 str_set(STAB_STR(tmpstab),"\034");
575#ifdef TAINT
576 tainted = 1;
577#endif
578 if (tmpstab = stabent("0",allstabs))
579 str_set(STAB_STR(tmpstab),origfilename);
580#ifdef TAINT
581 tainted = 0;
582#endif
583 if (tmpstab = stabent("]",allstabs))
584 str_set(STAB_STR(tmpstab),rcsid);
585 str_nset(stab_val(stabent("\"", TRUE)), " ", 1);
586
587 stdinstab = stabent("STDIN",TRUE);
588 stdinstab->str_pok |= SP_MULTI;
589 stab_io(stdinstab) = stio_new();
590 stab_io(stdinstab)->ifp = stdin;
591 tmpstab = stabent("stdin",TRUE);
592 stab_io(tmpstab) = stab_io(stdinstab);
593 tmpstab->str_pok |= SP_MULTI;
594
595 tmpstab = stabent("STDOUT",TRUE);
596 tmpstab->str_pok |= SP_MULTI;
597 stab_io(tmpstab) = stio_new();
598 stab_io(tmpstab)->ofp = stab_io(tmpstab)->ifp = stdout;
599 defoutstab = tmpstab;
600 tmpstab = stabent("stdout",TRUE);
601 stab_io(tmpstab) = stab_io(defoutstab);
602 tmpstab->str_pok |= SP_MULTI;
603
604 curoutstab = stabent("STDERR",TRUE);
605 curoutstab->str_pok |= SP_MULTI;
606 stab_io(curoutstab) = stio_new();
607 stab_io(curoutstab)->ofp = stab_io(curoutstab)->ifp = stderr;
608 tmpstab = stabent("stderr",TRUE);
609 stab_io(tmpstab) = stab_io(curoutstab);
610 tmpstab->str_pok |= SP_MULTI;
611 curoutstab = defoutstab; /* switch back to STDOUT */
612
613 statname = Str_new(66,0); /* last filename we did stat on */
614
615 perldb = FALSE; /* don't try to instrument evals */
616
617 if (dowarn) {
618 stab_check('A','Z');
619 stab_check('a','z');
8d063cd8 620 }
a687059c
LW
621
622 if (do_undump)
623 abort();
624
625 just_doit: /* come here if running an undumped a.out */
8d063cd8
LW
626 argc--,argv++; /* skip name of script */
627 if (doswitches) {
628 for (; argc > 0 && **argv == '-'; argc--,argv++) {
629 if (argv[0][1] == '-') {
630 argc--,argv++;
631 break;
632 }
a687059c 633 str_numset(stab_val(stabent(argv[0]+1,TRUE)),(double)1.0);
8d063cd8
LW
634 }
635 }
a687059c
LW
636#ifdef TAINT
637 tainted = 1;
638#endif
a559c259 639 if (argvstab = stabent("ARGV",allstabs)) {
a687059c
LW
640 argvstab->str_pok |= SP_MULTI;
641 (void)aadd(argvstab);
8d063cd8 642 for (; argc > 0; argc--,argv++) {
a687059c 643 (void)apush(stab_array(argvstab),str_make(argv[0],0));
8d063cd8
LW
644 }
645 }
a687059c
LW
646#ifdef TAINT
647 (void) stabent("ENV",TRUE); /* must test PATH and IFS */
648#endif
a559c259 649 if (envstab = stabent("ENV",allstabs)) {
a687059c
LW
650 envstab->str_pok |= SP_MULTI;
651 (void)hadd(envstab);
8d063cd8
LW
652 for (; *env; env++) {
653 if (!(s = index(*env,'=')))
654 continue;
655 *s++ = '\0';
a687059c
LW
656 str = str_make(s--,0);
657 str_magic(str, envstab, 'E', *env, s - *env);
658 (void)hstore(stab_hash(envstab), *env, s - *env, str, 0);
659 *s = '=';
8d063cd8
LW
660 }
661 }
a687059c
LW
662#ifdef TAINT
663 tainted = 0;
664#endif
378cc40b 665 if (tmpstab = stabent("$",allstabs))
8d063cd8
LW
666 str_numset(STAB_STR(tmpstab),(double)getpid());
667
a687059c
LW
668 if (setjmp(top_env)) /* sets goto_targ on longjump */
669 loop_ptr = 0; /* start label stack again */
8d063cd8
LW
670
671#ifdef DEBUGGING
672 if (debug & 1024)
a687059c 673 dump_all();
8d063cd8
LW
674 if (debug)
675 fprintf(stderr,"\nEXECUTING...\n\n");
676#endif
677
678 /* do it */
679
a687059c 680 (void) cmd_exec(main_root,G_SCALAR,-1);
8d063cd8
LW
681
682 if (goto_targ)
378cc40b 683 fatal("Can't find label \"%s\"--aborting",goto_targ);
8d063cd8 684 exit(0);
378cc40b 685 /* NOTREACHED */
8d063cd8
LW
686}
687
688magicalize(list)
689register char *list;
690{
691 register STAB *stab;
692 char sym[2];
693
694 sym[1] = '\0';
695 while (*sym = *list++) {
a559c259 696 if (stab = stabent(sym,allstabs)) {
a687059c
LW
697 stab_flags(stab) = SF_VMAGIC;
698 str_magic(stab_val(stab), stab, 0, Nullch, 0);
378cc40b 699 }
378cc40b 700 }
8d063cd8
LW
701}
702
a687059c 703/* this routine is in perly.c by virtue of being sort of an alternate main() */
8d063cd8 704
a687059c
LW
705int
706do_eval(str,optype,stash,gimme,arglast)
707STR *str;
708int optype;
709HASH *stash;
710int gimme;
711int *arglast;
8d063cd8 712{
a687059c
LW
713 STR **st = stack->ary_array;
714 int retval;
715 CMD *myroot;
716 ARRAY *ar;
717 int i;
718 char *oldfile = filename;
719 line_t oldline = line;
720 int oldtmps_base = tmps_base;
721 int oldsave = savestack->ary_fill;
722 SPAT *oldspat = curspat;
723 static char *last_eval = Nullch;
724 static CMD *last_root = Nullcmd;
725 int sp = arglast[0];
8d063cd8 726
a687059c
LW
727 tmps_base = tmps_max;
728 if (curstash != stash) {
729 (void)savehptr(&curstash);
730 curstash = stash;
8d063cd8 731 }
a687059c
LW
732 str_set(stab_val(stabent("@",TRUE)),"");
733 if (optype != O_DOFILE) { /* normal eval */
734 filename = "(eval)";
735 line = 1;
736 str_sset(linestr,str);
737 str_cat(linestr,";"); /* be kind to them */
8d063cd8 738 }
a687059c
LW
739 else {
740 if (last_root) {
741 Safefree(last_eval);
742 cmd_free(last_root);
743 last_root = Nullcmd;
8d063cd8 744 }
a687059c
LW
745 filename = savestr(str_get(str)); /* can't free this easily */
746 str_set(linestr,"");
747 rsfp = fopen(filename,"r");
748 ar = stab_array(incstab);
749 if (!rsfp && *filename != '/') {
750 for (i = 0; i <= ar->ary_fill; i++) {
751 (void)sprintf(buf,"%s/%s",str_get(afetch(ar,i,TRUE)),filename);
752 rsfp = fopen(buf,"r");
753 if (rsfp) {
754 filename = savestr(buf);
8d063cd8
LW
755 break;
756 }
378cc40b
LW
757 }
758 }
a687059c
LW
759 if (!rsfp) {
760 filename = oldfile;
761 tmps_base = oldtmps_base;
762 if (gimme != G_ARRAY)
763 st[++sp] = &str_undef;
764 return sp;
8d063cd8 765 }
a687059c 766 line = 0;
8d063cd8 767 }
a687059c
LW
768 in_eval++;
769 oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
770 bufend = bufptr + linestr->str_cur;
771 if (setjmp(eval_env)) {
772 retval = 1;
773 last_root = Nullcmd;
8d063cd8 774 }
a687059c
LW
775 else {
776 error_count = 0;
777 if (rsfp)
778 retval = yyparse();
779 else if (last_root && *bufptr == *last_eval && strEQ(bufptr,last_eval)){
780 retval = 0;
781 eval_root = last_root; /* no point in reparsing */
782 }
783 else if (in_eval == 1) {
784 if (last_root) {
785 Safefree(last_eval);
786 cmd_free(last_root);
8d063cd8 787 }
a687059c
LW
788 last_eval = savestr(bufptr);
789 last_root = Nullcmd;
790 retval = yyparse();
791 if (!retval)
792 last_root = eval_root;
8d063cd8 793 }
a687059c
LW
794 else
795 retval = yyparse();
8d063cd8 796 }
a687059c
LW
797 myroot = eval_root; /* in case cmd_exec does another eval! */
798 if (retval || error_count) {
799 str = &str_undef;
800 last_root = Nullcmd; /* can't free on error, for some reason */
801 if (rsfp) {
802 fclose(rsfp);
803 rsfp = 0;
804 }
8d063cd8 805 }
8d063cd8 806 else {
a687059c
LW
807 sp = cmd_exec(eval_root,gimme,sp);
808 st = stack->ary_array;
809 for (i = arglast[0] + 1; i <= sp; i++)
810 st[i] = str_static(st[i]);
811 /* if we don't save result, free zaps it */
812 if (in_eval != 1 && myroot != last_root)
813 cmd_free(myroot);
a559c259
LW
814 }
815 in_eval--;
378cc40b
LW
816 filename = oldfile;
817 line = oldline;
818 tmps_base = oldtmps_base;
a687059c 819 curspat = oldspat;
378cc40b
LW
820 if (savestack->ary_fill > oldsave) /* let them use local() */
821 restorelist(oldsave);
a687059c 822 return sp;
378cc40b 823}